Merge latest green changeset from mozilla-central to maple
authorBenoit Girard <b56girard@gmail.com>
Mon, 05 Mar 2012 13:41:15 -0500
changeset 92607 7c9f942b9becdb29912997dcda0bfe53d78b6451
parent 92606 17c65d32c7b891e70435561b965b71c355bd28ac (current diff)
parent 91105 433cfbd2a0da3f9cc7c1391f95a28404966c6466 (diff)
child 92608 f99d62aca00a57893150b7d63eeacfbd72338780
push idunknown
push userunknown
push dateunknown
milestone13.0a1
Merge latest green changeset from mozilla-central to maple
configure.in
content/base/public/Element.h
content/base/public/nsIContent.h
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/src/nsCommentNode.cpp
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsMappedAttributeElement.h
content/base/src/nsStyledElement.h
content/base/src/nsTextFragment.h
content/base/src/nsTextNode.h
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsGenericHTMLFrameElement.cpp
content/html/content/src/nsGenericHTMLFrameElement.h
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLDivElement.cpp
content/html/content/src/nsHTMLSpanElement.cpp
content/xml/content/src/nsXMLCDATASection.cpp
dom/base/nsDOMMemoryReporter.cpp
dom/base/nsDOMMemoryReporter.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowMemoryReporter.h
dom/interfaces/range/nsIDOMRangeException.idl
dom/plugins/base/nsJSNPRuntime.cpp
dom/plugins/base/nsNPAPIPlugin.h
dom/tests/mochitest/bugs/iframe_bug407839-1.html
dom/tests/mochitest/bugs/iframe_bug407839-2.html
dom/tests/mochitest/bugs/iframe_bug409349.html
dom/tests/mochitest/bugs/iframe_bug424093.html
dom/tests/mochitest/bugs/iframe_bug463000.html
dom/tests/mochitest/bugs/test_bug407839.html
dom/tests/mochitest/bugs/test_bug409349.html
dom/tests/mochitest/bugs/test_bug424093.html
dom/tests/mochitest/bugs/test_bug463000.html
dom/tests/mochitest/chrome/domstorage_global.js
dom/tests/mochitest/chrome/domstorage_global.xul
dom/tests/mochitest/chrome/test_domstorage.xul
dom/tests/mochitest/globalstorage/Makefile.in
dom/tests/mochitest/globalstorage/iframe_bug614116-1.html
dom/tests/mochitest/globalstorage/iframe_bug614116-2.html
dom/tests/mochitest/globalstorage/test_bug614116.html
dom/tests/mochitest/storageevent/frameGlobalStorageMaster.html
dom/tests/mochitest/storageevent/frameGlobalStorageSlaveEqual.html
dom/tests/mochitest/storageevent/frameGlobalStorageSlaveNotEqual.html
dom/tests/mochitest/storageevent/test_storageGlobalStorageEventCheckNoPropagation.html
dom/tests/mochitest/storageevent/test_storageGlobalStorageEventCheckPropagation.html
gfx/angle/angle-limit-identifiers-to-250-chars.patch
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
image/src/imgLoader.cpp
js/src/jsanalyze.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jspubtd.h
js/src/jsstr.cpp
js/src/shell/js.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresShell.cpp
layout/build/nsLayoutStatics.cpp
mobile/android/config/mozconfigs/linux-desktop/l10n-mozconfig
mobile/android/config/mozconfigs/linux-desktop/nightly
mobile/android/config/mozconfigs/macosx-desktop/l10n-mozconfig
mobile/android/config/mozconfigs/macosx-desktop/nightly
mobile/android/config/mozconfigs/win32-desktop/l10n-mozconfig
mobile/android/config/mozconfigs/win32-desktop/nightly
mobile/xul/config/mozconfigs/linux-desktop/l10n-mozconfig
mobile/xul/config/mozconfigs/linux-desktop/nightly
mobile/xul/config/mozconfigs/macosx-desktop/l10n-mozconfig
mobile/xul/config/mozconfigs/macosx-desktop/nightly
mobile/xul/config/mozconfigs/win32-desktop/l10n-mozconfig
mobile/xul/config/mozconfigs/win32-desktop/nightly
modules/libpref/src/init/all.js
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1492,31 +1492,26 @@ nsHTMLTableAccessible::IsProbablyForLayo
 
   /**
    * Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
    */
 
   // Check for styled background color across rows (alternating background
   // color is a common feature for data tables).
   PRUint32 childCount = GetChildCount();
-  nsAutoString rowColor, prevRowColor;
+  nscolor rowColor, prevRowColor;
   for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
     nsAccessible* child = GetChildAt(childIdx);
     if (child->Role() == roles::ROW) {
-      nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
-        nsCoreUtils::GetComputedStyleDeclaration(EmptyString(),
-                                                 child->GetContent());
-      if (styleDecl) {
-        prevRowColor = rowColor;
-        styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"),
-                                    rowColor);
-        if (childIdx > 0 && !prevRowColor.Equals(rowColor)) {
-          RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
-        }
-      }
+      prevRowColor = rowColor;
+      nsIFrame* rowFrame = child->GetFrame();
+      rowColor = rowFrame->GetStyleBackground()->mBackgroundColor;
+
+      if (childIdx > 0 && prevRowColor != rowColor)
+        RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
     }
   }
 
   // Check for many rows
   const PRInt32 kMaxLayoutRows = 20;
   if (rows > kMaxLayoutRows) { // A ton of rows, this is probably for data
     RETURN_LAYOUT_ANSWER(false, ">= kMaxLayoutRows (20) and non-bordered");
   }
--- a/accessible/src/msaa/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsApplicationAccessibleWrap.cpp
@@ -37,23 +37,50 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsApplicationAccessibleWrap.h"
 
 #include "AccessibleApplication_i.c"
 
+#include "nsIGfxInfo.h"
+#include "nsIPersistentProperties2.h"
 #include "nsServiceManagerUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessibleWrap,
                              nsApplicationAccessible)
 
+NS_IMETHODIMP
+nsApplicationAccessibleWrap::GetAttributes(nsIPersistentProperties** aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  *aAttributes = nsnull;
+
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  NS_ENSURE_STATE(attributes);
+
+  nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
+  if (gfxInfo) {
+    bool isD2DEnabled = false;
+    gfxInfo->GetD2DEnabled(&isD2DEnabled);
+    nsAutoString unused;
+    attributes->SetStringProperty(
+      NS_LITERAL_CSTRING("D2D"),
+      isD2DEnabled ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"),
+        unused);
+  }
+
+  attributes.swap(*aAttributes);
+  return NS_OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // IUnknown
 
 STDMETHODIMP
 nsApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
   *ppv = NULL;
 
--- a/accessible/src/msaa/nsApplicationAccessibleWrap.h
+++ b/accessible/src/msaa/nsApplicationAccessibleWrap.h
@@ -47,16 +47,19 @@
 
 class nsApplicationAccessibleWrap: public nsApplicationAccessible,
                                    public IAccessibleApplication
 {
 public:
   // nsISupporst
   NS_DECL_ISUPPORTS_INHERITED
 
+  // nsIAccessible
+  NS_IMETHOD GetAttributes(nsIPersistentProperties** aAttributes);
+
   // IUnknown
   STDMETHODIMP QueryInterface(REFIID, void**);
 
   // IAccessibleApplication
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_appName(
             /* [retval][out] */ BSTR *name);
 
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_appVersion(
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -91,16 +91,25 @@ https://bugzilla.mozilla.org/show_bug.cg
       // html
       testAttrs("radio", {"checkable" : "true"}, true); 
       testAttrs("checkbox", {"checkable" : "true"}, true); 
       testAttrs("draggable", {"draggable" : "true"}, true);
       testAttrs("th1", { "abbr": "SS#" }, true);
       testAttrs("th2", { "abbr": "SS#" }, true);
       testAttrs("th2", { "axis": "social" }, true);
 
+      // application accessible
+      if (WIN) {
+        var gfxInfo = Components.classes["@mozilla.org/gfx/info;1"].
+          getService(Components.interfaces.nsIGfxInfo);
+        var attrs = {
+          "D2D": (gfxInfo.D2DEnabled ? "true" : "false")
+        }
+        testAttrs(getApplicationAccessible(), attrs, false);
+      }
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -48,16 +48,17 @@ include $(topsrcdir)/config/rules.mk
 _TEST_FILES =\
 		test_ariadialog.html \
 		test_canvas.html \
 		test_colorpicker.xul \
 		test_cssoverflow.html \
 		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
+		test_hidden.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_menu.xul \
 		test_menubutton.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_hidden.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>@hidden attribute testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Set @hidden attribute
+     */
+    function setHiddenAttr(aContainerID, aChildID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function setHiddenAttr_invoke()
+      {
+        var tree =
+          { SECTION: [
+              { ENTRY: [
+              ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aChildID).setAttribute("hidden", "true");
+      }
+
+      this.finalCheck = function setHiddenAttr_finalCheck()
+      {
+        var tree =
+          { SECTION: [
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function setHiddenAttr_getID()
+      {
+        return "Set @hidden attribute on input and test accessible tree for div";
+      }
+    }
+
+    /**
+     * Remove @hidden attribute
+     */
+    function removeHiddenAttr(aContainerID, aChildID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function removeHiddenAttr_invoke()
+      {
+        var tree =
+          { SECTION: [
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aChildID).removeAttribute("hidden");
+      }
+
+      this.finalCheck = function removeHiddenAttr_finalCheck()
+      {
+        var tree =
+          { SECTION: [
+              { ENTRY: [
+              ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function removeHiddenAttr_getID()
+      {
+        return "Remove @hidden attribute on input and test accessible tree for div";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+    ////////////////////////////////////////////////////////////////////////////
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new setHiddenAttr("container", "child"));
+      gQueue.push(new removeHiddenAttr("container", "child"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+
+  </script>
+
+</head>
+
+<body>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="container"><input id="child"></div>
+
+  <div id="eventdump"></div>
+
+</body>
+
+</html>
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,19 +1,23 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1330033499000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1330367012000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i71" id="youtube@2youtube.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
                         <versionRange  minVersion=" " severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i43" id="supportaccessplugin@gmail.com">
                         </emItem>
       <emItem  blockID="i38" id="{B7082FAA-CB62-4872-9106-E42DD88EDE45}">
                         <versionRange  minVersion="0.1" maxVersion="3.3.0.*">
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -60,17 +60,17 @@
         </children>
         <xul:hbox anonid="textbox-input-box"
                   class="textbox-input-box urlbar-input-box"
                   flex="1" xbl:inherits="tooltiptext=inputtooltiptext">
           <children/>
           <html:input anonid="input"
                       class="autocomplete-textbox urlbar-input textbox-input uri-element-right-align"
                       allowevents="true"
-                      xbl:inherits="tooltiptext=inputtooltiptext,onfocus,onblur,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
+                      xbl:inherits="tooltiptext=inputtooltiptext,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
         </xul:hbox>
         <children includes="hbox"/>
       </xul:hbox>
       <xul:dropmarker anonid="historydropmarker"
                       class="autocomplete-history-dropmarker urlbar-history-dropmarker"
                       allowevents="true"
                       xbl:inherits="open,enablehistory,parentfocused=focused"/>
       <xul:popupset anonid="popupset"
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -193,30 +193,35 @@ PlacesTreeView.prototype = {
   /**
    * Given a row, finds and returns the parent details of the associated node.
    *
    * @param aChildRow
    *        Row number.
    * @return [parentNode, parentRow]
    */
   _getParentByChildRow: function PTV__getParentByChildRow(aChildRow) {
-    let parent = this._getNodeForRow(aChildRow).parent;
+    let node = this._getNodeForRow(aChildRow);
+    let parent = (node === null) ? this._rootNode : node.parent;
 
     // The root node is never visible
     if (parent == this._rootNode)
       return [this._rootNode, -1];
 
     let parentRow = this._rows.lastIndexOf(parent, aChildRow - 1);
     return [parent, parentRow];
   },
 
   /**
    * Gets the node at a given row.
    */
   _getNodeForRow: function PTV__getNodeForRow(aRow) {
+    if (aRow < 0) {
+      return null;
+    }
+  
     let node = this._rows[aRow];
     if (node !== undefined)
       return node;
 
     // Find the nearest node.
     let rowNode, row;
     for (let i = aRow - 1; i >= 0 && rowNode === undefined; i--) {
       rowNode = this._rows[i];
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -384,16 +384,17 @@
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
 @BINPATH@/components/SmsDatabaseService.manifest
 @BINPATH@/components/SmsDatabaseService.js
 @BINPATH@/components/nsWifiWorker.js
 @BINPATH@/components/nsWifiWorker.manifest
 #endif
 @BINPATH@/components/BrowserProfileMigrators.manifest
+@BINPATH@/components/ProfileMigrator.js
 @BINPATH@/components/ChromeProfileMigrator.js
 @BINPATH@/components/FirefoxProfileMigrator.js
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts.dylib
 #endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
 #endif
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -454,17 +454,17 @@ def wrapCommand(cmd):
   return cmd
 
 class ShutdownLeakLogger(object):
   """
   Parses the mochitest run log when running a debug build, assigns all leaked
   DOM windows (that are still around after test suite shutdown, despite running
   the GC) to the tests that created them and prints leak statistics.
   """
-  MAX_LEAK_COUNT = 120
+  MAX_LEAK_COUNT = 130
 
   def __init__(self, logger):
     self.logger = logger
     self.tests = []
     self.leakedWindows = {}
     self.leakedDocShells = set()
     self.currentTest = None
     self.seenShutdown = False
@@ -474,17 +474,17 @@ class ShutdownLeakLogger(object):
       self._logWindow(line)
     elif line[2:10] == "DOCSHELL":
       self._logDocShell(line)
     elif line.startswith("TEST-START"):
       fileName = line.split(" ")[-1].strip().replace("chrome://mochitests/content/browser/", "")
       self.currentTest = {"fileName": fileName, "windows": set(), "docShells": set()}
     elif line.startswith("INFO TEST-END"):
       # don't track a test if no windows or docShells leaked
-      if self.currentTest["windows"] and self.currentTest["docShells"]:
+      if self.currentTest["windows"] or self.currentTest["docShells"]:
         self.tests.append(self.currentTest)
       self.currentTest = None
     elif line.startswith("INFO TEST-START | Shutdown"):
       self.seenShutdown = True
 
   def parse(self):
     leakingTests = self._parseLeakingTests()
 
--- a/build/stdc++compat.cpp
+++ b/build/stdc++compat.cpp
@@ -52,16 +52,18 @@
 #define GLIBCXX_VERSION(a, b, c) (((a) << 16) | ((b) << 8) | (c))
 
 namespace std {
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 9)
     /* Instantiate these templates to avoid GLIBCXX_3.4.9 symbol versions */
     template ostream& ostream::_M_insert(double);
     template ostream& ostream::_M_insert(long);
     template ostream& ostream::_M_insert(unsigned long);
+    template ostream& ostream::_M_insert(long long);
+    template ostream& ostream::_M_insert(unsigned long long);
 #ifdef DEBUG
     template ostream& ostream::_M_insert(const void*);
 #endif
     template ostream& __ostream_insert(ostream&, const char*, streamsize);
     template istream& istream::_M_extract(double&);
 #endif
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 14)
     /* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions
--- a/configure.in
+++ b/configure.in
@@ -103,17 +103,17 @@ dnl ====================================
 _SUBDIR_HOST_CFLAGS="$HOST_CFLAGS"
 _SUBDIR_HOST_CXXFLAGS="$HOST_CXXFLAGS"
 _SUBDIR_HOST_LDFLAGS="$HOST_LDFLAGS"
 _SUBDIR_CONFIG_ARGS="$ac_configure_args"
 
 dnl Set the version number of the libs included with mozilla
 dnl ========================================================
 MOZJPEG=62
-MOZPNG=10401
+MOZPNG=10509
 MOZZLIB=0x1230
 NSPR_VERSION=4
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 PERL_VERSION=5.006
@@ -7303,17 +7303,21 @@ if test "$MOZ_DMD"; then
     MOZ_MEMORY=
 fi
 
 if test "${OS_TARGET}" = "Android"; then
   dnl On Android, we use WRAP_LDFLAGS to link everything to mozglue
   :
 elif test "${OS_TARGET}" = "WINNT" -o "${OS_TARGET}" = "Darwin" -o "${OS_TARGET}" = "OS2"; then
   dnl On Windows, OSX and OS2, we want to link all our binaries against mozglue
-  MOZ_GLUE_LDFLAGS='$(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
+  if test -z "$GNU_CC"; then
+    MOZ_GLUE_LDFLAGS='$(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
+  else
+    MOZ_GLUE_LDFLAGS='-L$(LIBXUL_DIST)/lib $(call EXPAND_LIBNAME,mozglue)'
+  fi
 else
   dnl On other Unix systems, we only want to link executables against mozglue
   MOZ_GLUE_PROGRAM_LDFLAGS='$(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib) $(MKSHLIB_UNFORCE_ALL)'
   if test -n "$GNU_CC"; then
     dnl And we need mozglue symbols to be exported.
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS -rdynamic"
   fi
   if test "$MOZ_LINKER" = 1; then
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -37,17 +37,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_Element_h__
 #define mozilla_dom_Element_h__
 
 #include "nsIContent.h"
 #include "nsEventStates.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsEventStateManager;
 class nsGlobalWindow;
 class nsFocusManager;
 
 // Element-specific flags
 enum {
   // Set if the element has a pending style change.
--- a/content/base/public/nsDeprecatedOperationList.h
+++ b/content/base/public/nsDeprecatedOperationList.h
@@ -68,11 +68,10 @@ DEPRECATED_OPERATION(CloneNode)
 DEPRECATED_OPERATION(OwnerDocument)
 DEPRECATED_OPERATION(Normalize)
 DEPRECATED_OPERATION(IsSupported)
 DEPRECATED_OPERATION(IsEqualNode)
 DEPRECATED_OPERATION(TextContent)
 DEPRECATED_OPERATION(EnablePrivilege)
 DEPRECATED_OPERATION(Position)
 DEPRECATED_OPERATION(TotalSize)
-DEPRECATED_OPERATION(GlobalStorage)
 DEPRECATED_OPERATION(InputEncoding)
 DEPRECATED_OPERATION(MozBeforePaint)
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -38,17 +38,16 @@
 #define nsIContent_h___
 
 #include "nsCOMPtr.h" // for already_AddRefed
 #include "nsStringGlue.h"
 #include "nsCaseTreatment.h"
 #include "nsChangeHint.h"
 #include "nsINode.h"
 #include "nsIDocument.h" // for IsInHTMLDocument
-#include "nsDOMMemoryReporter.h"
 
 // Forward declarations
 class nsIAtom;
 class nsIDOMEvent;
 class nsIContent;
 class nsEventListenerManager;
 class nsIURI;
 class nsRuleWalker;
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -63,17 +63,16 @@
 #include "nsPIDOMWindow.h"
 #include "nsSMILAnimationController.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIFrameRequestCallback.h"
 #include "nsEventStates.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIBFCacheEntry.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsIContent;
 class nsPresContext;
 class nsIPresShell;
 class nsIDocShell;
 class nsStyleSet;
 class nsIStyleSheet;
 class nsIStyleRule;
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -44,17 +44,17 @@
 #include "nsTObserverArray.h"
 #include "nsINodeInfo.h"
 #include "nsCOMPtr.h"
 #include "nsWrapperCache.h"
 #include "nsIProgrammingLanguage.h" // for ::JAVASCRIPT
 #include "nsDOMError.h"
 #include "nsDOMString.h"
 #include "jspubtd.h"
-#include "nsDOMMemoryReporter.h"
+#include "nsWindowMemoryReporter.h"
 #include "nsIVariant.h"
 #include "nsGkAtoms.h"
 
 // Including 'windows.h' will #define GetClassInfo to something else.
 #ifdef XP_WIN
 #ifdef GetClassInfo
 #undef GetClassInfo
 #endif
--- a/content/base/public/nsIObjectLoadingContent.idl
+++ b/content/base/public/nsIObjectLoadingContent.idl
@@ -81,17 +81,17 @@ interface nsIObjectLoadingContent : nsIS
   unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
 
   /**
   * Gets the base URI to be used for this object. This differs from
   * nsIContent::GetBaseURI in that it takes codebase attributes into
   * account. The MIME type is required as some plugins (java) calculate
   * this differently.
   */
-  nsIURI GetObjectBaseURI(in ACString aMimeType);
+  nsIURI getObjectBaseURI(in ACString aMimeType);
 
   /**
    * Returns the plugin instance if it has already been instantiated. This
    * will never instantiate the plugin and so is safe to call even when
    * content script must not execute.
    */
   [noscript] readonly attribute nsNPAPIPluginInstancePtr pluginInstance;
 
--- a/content/base/src/nsCommentNode.cpp
+++ b/content/base/src/nsCommentNode.cpp
@@ -40,17 +40,16 @@
  */
 
 #include "nsIDOMComment.h"
 #include "nsGenericDOMDataNode.h"
 
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsGenericElement.h" // DOMCI_NODE_DATA
-#include "nsDOMMemoryReporter.h"
 
 class nsCommentNode : public nsGenericDOMDataNode,
                       public nsIDOMComment
 {
 public:
   nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsCommentNode();
 
--- a/content/base/src/nsDOMSettableTokenList.cpp
+++ b/content/base/src/nsDOMSettableTokenList.cpp
@@ -34,16 +34,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Implementation of nsIDOMDOMSettableTokenList specified by HTML5.
  */
 
 #include "nsDOMSettableTokenList.h"
+#include "dombindings.h"
 
 
 nsDOMSettableTokenList::nsDOMSettableTokenList(nsGenericElement *aElement, nsIAtom* aAttrAtom)
   : nsDOMTokenList(aElement, aAttrAtom)
 {
 }
 
 nsDOMSettableTokenList::~nsDOMSettableTokenList()
@@ -73,8 +74,15 @@ nsDOMSettableTokenList::SetValue(const n
 {
   if (!mElement) {
     return NS_OK;
   }
 
   return mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true);
 }
 
+JSObject*
+nsDOMSettableTokenList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                                   bool *triedToWrap)
+{
+  return mozilla::dom::binding::DOMSettableTokenList::create(cx, scope, this,
+                                                             triedToWrap);
+}
--- a/content/base/src/nsDOMSettableTokenList.h
+++ b/content/base/src/nsDOMSettableTokenList.h
@@ -54,14 +54,17 @@ class nsDOMSettableTokenList : public ns
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDOMSETTABLETOKENLIST
 
   NS_FORWARD_NSIDOMDOMTOKENLIST(nsDOMTokenList::);
 
   nsDOMSettableTokenList(nsGenericElement* aElement, nsIAtom* aAttrAtom);
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
 protected:
   virtual ~nsDOMSettableTokenList();
 };
 
 #endif // nsDOMSettableTokenList_h___
 
--- a/content/base/src/nsDOMTokenList.cpp
+++ b/content/base/src/nsDOMTokenList.cpp
@@ -39,39 +39,53 @@
  */
 
 #include "nsDOMTokenList.h"
 
 #include "nsAttrValue.h"
 #include "nsContentUtils.h"
 #include "nsDOMError.h"
 #include "nsGenericElement.h"
+#include "dombindings.h"
 
 
 nsDOMTokenList::nsDOMTokenList(nsGenericElement *aElement, nsIAtom* aAttrAtom)
   : mElement(aElement),
     mAttrAtom(aAttrAtom)
 {
   // We don't add a reference to our element. If it goes away,
   // we'll be told to drop our reference
+  SetIsProxy();
 }
 
 nsDOMTokenList::~nsDOMTokenList() { }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTokenList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTokenList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTokenList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMTokenList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
 DOMCI_DATA(DOMTokenList, nsDOMTokenList)
 
 NS_INTERFACE_TABLE_HEAD(nsDOMTokenList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_TABLE1(nsDOMTokenList,
                       nsIDOMDOMTokenList)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDOMTokenList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMTokenList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsDOMTokenList)
-NS_IMPL_RELEASE(nsDOMTokenList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTokenList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTokenList)
 
 void
 nsDOMTokenList::DropReference()
 {
   mElement = nsnull;
 }
 
 NS_IMETHODIMP
@@ -288,8 +302,17 @@ nsDOMTokenList::ToString(nsAString& aRes
     aResult.Truncate();
     return NS_OK;
   }
 
   mElement->GetAttr(kNameSpaceID_None, mAttrAtom, aResult);
 
   return NS_OK;
 }
+
+JSObject*
+nsDOMTokenList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                           bool *triedToWrap)
+{
+  return mozilla::dom::binding::DOMTokenList::create(cx, scope, this,
+                                                     triedToWrap);
+}
+
--- a/content/base/src/nsDOMTokenList.h
+++ b/content/base/src/nsDOMTokenList.h
@@ -41,26 +41,36 @@
 #ifndef nsDOMTokenList_h___
 #define nsDOMTokenList_h___
 
 #include "nsGenericElement.h"
 #include "nsIDOMDOMTokenList.h"
 
 class nsAttrValue;
 
-class nsDOMTokenList : public nsIDOMDOMTokenList
+class nsDOMTokenList : public nsIDOMDOMTokenList,
+                       public nsWrapperCache
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
   NS_DECL_NSIDOMDOMTOKENLIST
 
   nsDOMTokenList(nsGenericElement* aElement, nsIAtom* aAttrAtom);
 
   void DropReference();
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsINode *GetParentObject()
+  {
+    return mElement;
+  }
+
 protected:
   ~nsDOMTokenList();
 
   const nsAttrValue* GetParsedAttr() {
     if (!mElement) {
       return nsnull;
     }
     return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -9144,16 +9144,23 @@ nsDocument::GetMozVisibilityState(nsAStr
 }
 
 /* virtual */ void
 nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
 {
   aWindowSizes->mDOM +=
     nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
 
+  if (mPresShell) {
+    mPresShell->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
+                                    &aWindowSizes->mLayoutArenas,
+                                    &aWindowSizes->mLayoutStyleSets,
+                                    &aWindowSizes->mLayoutTextRuns);
+  }
+
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
 void
 nsIDocument::DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -83,16 +83,17 @@
 #include "nsEventDispatcher.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIDocShellHistory.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIXULWindow.h"
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
+#include "nsIMozBrowserFrame.h"
 
 #include "nsLayoutUtils.h"
 #include "nsIView.h"
 #include "nsAsyncDOMEvent.h"
 
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
@@ -975,27 +976,27 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   bool equal;
   nsresult rv =
     ourContent->NodePrincipal()->Equals(otherContent->NodePrincipal(), &equal);
   if (NS_FAILED(rv) || !equal) {
     // Security problems loom.  Just bail on it all
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsCOMPtr<nsIDocShell> ourDochell = GetExistingDocShell();
+  nsCOMPtr<nsIDocShell> ourDocshell = GetExistingDocShell();
   nsCOMPtr<nsIDocShell> otherDocshell = aOther->GetExistingDocShell();
-  if (!ourDochell || !otherDocshell) {
+  if (!ourDocshell || !otherDocshell) {
     // How odd
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // To avoid having to mess with session history, avoid swapping
   // frameloaders that don't correspond to root same-type docshells,
   // unless both roots have session history disabled.
-  nsCOMPtr<nsIDocShellTreeItem> ourTreeItem = do_QueryInterface(ourDochell);
+  nsCOMPtr<nsIDocShellTreeItem> ourTreeItem = do_QueryInterface(ourDocshell);
   nsCOMPtr<nsIDocShellTreeItem> otherTreeItem =
     do_QueryInterface(otherDocshell);
   nsCOMPtr<nsIDocShellTreeItem> ourRootTreeItem, otherRootTreeItem;
   ourTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
   otherTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
   nsCOMPtr<nsIWebNavigation> ourRootWebnav =
     do_QueryInterface(ourRootTreeItem);
   nsCOMPtr<nsIWebNavigation> otherRootWebnav =
@@ -1053,17 +1054,17 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   PRInt32 ourParentType = nsIDocShellTreeItem::typeContent;
   PRInt32 otherParentType = nsIDocShellTreeItem::typeContent;
   ourParentItem->GetItemType(&ourParentType);
   otherParentItem->GetItemType(&otherParentType);
   if (ourParentType != otherParentType) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(ourDochell);
+  nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(ourDocshell);
   nsCOMPtr<nsPIDOMWindow> otherWindow = do_GetInterface(otherDocshell);
 
   nsCOMPtr<nsIDOMElement> ourFrameElement =
     ourWindow->GetFrameElementInternal();
   nsCOMPtr<nsIDOMElement> otherFrameElement =
     otherWindow->GetFrameElementInternal();
 
   nsCOMPtr<nsIDOMEventTarget> ourChromeEventHandler =
@@ -1103,16 +1104,24 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document");
 
   nsIPresShell* ourShell = ourDoc->GetShell();
   nsIPresShell* otherShell = otherDoc->GetShell();
   if (!ourShell || !otherShell) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
+  bool weAreBrowserFrame = false;
+  bool otherIsBrowserFrame = false;
+  ourDocshell->GetIsBrowserFrame(&weAreBrowserFrame);
+  otherDocshell->GetIsBrowserFrame(&otherIsBrowserFrame);
+  if (weAreBrowserFrame != otherIsBrowserFrame) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
   if (mInSwap || aOther->mInSwap) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   mInSwap = aOther->mInSwap = true;
 
   // Fire pageshow events on still-loading pages, and then fire pagehide
   // events.  Note that we do NOT fire these in the normal way, but just fire
   // them on the chrome event handlers.
@@ -1476,16 +1485,23 @@ nsFrameLoader::MaybeCreateDocShell()
       // handler from it and use that for our shell as well.
 
       parentShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
     }
 
     mDocShell->SetChromeEventHandler(chromeEventHandler);
   }
 
+  nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
+  if (browserFrame) {
+    bool isBrowserFrame = false;
+    browserFrame->GetReallyIsBrowser(&isBrowserFrame);
+    mDocShell->SetIsBrowserFrame(isBrowserFrame);
+  }
+
   // This is nasty, this code (the do_GetInterface(mDocShell) below)
   // *must* come *after* the above call to
   // mDocShell->SetChromeEventHandler() for the global window to get
   // the right chrome event handler.
 
   // Tell the window about the frame that hosts it.
   nsCOMPtr<nsIDOMElement> frame_element(do_QueryInterface(mOwnerContent));
   NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -45,17 +45,16 @@
 
 #include "nsIContent.h"
 
 #include "nsTextFragment.h"
 #include "nsDOMError.h"
 #include "nsEventListenerManager.h"
 #include "nsGenericElement.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsDOMMemoryReporter.h"
 
 #include "nsISMILAttr.h"
 
 // This bit is set to indicate that if the text node changes to
 // non-whitespace, we may need to create a frame for it. This bit must
 // not be set on nodes that already have a frame.
 #define NS_CREATE_FRAME_IF_NON_WHITESPACE (1 << NODE_TYPE_SPECIFIC_BITS_OFFSET)
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -147,17 +147,16 @@
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
 #include "prprf.h"
 
 #include "nsSVGFeatures.h"
-#include "nsDOMMemoryReporter.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsCycleCollector.h"
 #include "xpcpublic.h"
 #include "xpcprivate.h"
 #include "nsLayoutStatics.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
@@ -1976,17 +1975,17 @@ nsGenericElement::GetChildrenList()
     slots->mChildrenList = new nsContentList(this, kNameSpaceID_Wildcard, 
                                              nsGkAtoms::_asterix, nsGkAtoms::_asterix,
                                              false);
   }
 
   return slots->mChildrenList;
 }
 
-nsIDOMDOMTokenList*
+nsDOMTokenList*
 nsGenericElement::GetClassList(nsresult *aResult)
 {
   *aResult = NS_ERROR_OUT_OF_MEMORY;
 
   nsGenericElement::nsDOMSlots *slots = DOMSlots();
 
   if (!slots->mClassList) {
     nsCOMPtr<nsIAtom> classAttr = GetClassAttributeName();
@@ -2464,30 +2463,37 @@ nsGenericElement::nsDOMSlots::Traverse(n
 
   if (aIsXUL) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
     cb.NoteXPCOMChild(mControllers);
   }
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
+
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
+  cb.NoteXPCOMChild(mClassList.get());
 }
 
 void
 nsGenericElement::nsDOMSlots::Unlink(bool aIsXUL)
 {
   mStyle = nsnull;
   mSMILOverrideStyle = nsnull;
   if (mAttributeMap) {
     mAttributeMap->DropReference();
     mAttributeMap = nsnull;
   }
   if (aIsXUL)
     NS_IF_RELEASE(mControllers);
   mChildrenList = nsnull;
+  if (mClassList) {
+    mClassList->DropReference();
+    mClassList = nsnull;
+  }
 }
 
 nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : Element(aNodeInfo)
 {
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE ||
                     (mNodeInfo->NodeType() ==
                        nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -592,17 +592,17 @@ public:
   PRInt32 GetClientWidth()
   {
     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().width);
   }
   nsIContent* GetFirstElementChild();
   nsIContent* GetLastElementChild();
   nsIContent* GetPreviousElementSibling();
   nsIContent* GetNextElementSibling();
-  nsIDOMDOMTokenList* GetClassList(nsresult *aResult);
+  nsDOMTokenList* GetClassList(nsresult *aResult);
   bool MozMatchesSelector(const nsAString& aSelector, nsresult* aResult);
 
   /**
    * Get the attr info for the given namespace ID and attribute name.  The
    * namespace ID must not be kNameSpaceID_Unknown and the name must not be
    * null.  Note that this can only return info on attributes that actually
    * live on this element (and is only virtual to handle XUL prototypes).  That
    * is, this should only be called from methods that only care about attrs
--- a/content/base/src/nsMappedAttributeElement.h
+++ b/content/base/src/nsMappedAttributeElement.h
@@ -41,17 +41,16 @@
  * nsMappedAttributeElement is the base for elements supporting style mapped
  * attributes via nsMappedAttributes (HTML and MathML).
  */
 
 #ifndef NS_MAPPEDATTRIBUTEELEMENT_H_
 #define NS_MAPPEDATTRIBUTEELEMENT_H_
 
 #include "nsStyledElement.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsMappedAttributes;
 struct nsRuleData;
 
 typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, 
                                           nsRuleData* aData);
 
 typedef nsStyledElement nsMappedAttributeElementBase;
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1866,19 +1866,28 @@ nsObjectLoadingContent::GetObjectBaseURI
 
   if (codebase.IsEmpty() && aMimeType.Equals("application/x-java-vm")) {
     // bug 406541
     // Java resolves codebase="" as "/" -- so we replicate that quirk, to ensure
     // we run security checks against the same path.
     codebase.AssignLiteral("/");
   }
 
-  nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
-                                            thisContent->OwnerDoc(),
-                                            baseURI);
+  if (!codebase.IsEmpty()) {
+    nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
+                                                            thisContent->OwnerDoc(),
+                                                            baseURI);
+    if (NS_SUCCEEDED(rv))
+      return rv;
+    NS_WARNING("GetObjectBaseURI: Could not resolve plugin's codebase to a URI, using baseURI instead");
+  }
+
+  // Codebase empty or build URI failed, just use baseURI
+  *aURI = NULL;
+  baseURI.swap(*aURI);
   return NS_OK;
 }
 
 nsObjectFrame*
 nsObjectLoadingContent::GetExistingFrame()
 {
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   nsIFrame* frame = thisContent->GetPrimaryFrame();
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -103,17 +103,16 @@ nsPlainTextSerializer::nsPlainTextSerial
 
   mOutputString = nsnull;
   mHeadLevel = 0;
   mAtFirstColumn = true;
   mIndent = 0;
   mCiteQuoteLevel = 0;
   mStructs = true;       // will be read from prefs later
   mHeaderStrategy = 1 /*indent increasingly*/;   // ditto
-  mQuotesPreformatted = false;                // ditto
   mDontWrapAnyQuotes = false;                 // ditto
   mHasWrittenCiteBlockquote = false;
   mSpanLevel = 0;
   for (PRInt32 i = 0; i <= 6; i++) {
     mHeaderCounter[i] = 0;
   }
 
   // Line breaker
@@ -205,20 +204,16 @@ nsPlainTextSerializer::Init(PRUint32 aFl
 
   if (mFlags & nsIDocumentEncoder::OutputFormatted) {
     // Get some prefs that controls how we do formatted output
     mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs);
 
     mHeaderStrategy =
       Preferences::GetInt(PREF_HEADER_STRATEGY, mHeaderStrategy);
 
-    // The quotesPreformatted pref is a temporary measure. See bug 69638.
-    mQuotesPreformatted =
-      Preferences::GetBool("editor.quotesPreformatted", mQuotesPreformatted);
-
     // DontWrapAnyQuotes is set according to whether plaintext mail
     // is wrapping to window width -- see bug 134439.
     // We'll only want this if we're wrapping and formatted.
     if (mFlags & nsIDocumentEncoder::OutputWrap || mWrapColumn > 0) {
       mDontWrapAnyQuotes =
         Preferences::GetBool("mail.compose.wrap_to_window_width",
                              mDontWrapAnyQuotes);
     }
@@ -1631,17 +1626,17 @@ nsPlainTextSerializer::Write(const nsASt
         break;
     }
   }
 
   // We have two major codepaths here. One that does preformatted text and one
   // that does normal formatted text. The one for preformatted text calls
   // Output directly while the other code path goes through AddToLine.
   if ((mPreFormatted && !mWrapColumn) || IsInPre()
-      || ((((!mQuotesPreformatted && mSpanLevel > 0) || mDontWrapAnyQuotes))
+      || ((mSpanLevel > 0 || mDontWrapAnyQuotes)
           && mEmptyLines >= 0 && str.First() == PRUnichar('>'))) {
     // No intelligent wrapping.
 
     // This mustn't be mixed with intelligent wrapping without clearing
     // the mCurrentLine buffer before!!!
     NS_ASSERTION(mCurrentLine.IsEmpty(),
                  "Mixed wrapping data and nonwrapping data on the same line");
     if (!mCurrentLine.IsEmpty()) {
--- a/content/base/src/nsPlainTextSerializer.h
+++ b/content/base/src/nsPlainTextSerializer.h
@@ -171,21 +171,19 @@ protected:
   nsString         mCurrentLine;
   PRUint32         mHeadLevel;
   bool             mAtFirstColumn;
 
   // Handling of quoted text (for mail):
   // Quotes need to be wrapped differently from non-quoted text,
   // because quoted text has a few extra characters (e.g. ">> ")
   // which makes the line length longer.
-  // Mail can represent quotes in different ways: it can wrap
-  // quotes in a <pre> (if editor.quotesPreformatted is set),
-  // or not wrapped in any special tag (if mail.compose.wrap_to_window_width)
-  // or in a <span> (if neither of the above are set).
-  bool             mQuotesPreformatted; // expect quotes wrapped in <pre>
+  // Mail can represent quotes in different ways:
+  // Not wrapped in any special tag (if mail.compose.wrap_to_window_width)
+  // or in a <span>.
   bool             mDontWrapAnyQuotes;  // no special quote markers
 
   bool             mStructs;            // Output structs (pref)
 
   // If we've just written out a cite blockquote, we need to remember it
   // so we don't duplicate spaces before a <pre wrap> (which mail uses to quote
   // old messages).
   bool             mHasWrittenCiteBlockquote;
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -923,17 +923,17 @@ nsRange::SetStart(nsIDOMNode* aParent, P
   AutoInvalidateSelection atEndOfBlock(this);
   return SetStart(parent, aOffset);
 }
 
 /* virtual */ nsresult
 nsRange::SetStart(nsINode* aParent, PRInt32 aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aParent);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR);
+  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
   PRInt32 len = GetNodeLength(aParent);
   if (aOffset < 0 || aOffset > len)
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
   // Collapse if not positioned yet, if positioned in another doc or
   // if the new start is after end.
   if (!mIsPositioned || newRoot != mRoot ||
@@ -952,31 +952,31 @@ nsRange::SetStart(nsINode* aParent, PRIn
 NS_IMETHODIMP
 nsRange::SetStartBefore(nsIDOMNode* aSibling)
 {
   VALIDATE_ACCESS(aSibling);
   
   nsCOMPtr<nsIDOMNode> parent;
   nsresult rv = aSibling->GetParentNode(getter_AddRefs(parent));
   if (NS_FAILED(rv) || !parent) {
-    return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   return SetStart(parent, IndexOf(aSibling));
 }
 
 NS_IMETHODIMP
 nsRange::SetStartAfter(nsIDOMNode* aSibling)
 {
   VALIDATE_ACCESS(aSibling);
 
   nsCOMPtr<nsIDOMNode> nParent;
   nsresult res = aSibling->GetParentNode(getter_AddRefs(nParent));
   if (NS_FAILED(res) || !nParent) {
-    return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   return SetStart(nParent, IndexOf(aSibling) + 1);
 }
 
 NS_IMETHODIMP
 nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset)
 {
@@ -987,17 +987,17 @@ nsRange::SetEnd(nsIDOMNode* aParent, PRI
   return SetEnd(parent, aOffset);
 }
 
 
 /* virtual */ nsresult
 nsRange::SetEnd(nsINode* aParent, PRInt32 aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aParent);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR);
+  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
   PRInt32 len = GetNodeLength(aParent);
   if (aOffset < 0 || aOffset > len) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Collapse if not positioned yet, if positioned in another doc or
   // if the new end is before start.
@@ -1017,31 +1017,31 @@ nsRange::SetEnd(nsINode* aParent, PRInt3
 NS_IMETHODIMP
 nsRange::SetEndBefore(nsIDOMNode* aSibling)
 {
   VALIDATE_ACCESS(aSibling);
   
   nsCOMPtr<nsIDOMNode> nParent;
   nsresult rv = aSibling->GetParentNode(getter_AddRefs(nParent));
   if (NS_FAILED(rv) || !nParent) {
-    return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   return SetEnd(nParent, IndexOf(aSibling));
 }
 
 NS_IMETHODIMP
 nsRange::SetEndAfter(nsIDOMNode* aSibling)
 {
   VALIDATE_ACCESS(aSibling);
   
   nsCOMPtr<nsIDOMNode> nParent;
   nsresult res = aSibling->GetParentNode(getter_AddRefs(nParent));
   if (NS_FAILED(res) || !nParent) {
-    return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   return SetEnd(nParent, IndexOf(aSibling) + 1);
 }
 
 NS_IMETHODIMP
 nsRange::Collapse(bool aToStart)
 {
@@ -1060,41 +1060,41 @@ nsRange::Collapse(bool aToStart)
 }
 
 NS_IMETHODIMP
 nsRange::SelectNode(nsIDOMNode* aN)
 {
   VALIDATE_ACCESS(aN);
   
   nsCOMPtr<nsINode> node = do_QueryInterface(aN);
-  NS_ENSURE_TRUE(node, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR);
+  NS_ENSURE_TRUE(node, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
   nsINode* parent = node->GetNodeParent();
   nsINode* newRoot = IsValidBoundary(parent);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR);
+  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
   PRInt32 index = parent->IndexOf(node);
   if (index < 0) {
-    return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   DoSetRange(parent, index, parent, index + 1, newRoot);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::SelectNodeContents(nsIDOMNode* aN)
 {
   VALIDATE_ACCESS(aN);
 
   nsCOMPtr<nsINode> node = do_QueryInterface(aN);
   nsINode* newRoot = IsValidBoundary(node);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR);
+  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
   
   AutoInvalidateSelection atEndOfBlock(this);
   DoSetRange(node, 0, node, GetNodeLength(node), newRoot);
   
   return NS_OK;
 }
 
 // The Subtree Content Iterator only returns subtrees that are
@@ -2139,33 +2139,33 @@ nsRange::InsertNode(nsIDOMNode* aN)
 }
 
 NS_IMETHODIMP
 nsRange::SurroundContents(nsIDOMNode* aNewParent)
 {
   VALIDATE_ACCESS(aNewParent);
 
   NS_ENSURE_TRUE(mRoot, NS_ERROR_DOM_INVALID_STATE_ERR);
-  // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text
+  // INVALID_STATE_ERROR: Raised if the Range partially selects a non-text
   // node.
   if (mStartParent != mEndParent) {
     bool startIsText = mStartParent->IsNodeOfType(nsINode::eTEXT);
     bool endIsText = mEndParent->IsNodeOfType(nsINode::eTEXT);
     nsINode* startGrandParent = mStartParent->GetNodeParent();
     nsINode* endGrandParent = mEndParent->GetNodeParent();
     NS_ENSURE_TRUE((startIsText && endIsText &&
                     startGrandParent &&
                     startGrandParent == endGrandParent) ||
                    (startIsText &&
                     startGrandParent &&
                     startGrandParent == mEndParent) ||
                    (endIsText &&
                     endGrandParent &&
                     endGrandParent == mStartParent),
-                   NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR);
+                   NS_ERROR_DOM_INVALID_STATE_ERR);
   }
 
   // Extract the contents within the range.
 
   nsCOMPtr<nsIDOMDocumentFragment> docFrag;
 
   nsresult res = ExtractContents(getter_AddRefs(docFrag));
 
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -43,17 +43,16 @@
  * SVG and MathML.
  */
 
 #ifndef __NS_STYLEDELEMENT_H_
 #define __NS_STYLEDELEMENT_H_
 
 #include "nsString.h"
 #include "nsGenericElement.h"
-#include "nsDOMMemoryReporter.h"
 
 namespace mozilla {
 namespace css {
 class StyleRule;
 }
 }
 
 typedef nsGenericElement nsStyledElementBase;
--- a/content/base/src/nsTextFragment.h
+++ b/content/base/src/nsTextFragment.h
@@ -43,17 +43,16 @@
 #ifndef nsTextFragment_h___
 #define nsTextFragment_h___
 
 #include "mozilla/Attributes.h"
 
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsTraceRefcnt.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsString;
 class nsCString;
 
 // XXX should this normalize the code to keep a \u0000 at the end?
 
 // XXX nsTextFragmentPool?
 
--- a/content/base/src/nsTextNode.h
+++ b/content/base/src/nsTextNode.h
@@ -40,17 +40,16 @@
  */
 
 #include "nsGenericDOMDataNode.h"
 #include "nsIDOMText.h"
 
 #include "nsIAttribute.h"
 #include "nsIDocument.h"
 #include "nsThreadUtils.h"
-#include "nsDOMMemoryReporter.h"
 
 /**
  * Class used to implement DOM text nodes
  */
 class nsTextNode : public nsGenericDOMDataNode,
                    public nsIDOMText
 {
 public:
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -556,16 +556,17 @@ include $(topsrcdir)/config/rules.mk
 		file_XHR_timeout.sjs \
 		test_bug717511.html \
 		file_bug717511.html \
 		file_bug717511.html^headers^ \
 		file_bug717511_2.html \
 		file_bug717511_2.html^headers^ \
 		test_bug726364.html \
 		test_bug698381.html \
+		test_bug711047.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
--- a/content/base/test/test_bug454326.html
+++ b/content/base/test/test_bug454326.html
@@ -79,47 +79,50 @@ https://bugzilla.mozilla.org/show_bug.cg
       var r3 = document.createRange();
       r3.setStart(pts.firstChild, 6);
       r3.setEnd(pts.firstChild.nextSibling, 0);
       is(r3.toString(), "Hello ", "Wrong range!");
       r3.surroundContents(document.createElement("div"));
       is(r3.toString(), "Hello ", "Wrong range!");
     } catch(e) {
       ex = e;
-      is(e.code, 1, "Didn't get BAD_BOUNDARYPOINTS_ERR exception!");
+      is(Object.getPrototypeOf(e), DOMException.prototype, "Didn't get DOMException!");
+      is(e.code, 11, "Didn't get INVALID_STATE_ERR exception!");
     }
     ok(ex, "There should have been an exception!");
 
     reinitPartialTextSelection();
     ex = null;
     try {
       var r3 = document.createRange();
       r3.setStart(pts.firstChild.nextSibling, 0);
       r3.setEnd(pts.lastChild, 6);
       is(r3.toString(), "World!", "Wrong range!");
       r3.surroundContents(document.createElement("div"));
       is(r3.toString(), "World!", "Wrong range!");
     } catch(e) {
       ex = e;
-      is(e.code, 1, "Didn't get BAD_BOUNDARYPOINTS_ERR exception!");
+      is(Object.getPrototypeOf(e), DOMException.prototype, "Didn't get DOMException!");
+      is(e.code, 11, "Didn't get INVALID_STATE_ERR exception!");
     }
     ok(ex, "There should have been an exception!");
 
     ex = null;
     try {
       var pes = document.getElementById("partial-element-selection");
       var r4 = document.createRange();
       r4.setStart(pes.firstChild.firstChild, 6);
       r4.setEnd(pes.lastChild.firstChild, 6);
       is(r4.toString(), "Hello World!", "Wrong range!");
       r4.surroundContents(document.createElement("div"));
       is(r4.toString(), "Hello World!", "Wrong range!");
     } catch(e) {
       ex = e;
-      is(e.code, 1, "Didn't get BAD_BOUNDARYPOINTS_ERR exception!");
+      is(Object.getPrototypeOf(e), DOMException.prototype, "Didn't get DOMException!");
+      is(e.code, 11, "Didn't get INVALID_STATE_ERR exception!");
     }
     ok(ex, "There should have been an exception!");
   }
 
   SimpleTest.waitForExplicitFinish();
   addLoadEvent(doTest);
   addLoadEvent(SimpleTest.finish);
 </script>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug711047.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=711047
+-->
+<title>Test for Bug 711047</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=711047">Mozilla Bug 711047</a>
+<div id="content">
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 711047 **/
+ok(!("RangeException" in window), "RangeException shouldn't exist");
+</script>
+</pre>
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -58,16 +58,17 @@
 #include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsContentUtils.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
+#include "nsDataHashtable.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
 
 /* 
  * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
  *   https://bugzilla.mozilla.org/show_bug.cgi?id=686732
@@ -1622,26 +1623,35 @@ public:
             if (mFakeBlackStatus == DontKnowIfNeedFakeBlack)
                 mFakeBlackStatus = DoNotNeedFakeBlack;
         }
 
         return mFakeBlackStatus == DoNeedFakeBlack;
     }
 };
 
+struct WebGLMappedIdentifier {
+    nsCString original, mapped; // ASCII strings
+    WebGLMappedIdentifier(const nsACString& o, const nsACString& m) : original(o), mapped(m) {}
+};
+
 class WebGLShader MOZ_FINAL
     : public nsIWebGLShader
     , public WebGLRefCountedObject<WebGLShader>
     , public WebGLContextBoundObject
 {
+    friend class WebGLContext;
+    friend class WebGLProgram;
+
 public:
     WebGLShader(WebGLContext *context, WebGLenum stype)
         : WebGLContextBoundObject(context)
         , mType(stype)
         , mNeedsTranslation(true)
+        , mAttribMaxNameLength(0)
     {
         mContext->MakeContextCurrent();
         mGLName = mContext->gl->fCreateShader(mType);
         mMonotonicHandle = mContext->mShaders.AppendElement(this);
     }
 
     ~WebGLShader() {
         DeleteOnce();
@@ -1688,35 +1698,66 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLSHADER
 
 protected:
 
     WebGLuint mGLName;
     WebGLenum mType;
     nsString mSource;
-    nsCString mTranslationLog;
+    nsCString mTranslationLog; // The translation log should contain only ASCII characters
     bool mNeedsTranslation;
     WebGLMonotonicHandle mMonotonicHandle;
+    nsTArray<WebGLMappedIdentifier> mAttributes;
+    nsTArray<WebGLMappedIdentifier> mUniforms;
+    int mAttribMaxNameLength;
 };
 
+/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
+  * 
+  * \param string input/output: the string to split, becomes the string without the bracket part
+  * \param bracketPart output: gets the bracket part.
+  * 
+  * Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split.
+  */
+static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
+{
+    NS_ABORT_IF_FALSE(bracketPart.Length() == 0, "SplitLastSquareBracket must be called with empty bracketPart string");
+    char *string_start = string.BeginWriting();
+    char *s = string_start + string.Length() - 1;
+
+    if (*s != ']')
+        return false;
+
+    while (*s != '[' && s != string_start)
+        s--;
+
+    if (*s != '[')
+        return false;
+
+    bracketPart.Assign(s);
+    *s = 0;
+    string.EndWriting();
+    string.SetLength(s - string_start);
+    return true;
+}
+
+typedef nsDataHashtable<nsCStringHashKey, nsCString> CStringHash;
+
 class WebGLProgram MOZ_FINAL
     : public nsIWebGLProgram
     , public WebGLRefCountedObject<WebGLProgram>
     , public WebGLContextBoundObject
 {
 public:
     WebGLProgram(WebGLContext *context)
         : WebGLContextBoundObject(context)
         , mLinkStatus(false)
         , mGeneration(0)
-        , mUniformMaxNameLength(0)
         , mAttribMaxNameLength(0)
-        , mUniformCount(0)
-        , mAttribCount(0)
     {
         mContext->MakeContextCurrent();
         mGLName = mContext->gl->fCreateProgram();
         mMonotonicHandle = mContext->mPrograms.AppendElement(this);
     }
 
     ~WebGLProgram() {
         DeleteOnce();
@@ -1785,44 +1826,133 @@ public:
     {
         if (!(mGeneration+1).valid())
             return false; // must exit without changing mGeneration
         ++mGeneration;
         return true;
     }
 
     /* Called only after LinkProgram */
-    bool UpdateInfo(gl::GLContext *gl);
+    bool UpdateInfo();
 
     /* Getters for cached program info */
-    WebGLint UniformMaxNameLength() const { return mUniformMaxNameLength; }
-    WebGLint AttribMaxNameLength() const { return mAttribMaxNameLength; }
-    WebGLint UniformCount() const { return mUniformCount; }
-    WebGLint AttribCount() const { return mAttribCount; }
     bool IsAttribInUse(unsigned i) const { return mAttribsInUse[i]; }
 
+    /* Maps identifier |name| to the mapped identifier |*mappedName|
+     * Both are ASCII strings.
+     */
+    void MapIdentifier(const nsACString& name, nsCString *mappedName) {
+        if (!mIdentifierMap) {
+            // if the identifier map doesn't exist yet, build it now
+            mIdentifierMap = new CStringHash;
+            mIdentifierMap->Init();
+            for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
+                for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
+                    const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
+                    mIdentifierMap->Put(attrib.original, attrib.mapped);
+                }
+                for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
+                    const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
+                    mIdentifierMap->Put(uniform.original, uniform.mapped);
+                }
+            }
+        }
+
+        nsCString mutableName(name);
+        nsCString bracketPart;
+        bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
+        if (hadBracketPart)
+            mutableName.AppendLiteral("[0]");
+
+        if (mIdentifierMap->Get(mutableName, mappedName)) {
+            if (hadBracketPart) {
+                nsCString mappedBracketPart;
+                bool mappedHadBracketPart = SplitLastSquareBracket(*mappedName, mappedBracketPart);
+                if (mappedHadBracketPart)
+                    mappedName->Append(bracketPart);
+            }
+            return;
+        }
+
+        // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
+        // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
+        mutableName.AppendLiteral("[0]");
+        if (mIdentifierMap->Get(mutableName, mappedName))
+            return;
+
+        // not found? return name unchanged. This case happens e.g. on bad user input, or when
+        // we're not using identifier mapping, or if we didn't store an identifier in the map because
+        // e.g. its mapping is trivial (as happens for short identifiers)
+        mappedName->Assign(name);
+    }
+
+    /* Un-maps mapped identifier |name| to the original identifier |*reverseMappedName|
+     * Both are ASCII strings.
+     */
+    void ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) {
+        if (!mIdentifierReverseMap) {
+            // if the identifier reverse map doesn't exist yet, build it now
+            mIdentifierReverseMap = new CStringHash;
+            mIdentifierReverseMap->Init();
+            for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
+                for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
+                    const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
+                    mIdentifierReverseMap->Put(attrib.mapped, attrib.original);
+                }
+                for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
+                    const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
+                    mIdentifierReverseMap->Put(uniform.mapped, uniform.original);
+                }
+            }
+        }
+
+        nsCString mutableName(name);
+        nsCString bracketPart;
+        bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
+        if (hadBracketPart)
+            mutableName.AppendLiteral("[0]");
+
+        if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) {
+            if (hadBracketPart) {
+                nsCString reverseMappedBracketPart;
+                bool reverseMappedHadBracketPart = SplitLastSquareBracket(*reverseMappedName, reverseMappedBracketPart);
+                if (reverseMappedHadBracketPart)
+                    reverseMappedName->Append(bracketPart);
+            }
+            return;
+        }
+
+        // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
+        // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
+        mutableName.AppendLiteral("[0]");
+        if (mIdentifierReverseMap->Get(mutableName, reverseMappedName))
+            return;
+
+        // not found? return name unchanged. This case happens e.g. on bad user input, or when
+        // we're not using identifier mapping, or if we didn't store an identifier in the map because
+        // e.g. its mapping is trivial (as happens for short identifiers)
+        reverseMappedName->Assign(name);
+    }
+
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLPROGRAM
 
 protected:
 
     WebGLuint mGLName;
     bool mLinkStatus;
     // attached shaders of the program object
     nsTArray<WebGLRefPtr<WebGLShader> > mAttachedShaders;
     CheckedUint32 mGeneration;
 
     // post-link data
-
-    GLint mUniformMaxNameLength;
-    GLint mAttribMaxNameLength;
-    GLint mUniformCount;
-    GLint mAttribCount;
     std::vector<bool> mAttribsInUse;
     WebGLMonotonicHandle mMonotonicHandle;
+    nsAutoPtr<CStringHash> mIdentifierMap, mIdentifierReverseMap;
+    int mAttribMaxNameLength;
 };
 
 class WebGLRenderbuffer MOZ_FINAL
     : public nsIWebGLRenderbuffer
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public WebGLRectangleObject
     , public WebGLContextBoundObject
 {
@@ -2361,22 +2491,21 @@ protected:
     WebGLMonotonicHandle mMonotonicHandle;
     friend class WebGLProgram;
 };
 
 class WebGLActiveInfo MOZ_FINAL
     : public nsIWebGLActiveInfo
 {
 public:
-    WebGLActiveInfo(WebGLint size, WebGLenum type, const char *nameptr, PRUint32 namelength) :
+    WebGLActiveInfo(WebGLint size, WebGLenum type, const nsACString& name) :
         mSize(size),
-        mType(type)
-    {
-        mName.AssignASCII(nameptr, namelength);
-    }
+        mType(type),
+        mName(NS_ConvertASCIItoUTF16(name))
+    {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLACTIVEINFO
 protected:
     WebGLint mSize;
     WebGLenum mType;
     nsString mName;
 };
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -116,17 +116,16 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, 
 }
 
 #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6)          \
 NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
     if (!IsContextStable()) { return NS_OK; }                                 \
     MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
 }
 
-
 //
 //  WebGL API
 //
 
 
 /* void GlActiveTexture (in GLenum texture); */
 NS_IMETHODIMP
 WebGLContext::ActiveTexture(WebGLenum texture)
@@ -176,29 +175,32 @@ WebGLContext::AttachShader(nsIWebGLProgr
 
 NS_IMETHODIMP
 WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, const nsAString& name)
 {
     if (!IsContextStable())
         return NS_OK;
 
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("bindAttribLocation: program", pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName("bindAttribLocation: program", pobj, &prog, &progname))
         return NS_OK;
 
     if (!ValidateGLSLVariableName(name, "bindAttribLocation"))
         return NS_OK;
 
     if (!ValidateAttribIndex(location, "bindAttribLocation"))
         return NS_OK;
 
+    NS_LossyConvertUTF16toASCII cname(name);
+    nsCString mappedName;
+    prog->MapIdentifier(cname, &mappedName);
+    
     MakeContextCurrent();
-
-    gl->fBindAttribLocation(progname, location, NS_LossyConvertUTF16toASCII(name).get());
-
+    gl->fBindAttribLocation(progname, location, mappedName.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindBuffer(WebGLenum target, nsIWebGLBuffer *bobj)
 {
     WebGLuint bufname;
     WebGLBuffer* buf;
@@ -1847,17 +1849,18 @@ NS_IMETHODIMP
 WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
     if (!IsContextStable())
         return NS_OK;
 
     *retval = nsnull;
 
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("getActiveAttrib: program", pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName("getActiveAttrib: program", pobj, &prog, &progname))
         return NS_OK;
 
     MakeContextCurrent();
 
     GLint len = 0;
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
     if (len == 0)
         return NS_OK;
@@ -1867,17 +1870,20 @@ WebGLContext::GetActiveAttrib(nsIWebGLPr
     GLuint attrtype = 0;
 
     gl->fGetActiveAttrib(progname, index, len, &len, &attrsize, &attrtype, name);
     if (attrsize == 0 || attrtype == 0) {
         *retval = nsnull;
         return NS_OK;
     }
 
-    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
+    nsCString reverseMappedName;
+    prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
+
+    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, reverseMappedName);
     NS_ADDREF(*retval = retActiveInfo);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GenerateMipmap(WebGLenum target)
 {
@@ -1911,60 +1917,59 @@ NS_IMETHODIMP
 WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
     if (!IsContextStable())
         return NS_OK;
 
     *retval = nsnull;
 
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("getActiveUniform: program", pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName("getActiveUniform: program", pobj, &prog, &progname))
         return NS_OK;
 
     MakeContextCurrent();
 
     GLint len = 0;
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
     if (len == 0)
         *retval = nsnull;
 
-    nsAutoArrayPtr<char> name(new char[len + 3]); // +3 because we might have to append "[0]", see below
-
-    GLint attrsize = 0;
-    GLuint attrtype = 0;
-
-    gl->fGetActiveUniform(progname, index, len, &len, &attrsize, &attrtype, name);
-    if (len == 0 || attrsize == 0 || attrtype == 0) {
+    nsAutoArrayPtr<char> name(new char[len]);
+
+    GLint usize = 0;
+    GLuint utype = 0;
+
+    gl->fGetActiveUniform(progname, index, len, &len, &usize, &utype, name);
+    if (len == 0 || usize == 0 || utype == 0) {
         *retval = nsnull;
         return NS_OK;
     }
 
+    nsCString reverseMappedName;
+    prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
+
     // OpenGL ES 2.0 specifies that if foo is a uniform array, GetActiveUniform returns its name as "foo[0]".
     // See section 2.10 page 35 in the OpenGL ES 2.0.24 specification:
     //
     // > If the active uniform is an array, the uniform name returned in name will always
     // > be the name of the uniform array appended with "[0]".
     //
     // There is no such requirement in the OpenGL (non-ES) spec and indeed we have OpenGL implementations returning
     // "foo" instead of "foo[0]". So, when implementing WebGL on top of desktop OpenGL, we must check if the
     // returned name ends in [0], and if it doesn't, append that.
     //
     // In principle we don't need to do that on OpenGL ES, but this is such a tricky difference between the ES and non-ES
     // specs that it seems probable that some ES implementers will overlook it. Since the work-around is quite cheap,
     // we do it unconditionally.
-    if (attrsize > 1 && name[len-1] != ']') {
-        name[len++] = '[';
-        name[len++] = '0';
-        name[len++] = ']';
-    }
-
-    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
-
+    if (usize > 1 && reverseMappedName.CharAt(reverseMappedName.Length()-1) != ']')
+        reverseMappedName.AppendLiteral("[0]");
+
+    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(usize, utype, reverseMappedName);
     NS_ADDREF(*retval = retActiveInfo);
-
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetAttachedShaders(nsIWebGLProgram *pobj, nsIVariant **retval)
 {
     if (!IsContextStable())
         return NS_OK;
@@ -2004,33 +2009,35 @@ WebGLContext::GetAttachedShaders(nsIWebG
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj,
                                 const nsAString& name,
                                 PRInt32 *retval)
 {
+    *retval = -1;
+
     if (!IsContextStable())
-    {
-        *retval = -1;
-        return NS_OK;
-    }
-
-    *retval = 0;
+        return NS_OK;
 
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("getAttribLocation: program", pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName("getAttribLocation: program", pobj, &prog, &progname))
         return NS_OK;
 
     if (!ValidateGLSLVariableName(name, "getAttribLocation"))
         return NS_OK; 
 
+    NS_LossyConvertUTF16toASCII cname(name);
+    nsCString mappedName;
+    prog->MapIdentifier(cname, &mappedName);
+
     MakeContextCurrent();
-    *retval = gl->fGetAttribLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
+    *retval = gl->fGetAttribLocation(progname, mappedName.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
 {
     if (!IsContextStable())
         return NS_OK;
@@ -2975,21 +2982,24 @@ WebGLContext::GetUniformLocation(nsIWebG
     *retval = nsnull;
 
     WebGLuint progname;
     WebGLProgram *prog;
     if (!GetConcreteObjectAndGLName("getUniformLocation: program", pobj, &prog, &progname))
         return NS_OK;
 
     if (!ValidateGLSLVariableName(name, "getUniformLocation"))
-        return NS_OK; 
+        return NS_OK;
+
+    NS_LossyConvertUTF16toASCII cname(name);
+    nsCString mappedName;
+    prog->MapIdentifier(cname, &mappedName);
 
     MakeContextCurrent();
-
-    GLint intlocation = gl->fGetUniformLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
+    GLint intlocation = gl->fGetUniformLocation(progname, mappedName.get());
 
     WebGLUniformLocation *loc = nsnull;
     if (intlocation >= 0)
         NS_ADDREF(loc = new WebGLUniformLocation(this, prog, intlocation));
     *retval = loc;
     return NS_OK;
 }
 
@@ -3246,28 +3256,26 @@ WebGLContext::LinkProgram(nsIWebGLProgra
         return NS_ERROR_FAILURE;
 
     if (!program->HasBothShaderTypesAttached()) {
         program->SetLinkStatus(false);
         return NS_OK;
     }
 
     MakeContextCurrent();
-
     gl->fLinkProgram(progname);
 
     GLint ok;
     gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
     if (ok) {
-        program->SetLinkStatus(true);
-        program->UpdateInfo(gl);
+        bool updateInfoSucceeded = program->UpdateInfo();
+        program->SetLinkStatus(updateInfoSucceeded);
     } else {
         program->SetLinkStatus(false);
     }
-
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::PixelStorei(WebGLenum pname, WebGLint param)
 {
     if (!IsContextStable())
         return NS_OK;
@@ -4382,16 +4390,30 @@ WebGLContext::CompileShader(nsIWebGLShad
 
     WebGLShader *shader;
     WebGLuint shadername;
     if (!GetConcreteObjectAndGLName("compileShader", sobj, &shader, &shadername))
         return NS_OK;
 
     MakeContextCurrent();
 
+    ShShaderOutput targetShaderSourceLanguage = gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
+    bool useShaderSourceTranslation = true;
+
+#ifdef ANDROID
+    // see bug 709947. On Android, we can't use the ESSL backend because of strange crashes (might be
+    // an allocator mismatch). So we use the GLSL backend, and discard the output, instead just passing
+    // the original WebGL shader source to the GL (since that's ESSL already). The problem is that means
+    // we can't use shader translations on Android, in particular we can't use long identifier shortening,
+    // which means we can't reach 100% conformance. We need to fix that by debugging the ESSL backend
+    // memory crashes.
+    targetShaderSourceLanguage = SH_GLSL_OUTPUT;
+    useShaderSourceTranslation = false;
+#endif
+
 #if defined(USE_ANGLE)
     if (shader->NeedsTranslation() && mShaderValidation) {
         ShHandle compiler = 0;
         ShBuiltInResources resources;
         memset(&resources, 0, sizeof(ShBuiltInResources));
 
         resources.MaxVertexAttribs = mGLMaxVertexAttribs;
         resources.MaxVertexUniformVectors = mGLMaxVertexUniformVectors;
@@ -4399,57 +4421,52 @@ WebGLContext::CompileShader(nsIWebGLShad
         resources.MaxVertexTextureImageUnits = mGLMaxVertexTextureImageUnits;
         resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
         resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
         resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
         resources.MaxDrawBuffers = 1;
         if (mEnabledExtensions[WebGL_OES_standard_derivatives])
             resources.OES_standard_derivatives = 1;
 
-        // notice that on Android, we always use SH_GLSL_OUTPUT, we never use the ESSL backend.
-        // see bug 709947, the reason is that 1) we dont really need a ESSL backend since the
-        // source is already ESSL, and 2) we ran into massive Android crashes when we used the ESSL backend.
-        // But if we wanted to use shader transformations on ES platforms, we would have to use the
-        // ESSL backend
-        compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
-                                       SH_WEBGL_SPEC,
-#ifdef ANDROID
-                                       SH_GLSL_OUTPUT,
-#else
-                                       gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
-#endif
-                                       &resources);
-
         // We're storing an actual instance of StripComments because, if we don't, the 
         // cleanSource nsAString instance will be destroyed before the reference is
         // actually used.
         StripComments stripComments(shader->Source());
         const nsAString& cleanSource = nsString(stripComments.result().Elements(), stripComments.length());
         if (!ValidateGLSLString(cleanSource, "compileShader"))
             return NS_OK;
 
         const nsPromiseFlatString& flatSource = PromiseFlatString(cleanSource);
 
         // shaderSource() already checks that the source stripped of comments is in the
         // 7-bit ASCII range, so we can skip the NS_IsAscii() check.
         const nsCString& sourceCString = NS_LossyConvertUTF16toASCII(flatSource);
-    
+
         const PRUint32 maxSourceLength = (PRUint32(1)<<18) - 1;
         if (sourceCString.Length() > maxSourceLength)
             return ErrorInvalidValue("compileShader: source has more than %d characters", maxSourceLength);
 
         const char *s = sourceCString.get();
-        
-        int compileOptions = SH_OBJECT_CODE;
-        
+
+        compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
+                                       SH_WEBGL_SPEC,
+                                       targetShaderSourceLanguage,
+                                       &resources);
+
+        int compileOptions = 0;
+        if (useShaderSourceTranslation) {
+            compileOptions |= SH_OBJECT_CODE
+                            | SH_MAP_LONG_VARIABLE_NAMES
+                            | SH_ATTRIBUTES_UNIFORMS;
 #ifdef XP_MACOSX
-        // work around bug 665578
-        if (!nsCocoaFeatures::OnLionOrLater() && gl->Vendor() == gl::GLContext::VendorATI)
-            compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
+            // work around bug 665578
+            if (!nsCocoaFeatures::OnLionOrLater() && gl->Vendor() == gl::GLContext::VendorATI)
+                compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
 #endif
+        }
 
         if (!ShCompile(compiler, &s, 1, compileOptions)) {
             int len = 0;
             ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &len);
 
             if (len) {
                 nsCAutoString info;
                 info.SetLength(len);
@@ -4457,33 +4474,75 @@ WebGLContext::CompileShader(nsIWebGLShad
                 shader->SetTranslationFailure(info);
             } else {
                 shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
             }
             ShDestruct(compiler);
             return NS_OK;
         }
 
-        /* If the GL context is really GLES2, we want to use the original provided code,
-         * since it's actually GLES2.  We still need to validate it however, which is
-         * why we ran it through the above, but we don't want the desktop GLSL.
-         */
-        if (!gl->IsGLES2()) {
+        int num_attributes = 0;
+        ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
+        int num_uniforms = 0;
+        ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
+        int attrib_max_length = 0;
+        ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_max_length);
+        int uniform_max_length = 0;
+        ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_max_length);
+        int mapped_max_length = 0;
+        ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_max_length);
+
+        shader->mAttribMaxNameLength = attrib_max_length;
+
+        shader->mAttributes.Clear();
+        shader->mUniforms.Clear();
+        nsAutoArrayPtr<char> attribute_name(new char[attrib_max_length+1]);
+        nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
+        nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
+
+        if (useShaderSourceTranslation) {
+            for (int i = 0; i < num_attributes; i++) {
+                int length, size;
+                ShDataType type;
+                ShGetActiveAttrib(compiler, i,
+                                  &length, &size, &type,
+                                  attribute_name,
+                                  mapped_name);
+                shader->mAttributes.AppendElement(WebGLMappedIdentifier(
+                                                    nsDependentCString(attribute_name),
+                                                    nsDependentCString(mapped_name)));
+            }
+
+            for (int i = 0; i < num_uniforms; i++) {
+                int length, size;
+                ShDataType type;
+                ShGetActiveUniform(compiler, i,
+                                   &length, &size, &type,
+                                   uniform_name,
+                                   mapped_name);
+                shader->mUniforms.AppendElement(WebGLMappedIdentifier(
+                                                  nsDependentCString(uniform_name),
+                                                  nsDependentCString(mapped_name)));
+            }
+
             int len = 0;
             ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &len);
 
             nsCAutoString translatedSrc;
             translatedSrc.SetLength(len);
             ShGetObjectCode(compiler, translatedSrc.BeginWriting());
 
             nsPromiseFlatCString translatedSrc2(translatedSrc);
             const char *ts = translatedSrc2.get();
 
             gl->fShaderSource(shadername, 1, &ts, NULL);
-        } else {
+        } else { // not useShaderSourceTranslation
+            // we just pass the raw untranslated shader source. We then can't use ANGLE idenfier mapping.
+            // that's really bad, as that means we can't be 100% conformant. We should work towards always
+            // using ANGLE identifier mapping.
             gl->fShaderSource(shadername, 1, &s, NULL);
         }
 
         shader->SetTranslationSuccess();
 
         ShDestruct(compiler);
 
         gl->fCompileShader(shadername);
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -44,48 +44,56 @@
 #include "CheckedInt.h"
 
 #include "jstypedarray.h"
 
 #if defined(USE_ANGLE)
 #include "angle/ShaderLang.h"
 #endif
 
+#include <algorithm>
+
 using namespace mozilla;
 
 /*
- * Pull all the data out of the program that will be used by validate later on
+ * Pull data out of the program, post-linking
  */
 bool
-WebGLProgram::UpdateInfo(gl::GLContext *gl)
+WebGLProgram::UpdateInfo()
 {
-    gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &mAttribMaxNameLength);
-    gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &mUniformMaxNameLength);
-    gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_UNIFORMS, &mUniformCount);
-    gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount);
+    mIdentifierMap = nsnull;
+    mIdentifierReverseMap = nsnull;
+
+    mAttribMaxNameLength = 0;
 
-    GLint numVertexAttribs;
-    if (mContext->MinCapabilityMode())  {
-        numVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
-    } else {
-        gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs);
-    }
-    mAttribsInUse.clear();
-    mAttribsInUse.resize(numVertexAttribs);
+    for (size_t i = 0; i < mAttachedShaders.Length(); i++)
+        mAttribMaxNameLength = NS_MAX(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
+
+    GLint attribCount;
+    mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
+
+    mAttribsInUse.resize(mContext->mGLMaxVertexAttribs);
+    std::fill(mAttribsInUse.begin(), mAttribsInUse.end(), false);
 
     nsAutoArrayPtr<char> nameBuf(new char[mAttribMaxNameLength]);
 
-    for (int i = 0; i < mAttribCount; ++i) {
+    for (int i = 0; i < attribCount; ++i) {
         GLint attrnamelen;
         GLint attrsize;
         GLenum attrtype;
-        gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
+        mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
         if (attrnamelen > 0) {
-            GLint loc = gl->fGetAttribLocation(mGLName, nameBuf);
-            mAttribsInUse[loc] = true;
+            GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
+            NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
+            if (loc < mContext->mGLMaxVertexAttribs) {
+                mAttribsInUse[loc] = true;
+            } else {
+                mContext->ErrorInvalidOperation("program exceeds MAX_VERTEX_ATTRIBS");
+                return false;
+            }
         }
     }
 
     return true;
 }
 
 /*
  * Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
@@ -329,17 +337,17 @@ bool WebGLContext::ValidateDrawModeEnum(
         default:
             ErrorInvalidEnumInfo(info, mode);
             return false;
     }
 }
 
 bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
 {
-    const PRUint32 maxSize = 255;
+    const PRUint32 maxSize = 256;
     if (name.Length() > maxSize) {
         ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
                           info, name.Length(), maxSize);
         return false;
     }
 
     if (!ValidateGLSLString(name, info)) {
         return false;
--- a/content/canvas/test/webgl/failing_tests_linux.txt
+++ b/content/canvas/test/webgl/failing_tests_linux.txt
@@ -1,13 +1,7 @@
 conformance/context/premultiplyalpha-test.html
-conformance/glsl/misc/glsl-long-variable-names.html
-conformance/glsl/misc/shader-with-256-character-identifier.frag.html
-conformance/glsl/misc/shader-with-long-line.html
 conformance/misc/uninitialized-test.html
 conformance/programs/gl-get-active-attribute.html
 conformance/textures/texture-mips.html
 conformance/uniforms/gl-uniform-bool.html
 conformance/more/conformance/quickCheckAPI-S_V.html
-conformance/more/functions/uniformfArrayLen1.html
-conformance/glsl/misc/attrib-location-length-limits.html
-conformance/glsl/misc/uniform-location-length-limits.html
 conformance/renderbuffers/framebuffer-object-attachment.html
\ No newline at end of file
--- a/content/canvas/test/webgl/failing_tests_mac.txt
+++ b/content/canvas/test/webgl/failing_tests_mac.txt
@@ -1,11 +1,6 @@
 conformance/context/premultiplyalpha-test.html
 conformance/glsl/misc/glsl-function-nodes.html
-conformance/glsl/misc/glsl-long-variable-names.html
-conformance/glsl/misc/shader-with-256-character-identifier.frag.html
-conformance/glsl/misc/shader-with-long-line.html
 conformance/more/conformance/quickCheckAPI-S_V.html
-conformance/glsl/misc/attrib-location-length-limits.html
-conformance/glsl/misc/uniform-location-length-limits.html
 conformance/programs/program-test.html
 conformance/textures/texture-mips.html
 conformance/textures/texture-npot.html
--- a/content/canvas/test/webgl/failing_tests_windows.txt
+++ b/content/canvas/test/webgl/failing_tests_windows.txt
@@ -1,11 +1,6 @@
 conformance/context/premultiplyalpha-test.html
 conformance/glsl/functions/glsl-function-atan.html
 conformance/glsl/functions/glsl-function-atan-xy.html
-conformance/glsl/misc/glsl-long-variable-names.html
-conformance/glsl/misc/shader-with-256-character-identifier.frag.html
-conformance/glsl/misc/shader-with-long-line.html
 conformance/more/conformance/quickCheckAPI-S_V.html
+conformance/glsl/misc/struct-nesting-under-maximum.html
 conformance/more/functions/uniformfArrayLen1.html
-conformance/glsl/misc/attrib-location-length-limits.html
-conformance/glsl/misc/struct-nesting-under-maximum.html
-conformance/glsl/misc/uniform-location-length-limits.html
\ No newline at end of file
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -40,17 +40,16 @@
 
 #include "nsMappedAttributeElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsFrameLoader.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -9,35 +9,35 @@
 #include "nsIWebProgress.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMCustomEvent.h"
 #include "nsIVariant.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsWeakPtr.h"
 #include "nsVariant.h"
 #include "nsContentUtils.h"
-#include "nsDOMMemoryReporter.h"
 #include "nsEventDispatcher.h"
 #include "nsContentUtils.h"
 #include "nsAsyncDOMEvent.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFrameLoader, nsIFrameLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement)
-  NS_INTERFACE_TABLE_INHERITED3(nsGenericHTMLFrameElement,
+  NS_INTERFACE_TABLE_INHERITED4(nsGenericHTMLFrameElement,
                                 nsIFrameLoaderOwner,
                                 nsIDOMMozBrowserFrame,
+                                nsIMozBrowserFrame,
                                 nsIWebProgressListener)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLFrameElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 NS_IMPL_INT_ATTR(nsGenericHTMLFrameElement, TabIndex, tabindex)
 
 nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
 {
@@ -281,30 +281,30 @@ nsGenericHTMLFrameElement::SetMozbrowser
   nsresult rv = SetBoolAttr(nsGkAtoms::mozbrowser, aValue);
   if (NS_SUCCEEDED(rv)) {
     MaybeEnsureBrowserFrameListenersRegistered();
   }
   return rv;
 }
 
 /*
- * If this frame element is allowed to be a browser frame (because it passes
- * BrowserFrameSecurityCheck()), then make sure that it has the appropriate
+ * If this frame element is allowed to be a browser frame (i.e.,
+ * GetReallyIsBrowser returns true), then make sure that it has the appropriate
  * event listeners enabled.
  */
 void
 nsGenericHTMLFrameElement::MaybeEnsureBrowserFrameListenersRegistered()
 {
   if (mBrowserFrameListenersRegistered) {
     return;
   }
 
   // If this frame passes the browser frame security check, ensure that its
   // listeners are active.
-  if (!BrowserFrameSecurityCheck()) {
+  if (!GetReallyIsBrowser()) {
     return;
   }
 
   // Not much we can do without a frameLoader.  But EnsureFrameLoader will call
   // this function, so we'll get a chance to pass this test.
   if (!mFrameLoader) {
     return;
   }
@@ -347,17 +347,17 @@ nsGenericHTMLFrameElement::MaybeEnsureBr
                                         /* wantsUntrusted = */ false);
 }
 
 /**
  * Return true if this frame element has permission to send mozbrowser
  * events, and false otherwise.
  */
 bool
-nsGenericHTMLFrameElement::BrowserFrameSecurityCheck()
+nsGenericHTMLFrameElement::GetReallyIsBrowser()
 {
   // Fail if browser frames are globally disabled.
   if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
     return false;
   }
 
   // Fail if this frame doesn't have the mozbrowser attribute.
   bool isBrowser = false;
@@ -374,16 +374,23 @@ nsGenericHTMLFrameElement::BrowserFrameS
                                            "dom.mozBrowserFramesWhitelist")) {
     return false;
   }
 
   // Otherwise, succeed.
   return true;
 }
 
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aResult)
+{
+  *aResult = GetReallyIsBrowser();
+  return NS_OK;
+}
+
 /**
  * Fire a mozbrowser event, if we have permission.
  *
  * @param aEventName the event name (e.g. "locationchange").  "mozbrowser" is
  *        added to the beginning of aEventName automatically.
  * @param aEventType the event type.  Must be either "event" or "customevent".
  * @param aValue the value passed along with the event.  This value will be
  *        set as the event's "detail" property.  This must be empty if
@@ -395,17 +402,17 @@ nsGenericHTMLFrameElement::MaybeFireBrow
   const nsAString &aEventType,
   const nsAString &aValue /* = EmptyString() */)
 {
   MOZ_ASSERT(aEventType.EqualsLiteral("event") ||
              aEventType.EqualsLiteral("customevent"));
   MOZ_ASSERT_IF(aEventType.EqualsLiteral("event"),
                 aValue.IsEmpty());
 
-  if (!BrowserFrameSecurityCheck()) {
+  if (!GetReallyIsBrowser()) {
     return NS_OK;
   }
 
   nsAutoString eventName;
   eventName.AppendLiteral("mozbrowser");
   eventName.Append(aEventName);
 
   nsCOMPtr<nsIDOMEvent> domEvent;
--- a/content/html/content/src/nsGenericHTMLFrameElement.h
+++ b/content/html/content/src/nsGenericHTMLFrameElement.h
@@ -2,42 +2,43 @@
 /* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFrameElement.h"
-#include "nsIDOMMozBrowserFrame.h"
+#include "nsIMozBrowserFrame.h"
 #include "nsIDOMEventListener.h"
 #include "nsIWebProgressListener.h"
 
 /**
  * A helper class for frame elements
  */
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
                                   public nsIFrameLoaderOwner,
-                                  public nsIDOMMozBrowserFrame,
+                                  public nsIMozBrowserFrame,
                                   public nsIWebProgressListener
 {
 public:
   nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                             mozilla::dom::FromParser aFromParser)
     : nsGenericHTMLElement(aNodeInfo)
     , mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
     , mBrowserFrameListenersRegistered(false)
   {
   }
 
   virtual ~nsGenericHTMLFrameElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
   NS_DECL_NSIFRAMELOADEROWNER
   NS_DECL_NSIDOMMOZBROWSERFRAME
+  NS_DECL_NSIMOZBROWSERFRAME
   NS_DECL_NSIWEBPROGRESSLISTENER
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
@@ -56,16 +57,19 @@ public:
 
   // nsIDOMHTMLElement
   NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
   NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
                                                      nsGenericHTMLElement)
 
+  // Non-COM version of nsIMozBrowserFrame::GetReallyIsBrowser.
+  bool GetReallyIsBrowser();
+
 protected:
   /**
    * Listens to titlechanged events from the document inside the iframe and
    * forwards them along to the iframe so it can fire a mozbrowsertitlechange
    * event if appropriate.
    */
   class TitleChangedListener MOZ_FINAL : public nsIDOMEventListener
   {
@@ -87,17 +91,16 @@ protected:
   // This doesn't really ensure a frame loade in all cases, only when
   // it makes sense.
   nsresult EnsureFrameLoader();
   nsresult LoadSrc();
   nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
   nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
 
   void MaybeEnsureBrowserFrameListenersRegistered();
-  bool BrowserFrameSecurityCheck();
   nsresult MaybeFireBrowserEvent(const nsAString &aEventName,
                                  const nsAString &aEventType,
                                  const nsAString &aValue = EmptyString());
 
   nsRefPtr<nsFrameLoader> mFrameLoader;
   nsRefPtr<TitleChangedListener> mTitleChangedListener;
 
   // True when the element is created by the parser
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -46,17 +46,16 @@
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsHTMLDNSPrefetch.h"
-#include "nsDOMMemoryReporter.h"
 
 using namespace mozilla::dom;
 
 class nsHTMLAnchorElement : public nsGenericHTMLElement,
                             public nsIDOMHTMLAnchorElement,
                             public nsILink,
                             public Link
 {
--- a/content/html/content/src/nsHTMLDivElement.cpp
+++ b/content/html/content/src/nsHTMLDivElement.cpp
@@ -38,17 +38,16 @@
 #include "mozilla/Util.h"
 
 #include "nsIDOMHTMLDivElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
-#include "nsDOMMemoryReporter.h"
 
 using namespace mozilla;
 
 class nsHTMLDivElement : public nsGenericHTMLElement,
                          public nsIDOMHTMLDivElement
 {
 public:
   nsHTMLDivElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/html/content/src/nsHTMLOutputElement.cpp
+++ b/content/html/content/src/nsHTMLOutputElement.cpp
@@ -95,18 +95,18 @@ public:
   void DescendantsChanged();
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLOutputElement,
-                                                     nsGenericHTMLFormElement)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLOutputElement,
+                                           nsGenericHTMLFormElement)
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   enum ValueModeFlag {
     eModeDefault,
     eModeValue
   };
 
@@ -131,23 +131,36 @@ nsHTMLOutputElement::nsHTMLOutputElement
 
 nsHTMLOutputElement::~nsHTMLOutputElement()
 {
   if (mTokenList) {
     mTokenList->DropReference();
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLOutputElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLOutputElement,
+                                                nsGenericHTMLFormElement)
+  if (tmp->mTokenList) {
+    tmp->mTokenList->DropReference();
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTokenList)
+  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLOutputElement,
+                                                  nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTokenList,
+                                                       nsDOMTokenList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLOutputElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLOutputElement, nsGenericElement)
 
 DOMCI_NODE_DATA(HTMLOutputElement, nsHTMLOutputElement)
 
-NS_INTERFACE_TABLE_HEAD(nsHTMLOutputElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLOutputElement)
   NS_HTML_CONTENT_INTERFACE_TABLE3(nsHTMLOutputElement,
                                    nsIDOMHTMLOutputElement,
                                    nsIMutationObserver,
                                    nsIConstraintValidation)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLOutputElement,
                                                nsGenericHTMLFormElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLOutputElement)
 
--- a/content/html/content/src/nsHTMLSpanElement.cpp
+++ b/content/html/content/src/nsHTMLSpanElement.cpp
@@ -36,17 +36,16 @@
  * ***** END LICENSE BLOCK ***** */
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIAtom.h"
 #include "nsRuleData.h"
-#include "nsDOMMemoryReporter.h"
 
 class nsHTMLSpanElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLElement
 {
 public:
   nsHTMLSpanElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLSpanElement();
 
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
+++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
@@ -387,19 +387,19 @@ SMILPreserveAspectRatio::GetBaseValue() 
   val.mU.mUint = PackPreserveAspectRatio(mVal->GetBaseValue());
   return val;
 }
 
 void
 SMILPreserveAspectRatio::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(PackPreserveAspectRatio(mVal->GetBaseValue()),
-                       mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimatePreserveAspectRatio();
   }
 }
 
 nsresult
 SMILPreserveAspectRatio::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SMILEnumType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -505,18 +505,20 @@ nsSVGAngle::SMILOrient::GetBaseValue() c
   return val;
 }
 
 void
 nsSVGAngle::SMILOrient::ClearAnimValue()
 {
   if (mAngle->mIsAnimated) {
     mOrientType->SetAnimValue(mOrientType->GetBaseValue());
-    mAngle->SetAnimValue(mAngle->mBaseVal, mAngle->mBaseValUnit, mSVGElement);
     mAngle->mIsAnimated = false;
+    mAngle->mAnimVal = mAngle->mBaseVal;
+    mAngle->mAnimValUnit = mAngle->mBaseValUnit;
+    mSVGElement->DidAnimateAngle(mAngle->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGAngle::SMILOrient::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SVGOrientSMILType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGBoolean.cpp
+++ b/content/svg/content/src/nsSVGBoolean.cpp
@@ -185,18 +185,19 @@ nsSVGBoolean::SMILBool::GetBaseValue() c
   val.mU.mBool = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGBoolean::SMILBool::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimateBoolean(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGBoolean::SMILBool::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SMILBoolType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGCircleElement.cpp
+++ b/content/svg/content/src/nsSVGCircleElement.cpp
@@ -62,16 +62,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGCIRCLEELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGCircleElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGCircleElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGCircleElementBase::)
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
 
@@ -138,16 +141,23 @@ NS_IMETHODIMP nsSVGCircleElement::GetCy(
 NS_IMETHODIMP nsSVGCircleElement::GetR(nsIDOMSVGAnimatedLength * *aR)
 {
   return mLengthAttributes[R].ToDOMAnimatedLength(aR, this);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGCircleElement::HasValidDimensions() const
+{
+  return mLengthAttributes[R].IsExplicitlySet() &&
+         mLengthAttributes[R].GetAnimValInSpecifiedUnits() > 0;
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGCircleElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -44,17 +44,16 @@
   It implements all the common DOM interfaces and handles attributes.
 */
 
 #include "mozilla/css/StyleRule.h"
 #include "nsAutoPtr.h"
 #include "nsChangeHint.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsDOMMemoryReporter.h"
 #include "nsError.h"
 #include "nsGenericElement.h"
 #include "nsISupportsImpl.h"
 #include "nsStyledElement.h"
 
 class nsIDOMSVGElement;
 class nsIDOMSVGSVGElement;
 class nsSVGAngle;
@@ -190,16 +189,19 @@ public:
   virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix) {/*no-op*/}
 
   bool IsStringAnimatable(PRUint8 aAttrEnum) {
     return GetStringInfo().mStringInfo[aAttrEnum].mIsAnimatable;
   }
   bool NumberAttrAllowsPercentage(PRUint8 aAttrEnum) {
     return GetNumberInfo().mNumberInfo[aAttrEnum].mPercentagesAllowed;
   }
+  virtual bool HasValidDimensions() const {
+    return true;
+  }
   void SetLength(nsIAtom* aName, const nsSVGLength2 &aLength);
 
   nsAttrValue WillChangeLength(PRUint8 aAttrEnum);
   nsAttrValue WillChangeNumberPair(PRUint8 aAttrEnum);
   nsAttrValue WillChangeIntegerPair(PRUint8 aAttrEnum);
   nsAttrValue WillChangeAngle(PRUint8 aAttrEnum);
   nsAttrValue WillChangeViewBox();
   nsAttrValue WillChangePreserveAspectRatio();
--- a/content/svg/content/src/nsSVGEllipseElement.cpp
+++ b/content/svg/content/src/nsSVGEllipseElement.cpp
@@ -63,16 +63,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGELLIPSEELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGEllipseElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGEllipseElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGEllipseElementBase::)
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
 
@@ -146,16 +149,25 @@ NS_IMETHODIMP nsSVGEllipseElement::GetRx
 NS_IMETHODIMP nsSVGEllipseElement::GetRy(nsIDOMSVGAnimatedLength * *aRy)
 {
   return mLengthAttributes[RY].ToDOMAnimatedLength(aRy, this);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGEllipseElement::HasValidDimensions() const
+{
+  return mLengthAttributes[RX].IsExplicitlySet() &&
+         mLengthAttributes[RX].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[RY].IsExplicitlySet() &&
+         mLengthAttributes[RY].GetAnimValInSpecifiedUnits() > 0;
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGEllipseElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -195,18 +195,19 @@ nsSVGEnum::SMILEnum::GetBaseValue() cons
   val.mU.mUint = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGEnum::SMILEnum::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimateEnum(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGEnum::SMILEnum::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SMILEnumType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGFilterElement.cpp
+++ b/content/svg/content/src/nsSVGFilterElement.cpp
@@ -214,16 +214,25 @@ nsSVGFilterElement::Invalidate()
         filter->Invalidate();
     }
   }
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGFilterElement::HasValidDimensions() const
+{
+  return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
+           mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+         (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
+           mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0);
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGFilterElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::IntegerPairAttributesInfo
--- a/content/svg/content/src/nsSVGFilterElement.h
+++ b/content/svg/content/src/nsSVGFilterElement.h
@@ -78,16 +78,19 @@ public:
   // nsIContent
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   // Invalidate users of this filter
   void Invalidate();
 
   virtual nsXPCClassInfo* GetClassInfo();
+
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual IntegerPairAttributesInfo GetIntegerPairInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   enum { X, Y, WIDTH, HEIGHT };
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -305,16 +305,25 @@ nsSVGFE::IsAttributeMapped(const nsIAtom
   
   return FindAttributeDependence(name, map) ||
     nsSVGFEBase::IsAttributeMapped(name);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGFE::HasValidDimensions() const
+{
+  return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
+           mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+         (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
+           mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0);
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGFE::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //---------------------Gaussian Blur------------------------
--- a/content/svg/content/src/nsSVGFilters.h
+++ b/content/svg/content/src/nsSVGFilters.h
@@ -153,16 +153,19 @@ public:
   
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
+  // nsSVGElement interface
+  virtual bool HasValidDimensions() const;
+
   virtual nsSVGString& GetResultImageName() = 0;
   // Return a list of all image names used as sources. Default is to
   // return no sources.
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   // Compute the bounding box of the filter output. The default is just the
   // union of the source bounding boxes. The caller is
   // responsible for clipping this to the filter primitive subregion, so
   // if the filter fills its filter primitive subregion, it can just
--- a/content/svg/content/src/nsSVGForeignObjectElement.cpp
+++ b/content/svg/content/src/nsSVGForeignObjectElement.cpp
@@ -131,16 +131,25 @@ nsSVGForeignObjectElement::PrependLocalT
   gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
   if (aWhich == eChildToUserSpace) {
     return toUserSpace;
   }
   NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
   return toUserSpace * fromUserSpace;
 }
 
+/* virtual */ bool
+nsSVGForeignObjectElement::HasValidDimensions() const
+{
+  return mLengthAttributes[WIDTH].IsExplicitlySet() &&
+         mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[HEIGHT].IsExplicitlySet() &&
+         mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+}
+
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
 nsSVGForeignObjectElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sFEFloodMap,
--- a/content/svg/content/src/nsSVGForeignObjectElement.h
+++ b/content/svg/content/src/nsSVGForeignObjectElement.h
@@ -66,16 +66,17 @@ public:
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGForeignObjectElementBase::)
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
+  virtual bool HasValidDimensions() const;
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
--- a/content/svg/content/src/nsSVGImageElement.cpp
+++ b/content/svg/content/src/nsSVGImageElement.cpp
@@ -262,16 +262,25 @@ nsSVGImageElement::ConstructPath(gfxCont
     return;
 
   aCtx->Rectangle(gfxRect(x, y, width, height));
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGImageElement::HasValidDimensions() const
+{
+  return mLengthAttributes[WIDTH].IsExplicitlySet() &&
+         mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[HEIGHT].IsExplicitlySet() &&
+         mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGImageElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 SVGAnimatedPreserveAspectRatio *
--- a/content/svg/content/src/nsSVGImageElement.h
+++ b/content/svg/content/src/nsSVGImageElement.h
@@ -85,16 +85,19 @@ public:
 
   virtual nsEventStates IntrinsicState() const;
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   nsresult CopyInnerTo(nsGenericElement* aDest) const;
 
   void MaybeLoadSVGImage();
 
   bool IsImageSrcSetDisabled() const;
 
--- a/content/svg/content/src/nsSVGInteger.cpp
+++ b/content/svg/content/src/nsSVGInteger.cpp
@@ -180,18 +180,19 @@ nsSVGInteger::SMILInteger::GetBaseValue(
   val.mU.mInt = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGInteger::SMILInteger::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimateInteger(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGInteger::SMILInteger::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SMILIntegerType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGIntegerPair.cpp
+++ b/content/svg/content/src/nsSVGIntegerPair.cpp
@@ -236,18 +236,20 @@ nsSVGIntegerPair::SMILIntegerPair::GetBa
   val.mU.mIntPair[1] = mVal->mBaseVal[1];
   return val;
 }
 
 void
 nsSVGIntegerPair::SMILIntegerPair::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal[0] = mVal->mBaseVal[0];
+    mVal->mAnimVal[1] = mVal->mBaseVal[1];
+    mSVGElement->DidAnimateIntegerPair(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGIntegerPair::SMILIntegerPair::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SVGIntegerPairSMILType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -565,18 +565,19 @@ nsSVGLength2::SMILLength::GetBaseValue()
   val.mU.mDouble = mVal->GetBaseValue(mSVGElement);
   return val;
 }
 
 void
 nsSVGLength2::SMILLength::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValueInSpecifiedUnits(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimateLength(mVal->mAttrEnum);
   }  
 }
 
 nsresult
 nsSVGLength2::SMILLength::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
     "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -301,16 +301,25 @@ nsSVGMarkerElement::UnsetAttr(PRInt32 aN
 
 void 
 nsSVGMarkerElement::SetParentCoordCtxProvider(nsSVGSVGElement *aContext)
 {
   mCoordCtx = aContext;
   mViewBoxToViewportTransform = nsnull;
 }
 
+/* virtual */ bool
+nsSVGMarkerElement::HasValidDimensions() const
+{
+  return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() ||
+           mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+         (!mLengthAttributes[MARKERHEIGHT].IsExplicitlySet() || 
+           mLengthAttributes[MARKERHEIGHT].GetAnimValInSpecifiedUnits() > 0);
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGMarkerElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::AngleAttributesInfo
--- a/content/svg/content/src/nsSVGMarkerElement.h
+++ b/content/svg/content/src/nsSVGMarkerElement.h
@@ -128,16 +128,19 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual bool GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                          nsAString& aResult) const;
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   // public helpers
   gfxMatrix GetMarkerTransform(float aStrokeWidth,
                                float aX, float aY, float aAutoAngle);
   nsSVGViewBoxRect GetViewBoxRect();
   gfxMatrix GetViewBoxTransform();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
--- a/content/svg/content/src/nsSVGMaskElement.cpp
+++ b/content/svg/content/src/nsSVGMaskElement.cpp
@@ -131,16 +131,25 @@ NS_IMETHODIMP nsSVGMaskElement::GetWidth
 NS_IMETHODIMP nsSVGMaskElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
 {
   return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGMaskElement::HasValidDimensions() const
+{
+  return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
+           mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+         (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
+           mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0);
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGMaskElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
--- a/content/svg/content/src/nsSVGMaskElement.h
+++ b/content/svg/content/src/nsSVGMaskElement.h
@@ -71,16 +71,19 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsSVGElement::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
 
   // nsIContent interface
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
+
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
 
   // nsIDOMSVGMaskElement values
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
--- a/content/svg/content/src/nsSVGNumber2.cpp
+++ b/content/svg/content/src/nsSVGNumber2.cpp
@@ -222,18 +222,19 @@ nsSVGNumber2::SMILNumber::GetBaseValue()
   val.mU.mDouble = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGNumber2::SMILNumber::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal = mVal->mBaseVal;
+    mSVGElement->DidAnimateNumber(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGNumber2::SMILNumber::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGNumberPair.cpp
+++ b/content/svg/content/src/nsSVGNumberPair.cpp
@@ -234,18 +234,20 @@ nsSVGNumberPair::SMILNumberPair::GetBase
   val.mU.mNumberPair[1] = mVal->mBaseVal[1];
   return val;
 }
 
 void
 nsSVGNumberPair::SMILNumberPair::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
-    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
     mVal->mIsAnimated = false;
+    mVal->mAnimVal[0] = mVal->mBaseVal[0];
+    mVal->mAnimVal[1] = mVal->mBaseVal[1];
+    mSVGElement->DidAnimateNumberPair(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGNumberPair::SMILNumberPair::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ASSERTION(aValue.mType == &SVGNumberPairSMILType::sSingleton,
                "Unexpected type to assign animated value");
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -336,16 +336,22 @@ nsSVGPathElement::CreateSVGPathSegCurvet
   nsIDOMSVGPathSeg* seg = NS_NewSVGPathSegCurvetoQuadraticSmoothRel(x, y);
   NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
   return CallQueryInterface(seg, _retval);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGPathElement::HasValidDimensions() const
+{
+  return !mD.GetAnimValue().IsEmpty();
+}
+
 nsSVGElement::NumberAttributesInfo
 nsSVGPathElement::GetNumberInfo()
 {
   return NumberAttributesInfo(&mPathLength, &sNumberInfo, 1);
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGAnimatedPathData methods:
--- a/content/svg/content/src/nsSVGPathElement.h
+++ b/content/svg/content/src/nsSVGPathElement.h
@@ -71,16 +71,19 @@ public:
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGPathElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGPathElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPathElementBase::)
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   // nsSVGPathGeometryElement methods:
   virtual bool AttributeDefinesGeometry(const nsIAtom *aName);
   virtual bool IsMarkable();
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual already_AddRefed<gfxFlattenedPath> GetFlattenedPath(const gfxMatrix &aMatrix);
 
--- a/content/svg/content/src/nsSVGPatternElement.cpp
+++ b/content/svg/content/src/nsSVGPatternElement.cpp
@@ -209,16 +209,25 @@ SVGAnimatedTransformList*
 nsSVGPatternElement::GetAnimatedTransformList()
 {
   if (!mPatternTransform) {
     mPatternTransform = new SVGAnimatedTransformList();
   }
   return mPatternTransform;
 }
 
+/* virtual */ bool
+nsSVGPatternElement::HasValidDimensions() const
+{
+  return mLengthAttributes[WIDTH].IsExplicitlySet() &&
+         mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[HEIGHT].IsExplicitlySet() &&
+         mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGPatternElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
--- a/content/svg/content/src/nsSVGPatternElement.h
+++ b/content/svg/content/src/nsSVGPatternElement.h
@@ -91,16 +91,19 @@ public:
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   virtual mozilla::SVGAnimatedTransformList* GetAnimatedTransformList();
   virtual nsIAtom* GetTransformListAttrName() const {
     return nsGkAtoms::patternTransform;
   }
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
--- a/content/svg/content/src/nsSVGRectElement.cpp
+++ b/content/svg/content/src/nsSVGRectElement.cpp
@@ -62,16 +62,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGRECTELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGRectElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGRectElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGRectElementBase::)
 
+  // nsSVGSVGElement methods:
+  virtual bool HasValidDimensions() const;
+
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
 
@@ -159,16 +162,25 @@ NS_IMETHODIMP nsSVGRectElement::GetRx(ns
 NS_IMETHODIMP nsSVGRectElement::GetRy(nsIDOMSVGAnimatedLength * *aRy)
 {
   return mLengthAttributes[RY].ToDOMAnimatedLength(aRy, this);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+/* virtual */ bool
+nsSVGRectElement::HasValidDimensions() const
+{
+  return mLengthAttributes[WIDTH].IsExplicitlySet() &&
+         mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[HEIGHT].IsExplicitlySet() &&
+         mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGRectElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1184,16 +1184,26 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxT
   case nsSVGUtils::Y:
     return h;
   case nsSVGUtils::XY:
     return float(nsSVGUtils::ComputeNormalizedHypotenuse(w, h));
   }
   return 0;
 }
 
+void
+nsSVGSVGElement::SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const
+{
+  NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height,
+               "The clue is in the function name");
+
+  PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT;
+  aTarget->SetLength(aName, mLengthAttributes[index]);
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ gfxMatrix
 nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                                           TransformTypes aWhich) const
 {
   NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
@@ -1224,16 +1234,26 @@ nsSVGSVGElement::PrependLocalTransformsT
     zoomPanTM.Scale(mCurrentScale, mCurrentScale);
     return GetViewBoxTransform() * zoomPanTM * aMatrix;
   }
 
   // outer-<svg>, but inline in some other content:
   return GetViewBoxTransform() * aMatrix;
 }
 
+/* virtual */ bool
+nsSVGSVGElement::HasValidDimensions() const
+{
+  return !IsInner() ||
+    ((!mLengthAttributes[WIDTH].IsExplicitlySet() ||
+       mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+     (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
+       mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0));
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGSVGElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -183,19 +183,22 @@ public:
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
+  virtual bool HasValidDimensions() const;
  
   // nsSVGSVGElement methods:
   float GetLength(PRUint8 mCtxType);
+  // Copy our width or height to the target
+  void SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const;
 
   // public helpers:
   gfxMatrix GetViewBoxTransform() const;
   bool      HasValidViewbox() const { return mViewBox.IsValid(); }
 
   // This services any pending notifications for the transform on on this root
   // <svg> node needing to be recalculated.  (Only applicable in
   // SVG-as-an-image documents.)
--- a/content/svg/content/src/nsSVGUseElement.cpp
+++ b/content/svg/content/src/nsSVGUseElement.cpp
@@ -35,17 +35,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "nsSVGUseElement.h"
 #include "nsIDOMSVGGElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMSVGSVGElement.h"
+#include "nsSVGSVGElement.h"
 #include "nsIDOMSVGSymbolElement.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "mozilla/dom/Element.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -283,29 +283,25 @@ nsSVGUseElement::CreateAnonymousContent(
       tag != nsGkAtoms::ellipse &&
       tag != nsGkAtoms::line &&
       tag != nsGkAtoms::polyline &&
       tag != nsGkAtoms::polygon &&
       tag != nsGkAtoms::image &&
       tag != nsGkAtoms::use)
     return nsnull;
 
-  // Make sure the use attributes are valid
-  if (!HasValidDimensions())
-    return nsnull;
-
   // circular loop detection
 
   // check 1 - check if we're a document descendent of the target
   if (nsContentUtils::ContentIsDescendantOf(this, targetContent))
     return nsnull;
 
   // check 2 - check if we're a clone, and if we already exist in the hierarchy
-  if (this->GetParent() && mOriginal) {
-    for (nsCOMPtr<nsIContent> content = this->GetParent();
+  if (GetParent() && mOriginal) {
+    for (nsCOMPtr<nsIContent> content = GetParent();
          content;
          content = content->GetParent()) {
       nsCOMPtr<nsIDOMSVGUseElement> useElement = do_QueryInterface(content);
 
       if (useElement) {
         nsRefPtr<nsSVGUseElement> useImpl;
         useElement->QueryInterface(NS_GET_IID(nsSVGUseElement),
                                    getter_AddRefs(useImpl));
@@ -402,53 +398,53 @@ void
 nsSVGUseElement::DestroyAnonymousContent()
 {
   nsContentUtils::DestroyAnonymousContent(&mClone);
 }
 
 //----------------------------------------------------------------------
 // implementation helpers
 
-bool nsSVGUseElement::HasValidDimensions()
-{
-  nsSVGSVGElement *ctx = GetCtx();
-
-  return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
-           mLengthAttributes[WIDTH].GetAnimValue(ctx) > 0) &&
-         (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
-           mLengthAttributes[HEIGHT].GetAnimValue(ctx) > 0);
-}
-
 void
-nsSVGUseElement::SyncWidthHeight(nsIAtom* aName)
+nsSVGUseElement::SyncWidthOrHeight(nsIAtom* aName)
 {
   NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height,
                "The clue is in the function name");
 
-  if (HasValidDimensions() == !mClone) {
-    TriggerReclone();
+  if (!mClone) {
     return;
   }
 
-  if (mClone) {
-    nsCOMPtr<nsIDOMSVGSymbolElement> symbol = do_QueryInterface(mClone);
-    nsCOMPtr<nsIDOMSVGSVGElement>    svg    = do_QueryInterface(mClone);
+  nsCOMPtr<nsIDOMSVGSymbolElement> symbol = do_QueryInterface(mClone);
+  nsCOMPtr<nsIDOMSVGSVGElement>    svg    = do_QueryInterface(mClone);
+
+  if (symbol || svg) {
+    nsSVGElement *target = static_cast<nsSVGElement*>(mClone.get());
+    PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT;
 
-    if (symbol || svg) {
-      PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT;
-      if (mLengthAttributes[index].IsExplicitlySet()) {
-        static_cast<nsSVGElement*>(mClone.get())->
-          SetLength(aName, mLengthAttributes[index]);
-      } else {
-        // Our width/height attribute is now no longer explicitly set, so we
-        // need to revert the clone's width/height to the width/height of the
-        // content that's being cloned.
-        TriggerReclone();
-      }
+    if (mLengthAttributes[index].IsExplicitlySet()) {
+      target->SetLength(aName, mLengthAttributes[index]);
+      return;
     }
+    if (svg) {
+      // Our width/height attribute is now no longer explicitly set, so we
+      // need to revert the clone's width/height to the width/height of the
+      // content that's being cloned.
+      nsSVGSVGElement* svgElement =
+        static_cast<nsSVGSVGElement*>(mSource.get());
+      svgElement->SyncWidthOrHeight(aName, target);
+      return;
+    }
+    // Our width/height attribute is now no longer explicitly set, so we
+    // need to set the value to 100%
+    nsSVGLength2 length;
+    length.Init(nsSVGUtils::XY, 0xff,
+                100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE);
+    target->SetLength(aName, length);
+    return;
   }
 }
 
 void
 nsSVGUseElement::LookupHref()
 {
   nsAutoString href;
   mStringAttributes[HREF].GetAnimValue(href, this);
@@ -506,16 +502,25 @@ nsSVGUseElement::PrependLocalTransformsT
   gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
   if (aWhich == eChildToUserSpace) {
     return toUserSpace;
   }
   NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
   return toUserSpace * fromUserSpace;
 }
 
+/* virtual */ bool
+nsSVGUseElement::HasValidDimensions() const
+{
+  return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
+           mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
+         (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
+           mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0);
+}
+
 nsSVGElement::LengthAttributesInfo
 nsSVGUseElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::StringAttributesInfo
--- a/content/svg/content/src/nsSVGUseElement.h
+++ b/content/svg/content/src/nsSVGUseElement.h
@@ -100,16 +100,17 @@ public:
   // for nsSVGUseFrame's nsIAnonymousContentCreator implementation.
   nsIContent* CreateAnonymousContent();
   nsIContent* GetAnonymousContent() const { return mClone; }
   void DestroyAnonymousContent();
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
+  virtual bool HasValidDimensions() const;
 
   // nsIContent interface
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   class SourceReference : public nsReferencedElement {
@@ -125,18 +126,17 @@ protected:
     }
   private:
     nsSVGUseElement* mContainer;
   };
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual StringAttributesInfo GetStringInfo();
 
-  bool HasValidDimensions();
-  void SyncWidthHeight(nsIAtom *aName);
+  void SyncWidthOrHeight(nsIAtom *aName);
   void LookupHref();
   void TriggerReclone();
   void UnlinkSource();
 
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
--- a/content/xml/content/src/nsXMLCDATASection.cpp
+++ b/content/xml/content/src/nsXMLCDATASection.cpp
@@ -35,18 +35,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMCDATASection.h"
 #include "nsGenericDOMDataNode.h"
 #include "nsGkAtoms.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
-#include "nsDOMMemoryReporter.h"
-
 
 class nsXMLCDATASection : public nsGenericDOMDataNode,
                           public nsIDOMCDATASection
 {
 public:
   nsXMLCDATASection(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsXMLCDATASection();
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11751,8 +11751,23 @@ nsDocShell::GetCanExecuteScripts(bool *a
             NS_ERROR("cannot get a docshell from a treeItem!");
           }
 #endif // DEBUG
       } while (treeItem && docshell);
   }
 
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsDocShell::GetIsBrowserFrame(bool *aOut)
+{
+  NS_ENSURE_ARG_POINTER(aOut);
+  *aOut = mIsBrowserFrame;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetIsBrowserFrame(bool aValue)
+{
+  mIsBrowserFrame = aValue;
+  return NS_OK;
+}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -799,16 +799,17 @@ protected:
     bool                       mObserveErrorPages;
     bool                       mAllowAuth;
     bool                       mAllowKeywordFixup;
     bool                       mIsOffScreenBrowser;
     bool                       mIsActive;
     bool                       mIsAppTab;
     bool                       mUseGlobalHistory;
     bool                       mInPrivateBrowsing;
+    bool                       mIsBrowserFrame;
 
     // This boolean is set to true right before we fire pagehide and generally
     // unset when we embed a new content viewer.  While it's true no navigation
     // is allowed in this docshell.
     bool                       mFiredUnloadEvent;
 
     // this flag is for bug #21358. a docshell may load many urls
     // which don't result in new documents being created (i.e. a new
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -67,17 +67,17 @@ interface nsIRequest;
 interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 
-[scriptable, uuid(0615d1a6-313f-11e1-a043-6c626d69675c)]
+[scriptable, uuid(DBD39C21-5788-4C68-9D97-0FCEE289BCE1)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -597,9 +597,21 @@ interface nsIDocShell : nsISupports
    */
   attribute nsIAtom parentCharset;
 
   /*
    * In a child docshell, this is the source of parentCharset
    * @see nsIParser
    */
   attribute PRInt32 parentCharsetSource;
+
+  /*
+   * Is this docshell a browser frame (i.e., does it correspond to an <iframe
+   * mozbrowser>)?  The frameloader is responsible for setting this property
+   * when it initializes the docshell.
+   *
+   * If so, this docshell should act like a chrome/content boundary for the
+   * purposes of window.top and window.parent.
+   *
+   * See also nsIMozBrowserFrame.
+   */
+  attribute bool isBrowserFrame;
 };
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -99,17 +99,17 @@ EXPORTS = \
   nsIScriptRuntime.h \
   nsIScriptTimeoutHandler.h \
   nsPIDOMWindow.h \
   nsPIWindowRoot.h \
   nsFocusManager.h \
   nsWrapperCache.h \
   nsContentPermissionHelper.h \
   nsStructuredCloneContainer.h \
-  nsDOMMemoryReporter.h \
+  nsWindowMemoryReporter.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   DOMError.h \
   DOMRequest.h \
   StructuredCloneTags.h \
   $(NULL)
@@ -134,17 +134,17 @@ CPPSRCS =			\
 	nsDOMClassInfo.cpp	\
 	nsScriptNameSpaceManager.cpp \
 	nsDOMScriptObjectFactory.cpp \
 	nsQueryContentEventResult.cpp \
 	nsContentPermissionHelper.cpp \
 	nsStructuredCloneContainer.cpp \
 	nsDOMNavigationTiming.cpp \
 	nsPerformance.cpp	\
-	nsDOMMemoryReporter.cpp \
+	nsWindowMemoryReporter.cpp \
 	DOMError.cpp \
 	DOMRequest.cpp \
 	Navigator.cpp \
 	$(NULL)
 
 include $(topsrcdir)/dom/dom-config.mk
 
 ifdef MOZ_JSDEBUGGER
--- a/dom/base/domerr.msg
+++ b/dom/base/domerr.msg
@@ -61,21 +61,16 @@ DOM_MSG_DEF_(SECURITY_ERR, "SecurityErro
 DOM_MSG_DEF_(NETWORK_ERR, "NetworkError", "A network error occurred.")
 DOM_MSG_DEF_(ABORT_ERR, "AbortError", "The operation was aborted. ")
 DOM_MSG_DEF_(URL_MISMATCH_ERR, "URLMismatchError", "The given URL does not match another URL.")
 DOM_MSG_DEF_(QUOTA_EXCEEDED_ERR, "QuotaExceededError", "The quota has been exceeded.")
 DOM_MSG_DEF_(TIMEOUT_ERR, "TimeoutError", "The operation timed out.")
 DOM_MSG_DEF_(INVALID_NODE_TYPE_ERR, "InvalidNodeTypeError", "The supplied node is incorrect or has an incorrect ancestor for this operation.")
 DOM_MSG_DEF_(DATA_CLONE_ERR, "DataCloneError", "The object could not be cloned.")
 
-/* DOM error codes from http://www.w3.org/TR/DOM-Level-2/range.html */
-
-DOM_MSG_DEF(NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR, "The boundary-points of a range does not meet specific requirements.")
-DOM_MSG_DEF(NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR, "The container of an boundary-point of a range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.")
-
 /* SVG DOM error codes from http://www.w3.org/TR/SVG11/svgdom.html */
 
 DOM_MSG_DEF(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR, "Unknown or invalid type")
 DOM_MSG_DEF(NS_ERROR_DOM_SVG_INVALID_VALUE_ERR, "One of the parameters has an invalid value")
 DOM_MSG_DEF(NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE, "The matrix could not be computed")
 
 /* DOM error codes from http://www.w3.org/TR/DOM-Level-3-XPath/ */
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -135,50 +135,42 @@
 #include "nsIDOMPerformanceNavigation.h"
 #include "nsIDOMPerformance.h"
 #include "nsClientRect.h"
 
 // DOM core includes
 #include "nsDOMError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMNode.h"
-#include "nsIDOMNodeList.h"
 #include "nsIDOMNamedNodeMap.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMDOMTokenList.h"
 #include "nsIDOMDOMSettableTokenList.h"
 
 #include "nsDOMStringMap.h"
 
 // HTMLFormElement helper includes
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
-#include "nsIDOMHTMLCollection.h"
-#include "nsIHTMLCollection.h"
 #include "nsHTMLDocument.h"
 
 // Constraint Validation API helper includes
 #include "nsIDOMValidityState.h"
 
 // HTMLSelectElement helper includes
 #include "nsIDOMHTMLSelectElement.h"
 
 // HTMLEmbed/ObjectElement helper includes
 #include "nsNPAPIPluginInstance.h"
 #include "nsIObjectFrame.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIPluginHost.h"
 
-// HTMLOptionsCollection includes
 #include "nsIDOMHTMLOptionElement.h"
-#include "nsIDOMHTMLOptionsCollection.h"
-
-// ContentList includes
-#include "nsContentList.h"
 #include "nsGenericElement.h"
 
 // Event related includes
 #include "nsEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 
 // CSS related includes
 #include "nsIDOMStyleSheet.h"
@@ -324,17 +316,16 @@
 #include "nsIDOMMozCSSKeyframesRule.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsDOMCSSValueList.h"
 #include "nsIDOMDeviceOrientationEvent.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMRangeException.h"
 #include "nsIDOMNodeIterator.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMCrypto.h"
 #include "nsIDOMCRMFObject.h"
 #include "nsIControllers.h"
@@ -780,17 +771,18 @@ static nsDOMClassInfoData sClassInfoData
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Text, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Comment, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CDATASection, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ProcessingInstruction, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(NodeList, nsNodeListSH, ARRAY_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(NodeList, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(NamedNodeMap, nsNamedNodeMapSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   // Misc Core related classes
 
   // Event
   NS_DEFINE_CLASSINFO_DATA(Event, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -819,23 +811,20 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DeviceRotationRate, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // Misc HTML classes
   NS_DEFINE_CLASSINFO_DATA(HTMLDocument, nsHTMLDocumentSH,
                            DOCUMENT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_GETPROPERTY)
-  NS_DEFINE_CLASSINFO_DATA(HTMLOptionsCollection,
-                           nsHTMLOptionsCollectionSH,
-                           ARRAY_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_SETPROPERTY)
-  NS_DEFINE_CLASSINFO_DATA(HTMLCollection,
-                           nsHTMLCollectionSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(HTMLOptionsCollection, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(HTMLCollection, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // HTML element classes
   NS_DEFINE_CLASSINFO_DATA(HTMLElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLAnchorElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLAppletElement, nsHTMLPluginObjElementSH,
                            EXTERNAL_OBJ_SCRIPTABLE_FLAGS)
@@ -1029,24 +1018,22 @@ static nsDOMClassInfoData sClassInfoData
   // DOM Chrome Window class.
   NS_DEFINE_CLASSINFO_DATA(ChromeWindow, nsWindowSH,
                            DEFAULT_SCRIPTABLE_FLAGS |
                            WINDOW_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSRGBColor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(RangeException, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(CSSValueList, nsCSSValueListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(ContentList, HTMLCollection,
-                                     nsContentListSH, ARRAY_SCRIPTABLE_FLAGS)
+                                     nsDOMGenericSH,
+                                     DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XMLStylesheetProcessingInstruction, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ImageDocument, nsHTMLDocumentSH,
                            DOCUMENT_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_XUL
@@ -3103,21 +3090,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
     DOM_CLASSINFO_WINDOW_MAP_ENTRIES(true)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(RangeException, nsIDOMRangeException)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMRangeException)
-    DOM_CLASSINFO_MAP_ENTRY(nsIException)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentList, nsIDOMHTMLCollection)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCollection)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(ImageDocument, nsIImageDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIImageDocument)
@@ -4455,17 +4437,17 @@ nsDOMClassInfo::Init()
 // static
 PRInt32
 nsDOMClassInfo::GetArrayIndexFromId(JSContext *cx, jsid id, bool *aIsNumber)
 {
   if (aIsNumber) {
     *aIsNumber = false;
   }
 
-  jsint i;
+  int i;
   if (JSID_IS_INT(id)) {
       i = JSID_TO_INT(id);
   } else {
       JSAutoRequest ar(cx);
 
       jsval idval;
       double array_index;
       if (!::JS_IdToValue(cx, id, &idval) ||
@@ -8015,84 +7997,16 @@ nsArraySH::GetProperty(nsIXPConnectWrapp
       rv = NS_SUCCESS_I_DID_SOMETHING;
     }
   }
 
   return rv;
 }
 
 
-// NodeList scriptable helper
-
-nsresult
-nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                        JSObject *globalObj, JSObject **parentObj)
-{
-  nsINodeList* list = static_cast<nsINodeList*>(nativeObj);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(nativeObj);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsINodeList pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ASSERTION(list_qi == list, "Uh, fix QI!");
-  }
-#endif
-
-  nsINode* native_parent = list->GetParentObject();
-
-  nsresult rv =
-    WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
-}
-
-nsresult
-nsNodeListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj, PRUint32 *length)
-{
-  nsINodeList* list = static_cast<nsINodeList*>(GetNative(wrapper, obj));
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsINodeList> list_qi = do_QueryWrappedNative(wrapper, obj);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsINodeList pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
-  }
-#endif
-
-  return list->GetLength(length);
-}
-
-nsISupports*
-nsNodeListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                        nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsINodeList* list = static_cast<nsINodeList*>(aNative);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(aNative);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsINodeList pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
-  }
-#endif
-
-  nsINode *node;
-  *aCache = node = list->GetNodeAt(aIndex);
-  return node;
-}
-
-
 // StringList scriptable helper
 
 nsresult
 nsStringListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
                             nsAString& aResult)
 {
   nsCOMPtr<nsIDOMDOMStringList> list(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
@@ -8243,156 +8157,16 @@ nsNamedNodeMapSH::GetNamedItem(nsISuppor
   nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
 
   nsINode *attr;
   *aCache = attr = map->GetNamedItem(aName, aResult);
   return attr;
 }
 
 
-// HTMLCollection helper
-
-nsresult
-nsHTMLCollectionSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                              JSObject *globalObj, JSObject **parentObj)
-{
-  nsIHTMLCollection* list = static_cast<nsIHTMLCollection*>(nativeObj);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsIHTMLCollection> list_qi = do_QueryInterface(nativeObj);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsIHTMLCollection pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ASSERTION(list_qi == list, "Uh, fix QI!");
-  }
-#endif
-
-  nsINode* native_parent = list->GetParentObject();
-
-  nsresult rv =
-    WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
-}
-
-nsresult
-nsHTMLCollectionSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                              JSObject *obj, PRUint32 *length)
-{
-  nsIHTMLCollection* collection =
-    static_cast<nsIHTMLCollection*>(GetNative(wrapper, obj));
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsIHTMLCollection> collection_qi =
-      do_QueryWrappedNative(wrapper, obj);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsIHTMLCollection pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(collection_qi == collection, "Uh, fix QI!");
-  }
-#endif
-
-  return collection->GetLength(length);
-}
-
-nsISupports*
-nsHTMLCollectionSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                              nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsIHTMLCollection* collection = static_cast<nsIHTMLCollection*>(aNative);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsIHTMLCollection> collection_qi = do_QueryInterface(aNative);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsIHTMLCollection pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(collection_qi == collection, "Uh, fix QI!");
-  }
-#endif
-
-  nsINode *item;
-  *aCache = item = collection->GetNodeAt(aIndex);
-  return item;
-}
-
-nsISupports*
-nsHTMLCollectionSH::GetNamedItem(nsISupports *aNative,
-                                 const nsAString& aName,
-                                 nsWrapperCache **aCache,
-                                 nsresult *aResult)
-{
-  nsIHTMLCollection* collection = static_cast<nsIHTMLCollection*>(aNative);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsIHTMLCollection> collection_qi = do_QueryInterface(aNative);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsIHTMLCollection pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(collection_qi == collection, "Uh, fix QI!");
-  }
-#endif
-
-  return collection->GetNamedItem(aName, aCache);
-}
-
-
-// ContentList helper
-nsresult
-nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                           JSObject *globalObj, JSObject **parentObj)
-{
-  nsContentList *contentList = nsContentList::FromSupports(nativeObj);
-  nsINode *native_parent = contentList->GetParentObject();
-
-  if (!native_parent) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsresult rv =
-    WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
-}
-
-nsresult
-nsContentListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                           JSObject *obj, PRUint32 *length)
-{
-  nsContentList *list =
-    nsContentList::FromSupports(GetNative(wrapper, obj));
-
-  return list->GetLength(length);
-}
-
-nsISupports*
-nsContentListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                           nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsContentList *list = nsContentList::FromSupports(aNative);
-
-  nsIContent *item;
-  *aCache = item = list->GetNodeAt(aIndex);
-  return item;
-}
-
-nsISupports*
-nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                              nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsContentList *list = nsContentList::FromSupports(aNative);
-
-  return list->GetNamedItem(aName, aCache);
-}
-
 NS_IMETHODIMP
 nsDOMStringMapSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                              JSObject *obj, jsid id, PRUint32 flags,
                              JSObject **objp, bool *_retval)
 {
   nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
   NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
 
@@ -9912,41 +9686,16 @@ nsHTMLPluginObjElementSH::NewResolve(nsI
   nsRefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, getter_AddRefs(pi));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return nsElementSH::NewResolve(wrapper, cx, obj, id, flags, objp,
                                  _retval);
 }
  
-// HTMLOptionsCollection helper
-
-NS_IMETHODIMP
-nsHTMLOptionsCollectionSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
-                                       JSContext *cx, JSObject *obj, jsid id,
-                                       jsval *vp, bool *_retval)
-{
-  PRInt32 n = GetArrayIndexFromId(cx, id);
-
-  if (n < 0) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDOMHTMLOptionsCollection> oc =
-    do_QueryWrappedNative(wrapper, obj);
-  NS_ENSURE_TRUE(oc, NS_ERROR_UNEXPECTED);
-
-  nsresult rv = nsHTMLSelectElementSH::SetOption(cx, vp, n, oc);
-  if (NS_SUCCEEDED(rv)) {
-    rv = NS_SUCCESS_I_DID_SOMETHING;
-  }
-  return rv;
-}
-
-
 // Plugin helper
 
 nsISupports*
 nsPluginSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                       nsWrapperCache **aCache, nsresult *aResult)
 {
   nsPluginElement* plugin = nsPluginElement::FromSupports(aNative);
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -56,17 +56,16 @@ class DOMSVGNumberList;
 class DOMSVGPathSegList;
 class DOMSVGPointList;
 class DOMSVGStringList;
 class DOMSVGTransformList;
 }
 class nsGlobalWindow;
 class nsIDOMDocument;
 class nsIDOMHTMLOptionsCollection;
-class nsIDOMNodeList;
 class nsIDOMSVGLength;
 class nsIDOMSVGLengthList;
 class nsIDOMSVGNumber;
 class nsIDOMSVGNumberList;
 class nsIDOMSVGPathSeg;
 class nsIDOMSVGPathSegList;
 class nsIDOMSVGPoint;
 class nsIDOMSVGPointList;
@@ -619,41 +618,16 @@ public:
                          JSObject *obj, jsid id, jsval *vp, bool *_retval);
 
 private:
   // Not implemented, nothing should create an instance of this class.
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
 };
 
 
-// NodeList scriptable helper
- 
-class nsNodeListSH : public nsArraySH
-{
-protected:
-  nsNodeListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
-  {
-  }
-
-public:
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-
-  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *obj, PRUint32 *length);
-  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
- 
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsNodeListSH(aData);
-  }
-};
-
-
 // NamedArray helper
 
 class nsNamedArraySH : public nsArraySH
 {
 protected:
   nsNamedArraySH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
@@ -706,80 +680,16 @@ protected:
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNamedNodeMapSH(aData);
   }
 };
 
 
-// HTMLCollection helper
-
-class nsHTMLCollectionSH : public nsNamedArraySH
-{
-protected:
-  nsHTMLCollectionSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
-  {
-  }
-
-  virtual ~nsHTMLCollectionSH()
-  {
-  }
-
-  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *obj, PRUint32 *length);
-  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
-
-  // Override nsNamedArraySH::GetNamedItem()
-  virtual nsISupports* GetNamedItem(nsISupports *aNative,
-                                    const nsAString& aName,
-                                    nsWrapperCache **cache,
-                                    nsresult *aResult);
-
-public:
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsHTMLCollectionSH(aData);
-  }
-};
-
-
-// ContentList helper
-
-class nsContentListSH : public nsNamedArraySH
-{
-protected:
-  nsContentListSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
-  {
-  }
-
-public:
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-
-  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *obj, PRUint32 *length);
-  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
-  virtual nsISupports* GetNamedItem(nsISupports *aNative,
-                                    const nsAString& aName,
-                                    nsWrapperCache **cache,
-                                    nsresult *aResult);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsContentListSH(aData);
-  }
-};
-
-
 // DOMStringMap helper for .dataset property on elements.
 
 class nsDOMStringMapSH : public nsDOMGenericSH
 {
 public:
   nsDOMStringMapSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
@@ -1002,41 +912,16 @@ public:
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHTMLPluginObjElementSH(aData);
   }
 };
 
 
-// HTMLOptionsCollection helper
-
-class nsHTMLOptionsCollectionSH : public nsHTMLCollectionSH
-{
-protected:
-  nsHTMLOptionsCollectionSH(nsDOMClassInfoData* aData)
-    : nsHTMLCollectionSH(aData)
-  {
-  }
-
-  virtual ~nsHTMLOptionsCollectionSH()
-  {
-  }
-
-public:
-  NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
-  
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsHTMLOptionsCollectionSH(aData);
-  }
-};
-
-
 // Plugin helper
 
 class nsPluginSH : public nsNamedArraySH
 {
 protected:
   nsPluginSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -192,18 +192,16 @@ DOMCI_CLASS(TreeWalker)
 DOMCI_CLASS(CSSRect)
 
 // DOM Chrome Window class, almost identical to Window
 DOMCI_CLASS(ChromeWindow)
 
 // RGBColor object used by getComputedStyle
 DOMCI_CLASS(CSSRGBColor)
 
-DOMCI_CLASS(RangeException)
-
 // CSSValueList object that represents an nsIDOMCSSValueList, used
 // by DOM CSS
 DOMCI_CLASS(CSSValueList)
 
 // ContentList object used for various live NodeLists
 DOMCI_CLASS(ContentList)
   
 // Processing-instruction with target "xml-stylesheet"
--- a/dom/base/nsDOMError.h
+++ b/dom/base/nsDOMError.h
@@ -66,21 +66,16 @@
 #define NS_ERROR_DOM_NETWORK_ERR                 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,19)
 #define NS_ERROR_DOM_ABORT_ERR                   NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,20)
 #define NS_ERROR_DOM_URL_MISMATCH_ERR            NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,21)
 #define NS_ERROR_DOM_QUOTA_EXCEEDED_ERR          NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,22)
 #define NS_ERROR_DOM_TIMEOUT_ERR                 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,23)
 #define NS_ERROR_DOM_INVALID_NODE_TYPE_ERR       NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,24)
 #define NS_ERROR_DOM_DATA_CLONE_ERR              NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,25)
 
-/* DOM error codes from http://www.w3.org/TR/DOM-Level-2/range.html */
-
-#define NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_RANGE, 1)
-#define NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_RANGE, 2)
-
 /* SVG DOM error codes from http://www.w3.org/TR/SVG11/svgdom.html */
 
 #define NS_ERROR_DOM_SVG_WRONG_TYPE_ERR          NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SVG,0)
 #define NS_ERROR_DOM_SVG_INVALID_VALUE_ERR       NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SVG,1)
 #define NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE   NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SVG,2)
 
 /* DOM error codes from http://www.w3.org/TR/DOM-Level-3-XPath/ */
 
--- a/dom/base/nsDOMException.cpp
+++ b/dom/base/nsDOMException.cpp
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMError.h"
 #include "nsDOMException.h"
 #include "nsIDOMDOMException.h"
-#include "nsIDOMRangeException.h"
 #include "nsIDOMFileException.h"
 #include "nsIDOMSVGException.h"
 #include "nsIDOMXPathException.h"
 #include "nsIIDBDatabaseException.h"
 #include "nsString.h"
 #include "prprf.h"
 
 #define DOM_MSG_DEF(val, message) {(val), #val, message},
@@ -164,33 +163,16 @@ nsDOMException::GetCode(PRUint16* aCode)
   NS_ENSURE_ARG_POINTER(aCode);
   nsresult result;
   GetResult(&result);
   *aCode = NS_ERROR_GET_CODE(result);
 
   return NS_OK;
 }
 
-IMPL_INTERNAL_DOM_EXCEPTION_HEAD(nsRangeException, nsIDOMRangeException)
-  NS_DECL_NSIDOMRANGEEXCEPTION
-IMPL_INTERNAL_DOM_EXCEPTION_TAIL(nsRangeException, nsIDOMRangeException,
-                                 RangeException, NS_ERROR_MODULE_DOM_RANGE,
-                                 NSResultToNameAndMessage)
-
-NS_IMETHODIMP
-nsRangeException::GetCode(PRUint16* aCode)
-{
-  NS_ENSURE_ARG_POINTER(aCode);
-  nsresult result;
-  GetResult(&result);
-  *aCode = NS_ERROR_GET_CODE(result);
-
-  return NS_OK;
-}
-
 IMPL_INTERNAL_DOM_EXCEPTION_HEAD(nsSVGException, nsIDOMSVGException)
   NS_DECL_NSIDOMSVGEXCEPTION
 IMPL_INTERNAL_DOM_EXCEPTION_TAIL(nsSVGException, nsIDOMSVGException,
                                  SVGException, NS_ERROR_MODULE_SVG,
                                  NSResultToNameAndMessage)
 
 NS_IMETHODIMP
 nsSVGException::GetCode(PRUint16* aCode)
--- a/dom/base/nsDOMException.h
+++ b/dom/base/nsDOMException.h
@@ -67,13 +67,12 @@ NS_GetNameAndMessageForDOMNSResult(nsres
 
 #define DECL_INTERNAL_DOM_EXCEPTION(domname)                                 \
 nsresult                                                                     \
 NS_New##domname(nsresult aNSResult, nsIException* aDefaultException,         \
                 nsIException** aException);
 
 
 DECL_INTERNAL_DOM_EXCEPTION(DOMException)
-DECL_INTERNAL_DOM_EXCEPTION(RangeException)
 DECL_INTERNAL_DOM_EXCEPTION(SVGException)
 DECL_INTERNAL_DOM_EXCEPTION(XPathException)
 DECL_INTERNAL_DOM_EXCEPTION(FileException)
 DECL_INTERNAL_DOM_EXCEPTION(IDBDatabaseException)
--- a/dom/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/base/nsDOMScriptObjectFactory.cpp
@@ -82,17 +82,16 @@ nsDOMScriptObjectFactory::nsDOMScriptObj
 
   nsCOMPtr<nsIExceptionProvider> provider(new nsDOMExceptionProvider());
   if (provider) {
     nsCOMPtr<nsIExceptionService> xs =
       do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
 
     if (xs) {
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM);
-      xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_RANGE);
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_SVG);
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_XPATH);
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_INDEXEDDB);
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_XPCONNECT);
       xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_EVENTS);
     }
 
     NS_ASSERTION(!gExceptionProvider, "Registered twice?!");
@@ -283,18 +282,16 @@ nsDOMScriptObjectFactory::Observe(nsISup
     if (gExceptionProvider) {
       nsCOMPtr<nsIExceptionService> xs =
         do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
 
       if (xs) {
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM);
         xs->UnregisterExceptionProvider(gExceptionProvider,
-                                        NS_ERROR_MODULE_DOM_RANGE);
-        xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_SVG);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM_XPATH);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_XPCONNECT);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM_EVENTS);
       }
@@ -381,18 +378,16 @@ nsDOMExceptionProvider::GetException(nsr
                                      nsIException **_retval)
 {
   if (!NS_IsMainThread()) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   switch (NS_ERROR_GET_MODULE(result))
   {
-    case NS_ERROR_MODULE_DOM_RANGE:
-      return NS_NewRangeException(result, aDefaultException, _retval);
     case NS_ERROR_MODULE_SVG:
       return NS_NewSVGException(result, aDefaultException, _retval);
     case NS_ERROR_MODULE_DOM_XPATH:
       return NS_NewXPathException(result, aDefaultException, _retval);
     case NS_ERROR_MODULE_XPCONNECT:
       return CreateXPConnectException(result, aDefaultException, _retval);
     case NS_ERROR_MODULE_DOM_FILE:
       return NS_NewFileException(result, aDefaultException, _retval);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -264,17 +264,16 @@ static PRLogModuleInfo* gDOMLeakPRLog;
 
 static const char kStorageEnabled[] = "dom.storage.enabled";
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
-nsIDOMStorageList *nsGlobalWindow::sGlobalStorageList  = nsnull;
 nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nsnull;
 bool nsGlobalWindow::sWarnedAboutWindowInternal = false;
 
 static nsIEntropyCollector *gEntropyCollector          = nsnull;
 static PRInt32              gRefCnt                    = 0;
 static PRInt32              gOpenPopupSpamCount        = 0;
 static PopupControlState    gPopupControlState         = openAbused;
 static PRInt32              gRunningTimeoutDepth       = 0;
@@ -1082,18 +1081,16 @@ nsGlobalWindow::~nsGlobalWindow()
 
   nsLayoutStatics::Release();
 }
 
 // static
 void
 nsGlobalWindow::ShutDown()
 {
-  NS_IF_RELEASE(sGlobalStorageList);
-
   if (gDumpFile && gDumpFile != stdout) {
     fclose(gDumpFile);
   }
   gDumpFile = nsnull;
 
   NS_IF_RELEASE(gEntropyCollector);
 
   delete sWindowsById;
@@ -2979,24 +2976,57 @@ nsGlobalWindow::GetPerformance(nsIDOMPer
         mPerformance = new nsPerformance(timing, timedChannel);
       }
     }
     NS_IF_ADDREF(*aPerformance = mPerformance);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetParent(nsIDOMWindow** aParent)
-{
-  FORWARD_TO_OUTER(GetParent, (aParent), NS_ERROR_NOT_INITIALIZED);
+/**
+ * GetScriptableParent is called when script reads window.parent.
+ *
+ * In contrast to GetRealParent, GetScriptableParent respects <iframe
+ * mozbrowser> boundaries, so if |this| is contained by an <iframe
+ * mozbrowser>, we will return |this| as its own parent.
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
+{
+  FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED);
+
+  *aParent = NULL;
+  if (!mDocShell) {
+    return NS_OK;
+  }
+
+  bool isMozBrowser = false;
+  mDocShell->GetIsBrowserFrame(&isMozBrowser);
+  if (isMozBrowser) {
+    nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
+    parent.swap(*aParent);
+    return NS_OK;
+  }
+
+  return GetRealParent(aParent);
+}
+
+/**
+ * nsIDOMWindow::GetParent (when called from C++) is just a wrapper around
+ * GetRealParent.
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetRealParent(nsIDOMWindow** aParent)
+{
+  FORWARD_TO_OUTER(GetRealParent, (aParent), NS_ERROR_NOT_INITIALIZED);
 
   *aParent = nsnull;
-  if (!mDocShell)
+  if (!mDocShell) {
     return NS_OK;
+  }
 
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocShellTreeItem> parent;
   docShellAsItem->GetSameTypeParent(getter_AddRefs(parent));
 
   if (parent) {
@@ -3006,31 +3036,72 @@ nsGlobalWindow::GetParent(nsIDOMWindow**
   }
   else {
     *aParent = static_cast<nsIDOMWindow*>(this);
     NS_ADDREF(*aParent);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetTop(nsIDOMWindow** aTop)
-{
-  FORWARD_TO_OUTER(GetTop, (aTop), NS_ERROR_NOT_INITIALIZED);
-
+/**
+ * GetScriptableTop is called when script reads window.top.
+ *
+ * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
+ * boundaries.  If we encounter a window owned by an <iframe mozbrowser> while
+ * walking up the window hierarchy, we'll stop and return that window.
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetScriptableTop(nsIDOMWindow **aTop)
+{
+  return GetTopImpl(aTop, /* aScriptable = */ true);
+}
+
+/**
+ * nsIDOMWindow::GetTop (when called from C++) is just a wrapper around
+ * GetRealTop.
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetRealTop(nsIDOMWindow** aTop)
+{
+  return GetTopImpl(aTop, /* aScriptable = */ false);
+}
+
+nsresult
+nsGlobalWindow::GetTopImpl(nsIDOMWindow** aTop, bool aScriptable)
+{
+  FORWARD_TO_OUTER(GetTopImpl, (aTop, aScriptable), NS_ERROR_NOT_INITIALIZED);
   *aTop = nsnull;
-  if (mDocShell) {
-    nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
-    nsCOMPtr<nsIDocShellTreeItem> root;
-    docShellAsItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
-
-    if (root) {
-      nsCOMPtr<nsIDOMWindow> top(do_GetInterface(root));
-      top.swap(*aTop);
-    }
+
+  // Walk up the parent chain.
+
+  nsCOMPtr<nsIDOMWindow> prevParent = this;
+  nsCOMPtr<nsIDOMWindow> parent = this;
+  do {
+    if (!parent) {
+      break;
+    }
+
+    prevParent = parent;
+
+    nsCOMPtr<nsIDOMWindow> newParent;
+    nsresult rv;
+    if (aScriptable) {
+      rv = parent->GetScriptableParent(getter_AddRefs(newParent));
+    }
+    else {
+      rv = parent->GetParent(getter_AddRefs(newParent));
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    parent = newParent;
+
+  } while (parent != prevParent);
+
+  if (parent) {
+    parent.swap(*aTop);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
 {
@@ -6905,22 +6976,53 @@ nsGlobalWindow::CacheXBLPrototypeHandler
       NS_ERROR("nsContentUtils::HoldJSObjects failed!");
       return;
     }
   }
 
   mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get());
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement)
-{
-  FORWARD_TO_OUTER(GetFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
-
-  *aFrameElement = nsnull;
+/**
+ * GetScriptableFrameElement is called when script reads
+ * nsIGlobalWindow::frameElement.
+ *
+ * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
+ * window contained by an <iframe mozbrowser> has no frame element
+ * (effectively treating a mozbrowser the same as a content/chrome boundary).
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
+{
+  FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
+  *aFrameElement = NULL;
+
+  if (!mDocShell) {
+    return NS_OK;
+  }
+
+  bool isMozBrowser = false;
+  mDocShell->GetIsBrowserFrame(&isMozBrowser);
+  if (isMozBrowser) {
+    return NS_OK;
+  }
+
+  return GetFrameElement(aFrameElement);
+}
+
+/**
+ * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
+ * around GetRealFrameElement.
+ */
+NS_IMETHODIMP
+nsGlobalWindow::GetRealFrameElement(nsIDOMElement** aFrameElement)
+{
+  FORWARD_TO_OUTER(GetRealFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
+
+  *aFrameElement = NULL;
 
   nsCOMPtr<nsIDocShellTreeItem> docShellTI(do_QueryInterface(mDocShell));
 
   if (!docShellTI) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> parent;
@@ -8191,42 +8293,16 @@ nsGlobalWindow::GetSessionStorage(nsIDOM
     }
 #endif
 
   NS_ADDREF(*aSessionStorage = mSessionStorage);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetGlobalStorage(nsIDOMStorageList ** aGlobalStorage)
-{
-  NS_ENSURE_ARG_POINTER(aGlobalStorage);
-
-  nsCOMPtr<nsIDocument> document = do_QueryInterface(GetExtantDocument());
-  if (document) {
-    document->WarnOnceAbout(nsIDocument::eGlobalStorage);
-  }
-
-  if (!Preferences::GetBool(kStorageEnabled)) {
-    *aGlobalStorage = nsnull;
-    return NS_OK;
-  }
-
-  if (!sGlobalStorageList) {
-    nsresult rv = NS_NewDOMStorageList(&sGlobalStorageList);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  *aGlobalStorage = sGlobalStorageList;
-  NS_IF_ADDREF(*aGlobalStorage);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
 {
   FORWARD_TO_INNER(GetLocalStorage, (aLocalStorage), NS_ERROR_UNEXPECTED);
 
   NS_ENSURE_ARG(aLocalStorage);
 
   if (!Preferences::GetBool(kStorageEnabled)) {
     *aLocalStorage = nsnull;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -421,16 +421,26 @@ public:
     // Make sure this matches the casts we do in QueryInterface().
     return (nsISupports *)(nsIScriptGlobalObject *)win;
   }
   static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper)
   {
     return FromSupports(wrapper->Native());
   }
 
+  /**
+   * Wrap nsIDOMWindow::GetTop so we can overload the inline GetTop()
+   * implementation below.  (nsIDOMWindow::GetTop simply calls
+   * nsIDOMWindow::GetRealTop().)
+   */
+  nsresult GetTop(nsIDOMWindow **aWindow)
+  {
+    return nsIDOMWindow::GetTop(aWindow);
+  }
+
   inline nsGlobalWindow *GetTop()
   {
     nsCOMPtr<nsIDOMWindow> top;
     GetTop(getter_AddRefs(top));
     if (top)
       return static_cast<nsGlobalWindow *>(static_cast<nsIDOMWindow *>(top.get()));
     return nsnull;
   }
@@ -583,16 +593,19 @@ public:
   void UnmarkGrayTimers();
 private:
   // Enable updates for the accelerometer.
   void EnableDeviceMotionUpdates();
 
   // Disables updates for the accelerometer.
   void DisableDeviceMotionUpdates();
 
+  // Implements Get{Real,Scriptable}Top.
+  nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
+
 protected:
   friend class HashchangeCallback;
   friend class nsBarProp;
 
   // Object Management
   virtual ~nsGlobalWindow();
   void CleanUp(bool aIgnoreModalDialog);
   void ClearControllers();
@@ -996,17 +1009,16 @@ protected:
   TimeStamp                     mLastDialogQuitTime;
   bool                          mDialogDisabled;
 
   nsRefPtr<nsDOMMozURLProperty> mURLProperty;
 
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class PostMessageEvent;
-  static nsIDOMStorageList* sGlobalStorageList;
 
   static WindowByIdTable* sWindowsById;
   static bool sWarnedAboutWindowInternal;
 };
 
 /*
  * nsGlobalChromeWindow inherits from nsGlobalWindow. It is the global
  * object created for a Chrome Window only.
rename from dom/base/nsDOMMemoryReporter.cpp
rename to dom/base/nsWindowMemoryReporter.cpp
--- a/dom/base/nsDOMMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -30,32 +30,32 @@
  * 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 "nsDOMMemoryReporter.h"
+#include "nsWindowMemoryReporter.h"
 #include "nsGlobalWindow.h"
 
 
-nsDOMMemoryMultiReporter::nsDOMMemoryMultiReporter()
+nsWindowMemoryReporter::nsWindowMemoryReporter()
 {
 }
 
-NS_IMPL_ISUPPORTS1(nsDOMMemoryMultiReporter, nsIMemoryMultiReporter)
+NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter, nsIMemoryMultiReporter)
 
 /* static */
 void
-nsDOMMemoryMultiReporter::Init()
+nsWindowMemoryReporter::Init()
 {
   // The memory reporter manager is going to own this object.
-  NS_RegisterMemoryMultiReporter(new nsDOMMemoryMultiReporter());
+  NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter());
 }
 
 static bool
 AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
 {
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
   nsCOMPtr<nsIURI> uri;
 
@@ -83,28 +83,21 @@ AppendWindowURI(nsGlobalWindow *aWindow,
   // (such as about:memory) have to undo this change.
   spec.ReplaceChar('/', '\\');
 
   aStr += spec;
 
   return true;
 }
 
-struct WindowTotals
-{
-  WindowTotals() : mDom(0), mStyleSheets(0) {}
-  size_t mDom;
-  size_t mStyleSheets;
-};
-
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "dom+style")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
 
 static void
 CollectWindowReports(nsGlobalWindow *aWindow,
-                     WindowTotals *aWindowTotals,
+                     nsWindowSizes *aWindowTotalSizes,
                      nsIMemoryMultiReporterCallback *aCb,
                      nsISupports *aClosure)
 {
   // DOM window objects fall into one of three categories:
   // - "active" windows are currently either displayed in an active
   //   tab, or a child of such a window.
   // - "cached" windows are in the fastback cache.
   // - "other" windows are closed (or navigated away from w/o being
@@ -121,17 +114,17 @@ CollectWindowReports(nsGlobalWindow *aWi
   // For outer windows we simply group them all together and just show
   // the combined count and amount of memory used, which is generally
   // a constant amount per window (since all the actual data lives in
   // the inner window).
   //
   // The path we give to the reporter callback for inner windows are
   // as follows:
   //
-  //   explicit/dom+style/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
+  //   explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
   //
   // Where:
   // - <category> is active, cached, or other, as described above.
   // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
   //   the top outer window (i.e. tab, or top level chrome window).
   // - <top-inner-id> is the window id of the top window's inner
   //   window.
   // - <id> is the window id of the inner window in question.
@@ -140,22 +133,22 @@ CollectWindowReports(nsGlobalWindow *aWi
   // Exposing the window ids is done to get logical grouping in
   // about:memory, and also for debuggability since one can get to the
   // nsGlobalWindow for a window id by calling the static method
   // nsGlobalWindow::GetInnerWindowWithId(id) (or
   // GetOuterWindowWithId(id) in a debugger.
   //
   // For outer windows we simply use:
   // 
-  //   explicit/dom+style/window-objects/<category>/outer-windows
+  //   explicit/window-objects/<category>/outer-windows
   //
   // Which gives us simple counts of how many outer windows (and their
   // combined sizes) per category.
 
-  nsCAutoString windowPath("explicit/dom+style/window-objects/");
+  nsCAutoString windowPath("explicit/window-objects/");
 
   nsIDocShell *docShell = aWindow->GetDocShell();
 
   nsGlobalWindow *top = aWindow->GetTop();
   nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
   aWindow->SizeOfIncludingThis(&windowSizes);
 
   if (docShell && aWindow->IsFrozen()) {
@@ -194,99 +187,126 @@ CollectWindowReports(nsGlobalWindow *aWi
   } else {
     // Combine all outer windows per section (active/cached/other) as
     // they basically never contain anything of interest, and are
     // always pretty much the same size.
 
     windowPath += NS_LITERAL_CSTRING("outer-windows");
   }
 
-  if (windowSizes.mDOM > 0) {
-    nsCAutoString domPath(windowPath);
-    domPath += "/dom";
-    NS_NAMED_LITERAL_CSTRING(kWindowDesc,
-                             "Memory used by a window and the DOM within it.");
-    aCb->Callback(EmptyCString(), domPath, nsIMemoryReporter::KIND_HEAP,
-                  nsIMemoryReporter::UNITS_BYTES, windowSizes.mDOM,
-                  kWindowDesc, aClosure);
-    aWindowTotals->mDom += windowSizes.mDOM;
-  }
+#define REPORT(_path1, _path2, _amount, _desc)                                \
+  do {                                                                        \
+    if (_amount > 0) {                                                        \
+        nsCAutoString path(_path1);                                           \
+        path += _path2;                                                       \
+        aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,     \
+                      nsIMemoryReporter::UNITS_BYTES, _amount,                \
+                      NS_LITERAL_CSTRING(_desc), aClosure);                   \
+    }                                                                         \
+  } while (0)
+
+  REPORT(windowPath, "/dom", windowSizes.mDOM,
+         "Memory used by a window and the DOM within it.");
+  aWindowTotalSizes->mDOM += windowSizes.mDOM;
 
-  if (windowSizes.mStyleSheets > 0) {
-    nsCAutoString styleSheetsPath(windowPath);
-    styleSheetsPath += "/style-sheets";
-    NS_NAMED_LITERAL_CSTRING(kStyleSheetsDesc,
-                             "Memory used by style sheets within a window.");
-    aCb->Callback(EmptyCString(), styleSheetsPath,
-                  nsIMemoryReporter::KIND_HEAP,
-                  nsIMemoryReporter::UNITS_BYTES, windowSizes.mStyleSheets,
-                  kStyleSheetsDesc, aClosure);
-    aWindowTotals->mStyleSheets += windowSizes.mStyleSheets;
-  }
+  REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
+         "Memory used by style sheets within a window.");
+  aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
+
+  REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
+         "Memory used by layout PresShell, PresContext, and other related "
+         "areas within a window.");
+  aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
+
+  REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
+         "Memory used by style sets within a window.");
+  aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;
+
+  REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
+         "Memory used for text-runs (glyph layout) in the PresShell's frame "
+         "tree, within a window.");
+  aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;
+
+#undef REPORT
 }
 
 typedef nsTArray< nsRefPtr<nsGlobalWindow> > WindowArray;
 
 static
 PLDHashOperator
 GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   ((WindowArray *)aClosure)->AppendElement(aWindow);
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
-nsDOMMemoryMultiReporter::GetName(nsACString &aName)
+nsWindowMemoryReporter::GetName(nsACString &aName)
 {
-  aName.AssignLiteral("dom+style");
+  aName.AssignLiteral("window-objects");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
-                                         nsISupports* aClosure)
+nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
+                                       nsISupports* aClosure)
 {
   nsGlobalWindow::WindowByIdTable* windowsById =
     nsGlobalWindow::GetWindowsTable();
   NS_ENSURE_TRUE(windowsById, NS_OK);
 
   // Hold on to every window in memory so that window objects can't be
   // destroyed while we're calling the memory reporter callback.
   WindowArray windows;
   windowsById->Enumerate(GetWindows, &windows);
 
   // Collect window memory usage.
   nsRefPtr<nsGlobalWindow> *w = windows.Elements();
   nsRefPtr<nsGlobalWindow> *end = w + windows.Length();
-  WindowTotals windowTotals;
+  nsWindowSizes windowTotalSizes(NULL);
   for (; w != end; ++w) {
-    CollectWindowReports(*w, &windowTotals, aCb, aClosure);
+    CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure);
   }
 
-  NS_NAMED_LITERAL_CSTRING(kDomTotalWindowsDesc,
-    "Memory used for the DOM within windows.  This is the sum of all windows' "
-    "'dom' numbers.");
-  aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("dom-total-window"),
-                nsIMemoryReporter::KIND_OTHER,
-                nsIMemoryReporter::UNITS_BYTES, windowTotals.mDom,
-                kDomTotalWindowsDesc, aClosure);
+#define REPORT(_path, _amount, _desc)                                         \
+  do {                                                                        \
+    aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),                  \
+                  nsIMemoryReporter::KIND_OTHER,                              \
+                  nsIMemoryReporter::UNITS_BYTES, _amount,                    \
+                  NS_LITERAL_CSTRING(_desc), aClosure);                       \
+  } while (0)
 
-  NS_NAMED_LITERAL_CSTRING(kLayoutTotalWindowStyleSheetsDesc,
-    "Memory used for style sheets within windows.  This is the sum of all windows' "
-    "'style-sheets' numbers.");
-  aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("style-sheets-total-window"),
-                nsIMemoryReporter::KIND_OTHER,
-                nsIMemoryReporter::UNITS_BYTES, windowTotals.mStyleSheets,
-                kLayoutTotalWindowStyleSheetsDesc, aClosure);
+  REPORT("window-objects-dom", windowTotalSizes.mDOM, 
+         "Memory used for the DOM within windows. "
+         "This is the sum of all windows' 'dom' numbers.");
+    
+  REPORT("window-objects-style-sheets", windowTotalSizes.mStyleSheets, 
+         "Memory used for style sheets within windows. "
+         "This is the sum of all windows' 'style-sheets' numbers.");
+    
+  REPORT("window-objects-layout-arenas", windowTotalSizes.mLayoutArenas, 
+         "Memory used by layout PresShell, PresContext, and other related "
+         "areas within windows. This is the sum of all windows' "
+         "'layout/arenas' numbers.");
+    
+  REPORT("window-objects-layout-style-sets", windowTotalSizes.mLayoutStyleSets, 
+         "Memory used for style sets within windows. "
+         "This is the sum of all windows' 'layout/style-sets' numbers.");
+    
+  REPORT("window-objects-layout-text-runs", windowTotalSizes.mLayoutTextRuns, 
+         "Memory used for text runs within windows. "
+         "This is the sum of all windows' 'layout/text-runs' numbers.");
 
+#undef REPORT
+    
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMMemoryMultiReporter::GetExplicitNonHeap(PRInt64* aAmount)
+nsWindowMemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
 {
   // This reporter only measures heap memory.
   *aAmount = 0;
   return NS_OK;
 }
 
 
rename from dom/base/nsDOMMemoryReporter.h
rename to dom/base/nsWindowMemoryReporter.h
--- a/dom/base/nsDOMMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -30,47 +30,49 @@
  * 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 nsDOMMemoryReporter_h__
-#define nsDOMMemoryReporter_h__
+#ifndef nsWindowMemoryReporter_h__
+#define nsWindowMemoryReporter_h__
 
 #include "nsIMemoryReporter.h"
 
 // This should be used for any nsINode sub-class that has fields of its own
 // that it needs to measure;  any sub-class that doesn't use it will inherit
 // SizeOfExcludingThis from its super-class.  SizeOfIncludingThis() need not be
 // defined, it is inherited from nsINode.
 #define NS_DECL_SIZEOF_EXCLUDING_THIS \
   virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
 class nsWindowSizes {
 public:
-    nsWindowSizes(nsMallocSizeOfFun aMallocSizeOf)
-    : mMallocSizeOf(aMallocSizeOf),
-      mDOM(0),
-      mStyleSheets(0)
-    {}
+    nsWindowSizes(nsMallocSizeOfFun aMallocSizeOf) {
+      memset(this, 0, sizeof(nsWindowSizes));
+      mMallocSizeOf = aMallocSizeOf;
+    }
     nsMallocSizeOfFun mMallocSizeOf;
     size_t mDOM;
     size_t mStyleSheets;
+    size_t mLayoutArenas;
+    size_t mLayoutStyleSets;
+    size_t mLayoutTextRuns;
 };
 
-class nsDOMMemoryMultiReporter: public nsIMemoryMultiReporter
+class nsWindowMemoryReporter: public nsIMemoryMultiReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEMORYMULTIREPORTER
 
   static void Init();
 
 private:
   // Protect ctor, use Init() instead.
-  nsDOMMemoryMultiReporter();
+  nsWindowMemoryReporter();
 };
 
-#endif // nsDOMMemoryReporter_h__
+#endif // nsWindowMemoryReporter_h__
 
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -65,17 +65,16 @@ interface nsIDOMProcessingInstruction;
 interface nsIDOMText;
 interface nsIDOMDOMStringList;
 interface nsIDOMDOMTokenList;
 interface nsIDOMClientRect;
 interface nsIDOMClientRectList;
 
 // Needed for raises() in our IDL
 interface DOMException;
-interface RangeException;
 
 // Style Sheets
 interface nsIDOMStyleSheetList;
 interface nsIDOMLinkStyle;
 interface nsIDOMStyleSheet;
 interface nsIDOMMediaList;
 
 // Base
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -65,17 +65,17 @@ interface nsIDOMMozURLProperty : nsISupp
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(f6e3b10d-d5f4-4fcd-aa4c-5f98626d428a)]
+[scriptable, uuid(17400E2B-F78B-4E69-B500-C2A3135A40FD)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -129,34 +129,100 @@ interface nsIDOMWindow : nsISupports
   void                      blur();
 
 
   // other browsing contexts
   /* [replaceable] length */
   readonly attribute unsigned long                      length;
 
   /**
-   * Accessor for the root of this hierarchy of windows. This root may
-   * be the window itself if there is no parent, or if the parent is
-   * of different type (i.e. this does not cross chrome-content
-   * boundaries).
+   * |top| gets the root of the window hierarchy.
+   *
+   * This function does not cross chrome-content boundaries, so if this
+   * window's parent is of a different type, |top| will return this window.
+   *
+   * When script reads the top property, we run GetScriptableTop, which
+   * will not cross an <iframe mozbrowser> boundary.
+   *
+   * In contrast, C++ calls to GetTop are forwarded to GetRealTop, which
+   * ignores <iframe mozbrowser> boundaries.
    *
-   * This property is "replaceable" in JavaScript */
+   * This property is "replaceable" in JavaScript.
+   */
+  [binaryname(ScriptableTop)]
   readonly attribute nsIDOMWindow                       top;
 
+  /**
+   * You shouldn't need to call this function directly; call GetTop instead.
+   */
+  [noscript]
+  readonly attribute nsIDOMWindow                       realTop;
+
+  %{C++
+  nsresult GetTop(nsIDOMWindow **aWindow)
+  {
+    return GetRealTop(aWindow);
+  }
+  %}
+
+  /**
+   * |parent| gets this window's parent window.  If this window has no parent,
+   * we return the window itself.
+   *
+   * This property does not cross chrome-content boundaries, so if this
+   * window's parent is of a different type, we return the window itself as its
+   * parent.
+   *
+   * When script reads the property (or when C++ calls ScriptableTop), this
+   * property does not cross <iframe mozbrowser> boundaries.  In contrast, when
+   * C++ calls GetParent, we ignore the mozbrowser attribute.
+   */
+  [binaryname(ScriptableParent)]
+  readonly attribute nsIDOMWindow                       parent;
+
+  /**
+   * You shouldn't need to read this property directly; call GetParent instead.
+   */
+  [noscript]
+  readonly attribute nsIDOMWindow                       realParent;
+
+  %{C++
+  inline nsresult GetParent(nsIDOMWindow **aWindow)
+  {
+    return GetRealParent(aWindow);
+  }
+  %}
+
            attribute nsIDOMWindow                       opener;
 
   /**
-   * Accessor for this window's parent window, or the window itself if
-   * there is no parent, or if the parent is of different type
-   * (i.e. this does not cross chrome-content boundaries).
+   * |frameElement| gets this window's <iframe> or <frame> element, if it has
+   * one.
+   *
+   * When script reads this property (or when C++ calls
+   * ScriptableFrameElement), we return |null| if the window is inside an
+   * <iframe mozbrowser>.  In contrast, when C++ calls GetFrameElement, we
+   * ignore the mozbrowser attribute.
    */
-  readonly attribute nsIDOMWindow                       parent;
+  [binaryname(ScriptableFrameElement)]
+  readonly attribute nsIDOMElement                      frameElement;
 
-  readonly attribute nsIDOMElement                      frameElement;
+  /**
+   * You shouldn't need to read this property directly; call GetFrameElement
+   * instead.
+   */
+  [noscript]
+  readonly attribute nsIDOMElement                      realFrameElement;
+
+  %{C++
+  inline nsresult GetFrameElement(nsIDOMElement **aElement)
+  {
+    return GetRealFrameElement(aElement);
+  }
+  %}
 
 
   // the user agent
   readonly attribute nsIDOMNavigator                    navigator;
 
   /**
    * Get the application cache object for this window.
    */
@@ -434,21 +500,16 @@ interface nsIDOMWindow : nsISupports
   readonly attribute long long mozAnimationStartTime;
 
   /**
    * @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
    */
   readonly attribute nsIDOMMozURLProperty URL;
 
   /**
-   * Global storage, accessible by domain.
-   */
-  readonly attribute nsIDOMStorageList globalStorage;
-
-  /**
    * HTML5 event attributes that only apply to windows and <body>/<frameset>
    */
   [implicit_jscontext] attribute jsval onafterprint;
   [implicit_jscontext] attribute jsval onbeforeprint;
   [implicit_jscontext] attribute jsval onbeforeunload;
   [implicit_jscontext] attribute jsval onhashchange;
   [implicit_jscontext] attribute jsval onmessage;
   [implicit_jscontext] attribute jsval onoffline;
--- a/dom/interfaces/core/nsIDOMDOMTokenList.idl
+++ b/dom/interfaces/core/nsIDOMDOMTokenList.idl
@@ -44,16 +44,16 @@
  * For more information on this interface please see
  * <http://www.whatwg.org/html5/#domtokenlist>
  */
 [scriptable, uuid(c6f1e160-eeeb-404a-98b0-6f1246520b6e)]
 interface nsIDOMDOMTokenList : nsISupports
 {
   readonly attribute unsigned long length;
 
-  DOMString          item(in unsigned long index);
+  [getter] DOMString item(in unsigned long index);
   boolean            contains([Null(Stringify)] in DOMString token);
   void               add([Null(Stringify)] in DOMString token);
   void               remove([Null(Stringify)] in DOMString token);
   boolean            toggle([Null(Stringify)] in DOMString token);
 
-  DOMString          toString();
+  [stringifier] DOMString          toString();
 };
--- a/dom/interfaces/html/Makefile.in
+++ b/dom/interfaces/html/Makefile.in
@@ -117,11 +117,12 @@ SDK_XPIDLSRCS =					\
 	nsIDOMValidityState.idl		\
 	nsIDOMDOMStringMap.idl		\
 	nsIDOMMozBrowserFrame.idl		\
 	$(NULL)
 
 XPIDLSRCS = 					\
 	nsIDOMHTMLCanvasElement.idl		\
 	nsIDOMHTMLUnknownElement.idl \
+	nsIMozBrowserFrame.idl \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIMozBrowserFrame.idl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMMozBrowserFrame.idl"
+
+[scriptable, uuid(076AD76C-2DF6-4760-B914-21D554F0A2B6)]
+interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
+{
+  /**
+   * Gets whether this frame really is a browser frame.
+   *
+   * In order to really be a browser frame, this frame's
+   * nsIDOMMozBrowserFrame::mozbrowser attribute must be true, and the frame
+   * may have to pass various security checks.
+   */
+  readonly attribute boolean reallyIsBrowser;
+};
--- a/dom/interfaces/range/Makefile.in
+++ b/dom/interfaces/range/Makefile.in
@@ -45,13 +45,9 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= dom
 XPIDL_MODULE	= dom_range
 GRE_MODULE	= 1
 
 SDK_XPIDLSRCS =		\
 	nsIDOMRange.idl	\
 	$(NULL)
 
-XPIDLSRCS =						\
-	nsIDOMRangeException.idl	\
-	$(NULL)
-
 include $(topsrcdir)/config/rules.mk
--- a/dom/interfaces/range/nsIDOMRange.idl
+++ b/dom/interfaces/range/nsIDOMRange.idl
@@ -45,75 +45,47 @@
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
  */
 
 [scriptable, builtinclass, uuid(a059eea8-fece-4c14-93d3-7f50a944ae43)]
 interface nsIDOMRange : nsISupports
 {
   readonly attribute nsIDOMNode       startContainer;
-                                        // raises(DOMException) on retrieval
-
   readonly attribute long             startOffset;
-                                        // raises(DOMException) on retrieval
-
   readonly attribute nsIDOMNode       endContainer;
-                                        // raises(DOMException) on retrieval
-
   readonly attribute long             endOffset;
-                                        // raises(DOMException) on retrieval
-
   readonly attribute boolean          collapsed;
-                                        // raises(DOMException) on retrieval
-
   readonly attribute nsIDOMNode       commonAncestorContainer;
-                                        // raises(DOMException) on retrieval
 
-  void               setStart(in nsIDOMNode refNode, in long offset)
-                                        raises(RangeException, DOMException);
-  void               setEnd(in nsIDOMNode refNode, in long offset)
-                                        raises(RangeException, DOMException);
-  void               setStartBefore(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
-  void               setStartAfter(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
-  void               setEndBefore(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
-  void               setEndAfter(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
-  void               collapse(in boolean toStart)
-                                        raises(DOMException);
-  void               selectNode(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
-  void               selectNodeContents(in nsIDOMNode refNode)
-                                        raises(RangeException, DOMException);
+  void               setStart(in nsIDOMNode refNode, in long offset);
+  void               setEnd(in nsIDOMNode refNode, in long offset);
+  void               setStartBefore(in nsIDOMNode refNode);
+  void               setStartAfter(in nsIDOMNode refNode);
+  void               setEndBefore(in nsIDOMNode refNode);
+  void               setEndAfter(in nsIDOMNode refNode);
+  void               collapse(in boolean toStart);
+  void               selectNode(in nsIDOMNode refNode);
+  void               selectNodeContents(in nsIDOMNode refNode);
 
   // CompareHow
   const unsigned short      START_TO_START                 = 0;
   const unsigned short      START_TO_END                   = 1;
   const unsigned short      END_TO_END                     = 2;
   const unsigned short      END_TO_START                   = 3;
 
   short              compareBoundaryPoints(in unsigned short how,
-                                           in nsIDOMRange sourceRange)
-                                        raises(DOMException);
-  void               deleteContents()
-                                        raises(DOMException);
-  nsIDOMDocumentFragment extractContents()
-                                        raises(DOMException);
-  nsIDOMDocumentFragment cloneContents()
-                                        raises(DOMException);
-  void               insertNode(in nsIDOMNode newNode)
-                                        raises(DOMException, RangeException);
-  void               surroundContents(in nsIDOMNode newParent)
-                                        raises(DOMException, RangeException);
-  nsIDOMRange        cloneRange()
-                                        raises(DOMException);
-  DOMString          toString()
-                                        raises(DOMException);
+                                           in nsIDOMRange sourceRange);
+  void               deleteContents();
+  nsIDOMDocumentFragment extractContents();
+  nsIDOMDocumentFragment cloneContents();
+  void               insertNode(in nsIDOMNode newNode);
+  void               surroundContents(in nsIDOMNode newParent);
+  nsIDOMRange        cloneRange();
+  DOMString          toString();
   void               detach();
   
   // This method comes from
   // http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface
   nsIDOMDocumentFragment    createContextualFragment(in DOMString fragment);
 
   // This returns true if parent+offset equals either
   // of the boundary points or is between them.
deleted file mode 100644
--- a/dom/interfaces/range/nsIDOMRangeException.idl
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Peter Van der Beken <peterv@netscape.com> (original author)
- *
- *
- * 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 ***** */
-
-/*
- * The complete Range spec is located at:
- * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html
- */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(0f807301-39d2-11d6-a7f2-8f504ff870dc)]
-interface nsIDOMRangeException : nsISupports
-{
-  const unsigned short      BAD_BOUNDARYPOINTS_ERR         = 1;
-  const unsigned short      INVALID_NODE_TYPE_ERR          = 2;
-
-  readonly attribute unsigned short code;
-};
--- a/dom/interfaces/storage/nsPIDOMStorage.h
+++ b/dom/interfaces/storage/nsPIDOMStorage.h
@@ -54,24 +54,22 @@ class nsIPrincipal;
 
 class nsPIDOMStorage : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMSTORAGE_IID)
 
   typedef enum {
     Unknown = 0,
-    GlobalStorage = 1,
-    LocalStorage = 2,
-    SessionStorage = 3
+    LocalStorage = 1,
+    SessionStorage = 2
   } nsDOMStorageType;
 
   virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0;
   virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0;
-  virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded) = 0;
 
   virtual already_AddRefed<nsIDOMStorage> Clone() = 0;
   virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI) = 0;
   virtual bool IsForkOf(nsIDOMStorage* aThat) = 0;
 
   virtual nsTArray<nsString> *GetKeys() = 0;
 
   virtual nsIPrincipal* Principal() = 0;
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -109,17 +109,16 @@ IsEqualNodeWarning=Use of attributes' is
 TextContentWarning=Use of attributes' textContent attribute is deprecated. Use value instead.
 EnablePrivilegeWarning=Use of enablePrivilege is deprecated.  Please use code that runs with the system principal (e.g. an extension) instead.
 PositionWarning=Use of XMLHttpRequest's progress events' position attribute is deprecated.
 TotalSizeWarning=Use of XMLHttpRequest's progress events' totalSize attribute is deprecated.
 nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated.  Please use JSON.parse instead.
 nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated.  Please use JSON.stringify instead.
 nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
 InputEncodingWarning=Use of inputEncoding is deprecated.
-GlobalStorageWarning=Use of globalStorage is deprecated. Please use localStorage instead.
 # LOCALIZATION NOTE: Do not translate "MozBeforePaint" and "mozRequestAnimationFrame"
 MozBeforePaintWarning=MozBeforePaint events are no longer supported.  mozRequestAnimationFrame must be passed a non-null callback argument.
 FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
 FullScreenDeniedFocusedPlugin=Request for full-screen was denied because a windowed plugin is focused.
 FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
 FullScreenDeniedIframeDisallowed=Request for full-screen was denied because at least one of the document's containing iframes does not have a "mozallowfullscreen" attribute.
 FullScreenDeniedNotInputDriven=Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler.
 FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -452,17 +452,17 @@ JSValToNPVariant(NPP npp, JSContext *cx,
     } else if (JSVAL_IS_NULL(val)) {
       NULL_TO_NPVARIANT(*variant);
     } else if (JSVAL_IS_BOOLEAN(val)) {
       BOOLEAN_TO_NPVARIANT(JSVAL_TO_BOOLEAN(val), *variant);
     } else if (JSVAL_IS_INT(val)) {
       INT32_TO_NPVARIANT(JSVAL_TO_INT(val), *variant);
     } else if (JSVAL_IS_DOUBLE(val)) {
       double d = JSVAL_TO_DOUBLE(val);
-      jsint i;
+      int i;
       if (JS_DoubleIsInt32(d, &i)) {
         INT32_TO_NPVARIANT(i, *variant);
       } else {
         DOUBLE_TO_NPVARIANT(d, *variant);
       }
     } else if (JSVAL_IS_STRING(val)) {
       JSString *jsstr = JSVAL_TO_STRING(val);
       size_t length;
--- a/dom/plugins/base/nsNPAPIPlugin.h
+++ b/dom/plugins/base/nsNPAPIPlugin.h
@@ -152,24 +152,24 @@ StringToNPIdentifier(JSContext *cx, JSSt
 }
 
 inline bool
 NPIdentifierIsInt(NPIdentifier id)
 {
     return JSID_IS_INT(NPIdentifierToJSId(id));
 }
 
-inline jsint
+inline int
 NPIdentifierToInt(NPIdentifier id)
 {
     return JSID_TO_INT(NPIdentifierToJSId(id));
 }
 
 inline NPIdentifier
-IntToNPIdentifier(jsint i)
+IntToNPIdentifier(int i)
 {
     return JSIdToNPIdentifier(INT_TO_JSID(i));
 }
 
 JSContext* GetJSContext(NPP npp);
 
 inline bool
 NPStringIdentifierIsPermanent(NPP npp, NPIdentifier id)
--- a/dom/src/storage/StorageChild.cpp
+++ b/dom/src/storage/StorageChild.cpp
@@ -125,23 +125,16 @@ StorageChild::InitAsSessionStorage(nsIUR
 
 void
 StorageChild::InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist)
 {
   DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist);
   InitRemote();
 }
 
-void
-StorageChild::InitAsGlobalStorage(const nsACString& aDomainDemanded)
-{
-  DOMStorageBase::InitAsGlobalStorage(aDomainDemanded);
-  InitRemote();
-}
-
 nsTArray<nsString>*
 StorageChild::GetKeys(bool aCallerSecure)
 {
   InfallibleTArray<nsString> remoteKeys;
   SendGetKeys(aCallerSecure, &remoteKeys);
   nsTArray<nsString>* keys = new nsTArray<nsString>;
   *keys = remoteKeys;
   return keys;
--- a/dom/src/storage/StorageChild.h
+++ b/dom/src/storage/StorageChild.h
@@ -54,17 +54,16 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS(StorageChild)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   
   StorageChild(nsDOMStorage* aOwner);
   StorageChild(nsDOMStorage* aOwner, StorageChild& aOther);
 
   virtual void InitAsSessionStorage(nsIURI* aDomainURI);
   virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist);
-  virtual void InitAsGlobalStorage(const nsACString& aDomainDemanded);
 
   virtual bool CacheStoragePermissions();
   
   virtual nsTArray<nsString>* GetKeys(bool aCallerSecure);
   virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength);
   virtual nsresult GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey);
   virtual nsIDOMStorageItem* GetValue(bool aCallerSecure, const nsAString& aKey,
                                       nsresult* rv);
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -694,37 +694,16 @@ DOMStorageBase::InitAsLocalStorage(nsIUR
   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
                                                 true, false, mQuotaDomainDBKey);
   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
                                                 true, true, mQuotaETLDplus1DomainDBKey);
   mCanUseChromePersist = aCanUseChromePersist;
   mStorageType = nsPIDOMStorage::LocalStorage;
 }
 
-void
-DOMStorageBase::InitAsGlobalStorage(const nsACString& aDomainDemanded)
-{
-  mDomain = aDomainDemanded;
-
-  nsDOMStorageDBWrapper::CreateDomainScopeDBKey(aDomainDemanded, mScopeDBKey);
-
-  // XXX Bug 357323, we have to solve the issue how to define
-  // origin for file URLs. In that case CreateOriginScopeDBKey
-  // fails (the result is empty) and we must avoid database use
-  // in that case because it produces broken entries w/o owner.
-  if (!(mUseDB = !mScopeDBKey.IsEmpty()))
-    mScopeDBKey.AppendLiteral(":");
-
-  nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomainDemanded,
-                                                true, false, mQuotaDomainDBKey);
-  nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomainDemanded,
-                                                true, true, mQuotaETLDplus1DomainDBKey);
-  mStorageType = nsPIDOMStorage::GlobalStorage;
-}
-
 PLDHashOperator
 SessionStorageTraverser(nsSessionStorageEntry* aEntry, void* userArg) {
   nsCycleCollectionTraversalCallback *cb = 
       static_cast<nsCycleCollectionTraversalCallback*>(userArg);
 
   cb->NoteXPCOMChild((nsIDOMStorageItem *) aEntry->mItem);
 
   return PL_DHASH_NEXT;
@@ -829,22 +808,16 @@ DOMStorageImpl::InitAsSessionStorage(nsI
 
 void
 DOMStorageImpl::InitAsLocalStorage(nsIURI* aDomainURI,
                                    bool aCanUseChromePersist)
 {
   DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist);
 }
 
-void
-DOMStorageImpl::InitAsGlobalStorage(const nsACString& aDomainDemanded)
-{
-  DOMStorageBase::InitAsGlobalStorage(aDomainDemanded);
-}
-
 bool
 DOMStorageImpl::CacheStoragePermissions()
 {
   // If this is a cross-process situation, we don't have a real storage owner.
   // All the correct checks have been done on the child, so we just need to
   // make sure that our session-only status is correctly updated.
   if (!mOwner)
     return nsDOMStorage::CanUseStorage(&mSessionOnly);
@@ -885,18 +858,17 @@ DOMStorageImpl::GetDBValue(const nsAStri
     return NS_OK;
 
   nsresult rv = InitDB();
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString value;
   rv = gStorageDB->GetKeyValue(this, aKey, value, aSecure);
 
-  if (rv == NS_ERROR_DOM_NOT_FOUND_ERR &&
-      mStorageType != nsPIDOMStorage::GlobalStorage) {
+  if (rv == NS_ERROR_DOM_NOT_FOUND_ERR) {
     SetDOMStringToNull(aValue);
   }
 
   if (NS_FAILED(rv))
     return rv;
 
   aValue.Assign(value);
 
@@ -1432,25 +1404,16 @@ nsDOMStorage::InitAsLocalStorage(nsIPrin
   if (NS_SUCCEEDED(aPrincipal->GetURI(getter_AddRefs(URI))) && URI) {
     canUseChromePersist = URICanUseChromePersist(URI);
   }
   
   mStorageImpl->InitAsLocalStorage(domainURI, canUseChromePersist);
   return NS_OK;
 }
 
-nsresult
-nsDOMStorage::InitAsGlobalStorage(const nsACString &aDomainDemanded)
-{
-  mStorageType = GlobalStorage;
-  mEventBroadcaster = this;
-  mStorageImpl->InitAsGlobalStorage(aDomainDemanded);
-  return NS_OK;
-}
-
 //static
 bool
 nsDOMStorage::CanUseStorage(bool* aSessionOnly)
 {
   // check if the calling domain can use storage. Downgrade to session
   // only if only session storage may be used.
   NS_ASSERTION(aSessionOnly, "null session flag");
   *aSessionOnly = false;
@@ -1607,35 +1570,31 @@ nsDOMStorage::GetItem(const nsAString& a
 static Telemetry::ID
 TelemetryIDForKey(nsPIDOMStorage::nsDOMStorageType type)
 {
   switch (type) {
   default:
     MOZ_ASSERT(false);
     // We need to return something to satisfy the compiler.
     // Fallthrough.
-  case nsPIDOMStorage::GlobalStorage:
-    return Telemetry::GLOBALDOMSTORAGE_KEY_SIZE_BYTES;
   case nsPIDOMStorage::LocalStorage:
     return Telemetry::LOCALDOMSTORAGE_KEY_SIZE_BYTES;
   case nsPIDOMStorage::SessionStorage:
     return Telemetry::SESSIONDOMSTORAGE_KEY_SIZE_BYTES;
   }
 }
 
 static Telemetry::ID
 TelemetryIDForValue(nsPIDOMStorage::nsDOMStorageType type)
 {
   switch (type) {
   default:
     MOZ_ASSERT(false);
     // We need to return something to satisfy the compiler.
     // Fallthrough.
-  case nsPIDOMStorage::GlobalStorage:
-    return Telemetry::GLOBALDOMSTORAGE_VALUE_SIZE_BYTES;
   case nsPIDOMStorage::LocalStorage:
     return Telemetry::LOCALDOMSTORAGE_VALUE_SIZE_BYTES;
   case nsPIDOMStorage::SessionStorage:
     return Telemetry::SESSIONDOMSTORAGE_VALUE_SIZE_BYTES;
   }
 }
 
 NS_IMETHODIMP
@@ -1657,17 +1616,17 @@ nsDOMStorage::SetItem(const nsAString& a
   Telemetry::Accumulate(TelemetryIDForKey(mStorageType), aKey.Length());
   Telemetry::Accumulate(TelemetryIDForValue(mStorageType), aData.Length());
 
   nsString oldValue;
   nsresult rv = mStorageImpl->SetValue(IsCallerSecure(), aKey, aData, oldValue);
   if (NS_FAILED(rv))
     return rv;
 
-  if ((oldValue != aData || mStorageType == GlobalStorage) && mEventBroadcaster)
+  if (oldValue != aData && mEventBroadcaster)
     mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, aData);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
 {
   if (!CacheStoragePermissions())
@@ -1678,17 +1637,17 @@ NS_IMETHODIMP nsDOMStorage::RemoveItem(c
 
   nsString oldValue;
   nsresult rv = mStorageImpl->RemoveValue(IsCallerSecure(), aKey, oldValue);
   if (rv == NS_ERROR_DOM_NOT_FOUND_ERR)
     return NS_OK;
   if (NS_FAILED(rv))
     return rv;
 
-  if ((!oldValue.IsEmpty() && mStorageType != GlobalStorage) && mEventBroadcaster) {
+  if (!oldValue.IsEmpty() && mEventBroadcaster) {
     nsAutoString nullString;
     SetDOMStringToNull(nullString);
     mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, nullString);
   }
 
   return NS_OK;
 }
 
@@ -1864,23 +1823,16 @@ nsDOMStorage2::InitAsLocalStorage(nsIPri
 
   mStorage->mSecurityChecker = this;
   mPrincipal = aPrincipal;
   mDocumentURI = aDocumentURI;
 
   return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI);
 }
 
-nsresult
-nsDOMStorage2::InitAsGlobalStorage(const nsACString &aDomainDemanded)
-{
-  NS_ASSERTION(false, "Should not initialize nsDOMStorage2 as global storage.");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 already_AddRefed<nsIDOMStorage>
 nsDOMStorage2::Clone()
 {
   nsDOMStorage2* storage = new nsDOMStorage2(*this);
   if (!storage)
     return nsnull;
 
   storage->mStorage->CloneFrom(mStorage);
@@ -2167,21 +2119,16 @@ nsDOMStorageList::GetStorageForDomain(co
   *aResult = NS_OK;
 
   // now have a valid domain, so look it up in the storage table
   nsIDOMStorageObsolete* storage = mStorages.GetWeak(usedDomain);
   if (!storage) {
     nsRefPtr<nsDOMStorage> newstorage;
     newstorage = new nsDOMStorage();
     if (newstorage && mStorages.Put(usedDomain, newstorage)) {
-      *aResult = newstorage->InitAsGlobalStorage(usedDomain);
-      if (NS_FAILED(*aResult)) {
-        mStorages.Remove(usedDomain);
-        return nsnull;
-      }
       storage = newstorage;
     }
     else {
       *aResult = NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   return storage;
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -147,17 +147,16 @@ protected:
 class DOMStorageBase : public nsISupports
 {
 public:
   DOMStorageBase();
   DOMStorageBase(DOMStorageBase&);
 
   virtual void InitAsSessionStorage(nsIURI* aDomainURI);
   virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist);
-  virtual void InitAsGlobalStorage(const nsACString& aDomainDemanded);
 
   virtual nsTArray<nsString>* GetKeys(bool aCallerSecure) = 0;
   virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength) = 0;
   virtual nsresult GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey) = 0;
   virtual nsIDOMStorageItem* GetValue(bool aCallerSecure, const nsAString& aKey,
                                       nsresult* rv) = 0;
   virtual nsresult SetValue(bool aCallerSecure, const nsAString& aKey,
                             const nsAString& aData, nsAString& aOldValue) = 0;
@@ -246,17 +245,16 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   DOMStorageImpl(nsDOMStorage*);
   DOMStorageImpl(nsDOMStorage*, DOMStorageImpl&);
   ~DOMStorageImpl();
 
   virtual void InitAsSessionStorage(nsIURI* aDomainURI);
   virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist);
-  virtual void InitAsGlobalStorage(const nsACString& aDomainDemanded);
 
   bool SessionOnly() {
     return mSessionOnly;
   }
 
   virtual nsTArray<nsString>* GetKeys(bool aCallerSecure);
   virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength);
   virtual nsresult GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey);
@@ -357,17 +355,16 @@ public:
 
   // Helpers for implementing nsIDOMStorage
   nsresult GetItem(const nsAString& key, nsAString& aData);
   nsresult Clear();
 
   // nsPIDOMStorage
   virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
   virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
-  virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
   virtual already_AddRefed<nsIDOMStorage> Clone();
   virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
   virtual bool IsForkOf(nsIDOMStorage* aThat);
   virtual nsTArray<nsString> *GetKeys();
   virtual nsIPrincipal* Principal();
   virtual bool CanAccess(nsIPrincipal *aPrincipal);
   virtual nsDOMStorageType StorageType();
   virtual void BroadcastChangeNotification(const nsSubstring &aKey,
@@ -437,17 +434,16 @@ public:
   nsDOMStorage2(nsDOMStorage2& aThat);
   nsDOMStorage2();
 
   NS_DECL_NSIDOMSTORAGE
 
   // nsPIDOMStorage
   virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
   virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
-  virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
   virtual already_AddRefed<nsIDOMStorage> Clone();
   virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
   virtual bool IsForkOf(nsIDOMStorage* aThat);
   virtual nsTArray<nsString> *GetKeys();
   virtual nsIPrincipal* Principal();
   virtual bool CanAccess(nsIPrincipal *aPrincipal);
   virtual nsDOMStorageType StorageType();
   virtual void BroadcastChangeNotification(const nsSubstring &aKey,
--- a/dom/tests/mochitest/Makefile.in
+++ b/dom/tests/mochitest/Makefile.in
@@ -48,17 +48,16 @@ DIRS	+= \
 	dom-level2-core \
 	dom-level2-html \
 	ajax \
 	bugs \
 	chrome \
 	general \
 	whatwg \
 	geolocation \
-	globalstorage \
 	localstorage \
 	orientation \
 	sessionstorage \
 	storageevent \
 	$(NULL)
 
 #needs IPC support, also tests do not run successfully in Firefox for now
 #ifneq (mobile,$(MOZ_BUILD_APP))
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -73,36 +73,27 @@ include $(topsrcdir)/config/rules.mk
 		test_bug384122.html \
 		test_bug389366.html \
 		test_bug393974.html \
 		test_bug394769.html \
 		test_bug396843.html \
 		test_bug397571.html \
 		test_bug400204.html \
 		test_bug404748.html \
-		test_bug407839.html \
-		iframe_bug407839-1.html \
-		iframe_bug407839-2.html \
-		test_bug424093.html \
-		iframe_bug424093.html \
-		test_bug409349.html \
-		iframe_bug409349.html \
 		test_bug411103.html \
 		test_bug414291.html \
 		test_bug430276.html \
 		iframe_bug430276.html \
 		iframe_bug430276-2.html \
 		test_bug440572.html \
 		iframe_bug440572.html \
 		test_bug437361.html \
 		test_bug458091.html \
 		bug458091_child.html \
 		test_bug459848.html \
-		test_bug463000.html \
-		iframe_bug463000.html \
 		test_bug465263.html \
 		test_bug479143.html \
 		test_bug484775.html \
 		test_bug427744.html \
 		test_bug492925.html \
 		test_bug495219.html \
 		test_bug504862.html \
 		file_bug504862.html \
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/iframe_bug407839-1.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Child window at test1.example.org</title>
-  <script type="application/javascript">
-
-function run()
-{
-  var storage;
-
-  var message = "child-response";
-
-  // This script expects to be loaded as test1.example.org
-  if (window.location.host != "test1.example.org") {
-    message += "\n child not loaded as test1.example.org";
-  }
-
-  try {
-    storage = globalStorage["test1.example.org"];
-  }
-  catch (ex) {
-    message += "\n failed globalStorage[\"test1.example.org\"]";
-  }
-
-  try {
-    storage = globalStorage["test1.EXAMPLE.ORG"];
-  }
-  catch (ex) {
-    message += "\n failed globalStorage[\"test1.EXAMPLE.ORG\"]";
-  }
-
-  try {
-    storage = globalStorage["example.org"];
-    message += "\n passed globalStorage[\"example.org\"]";
-  }
-  catch (ex) {
-  }
-
-  try {
-    storage = globalStorage["org"];
-    message += "\n passed globalStorage[\"org\"]";
-  }
-  catch (ex) {
-  }
-
-  try {
-    storage = globalStorage["test2.test1.example.org"];
-    message += "\n passed globalStorage[\"test2.test1.example.org\"]";
-  }
-  catch (ex) {
-  }
-
-  try {
-    storage = globalStorage[""];
-    message += "\n passed globalStorage[\"\"]";
-  }
-  catch (ex) {
-  }
-  window.parent.postMessage(message, "http://mochi.test:8888");
-}
-
-window.addEventListener("load", run, false);
-  </script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/iframe_bug407839-2.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
-  <title>Child window at sub1.ält.example.org</title>
-  <script type="application/javascript">
-
-function run()
-{
-  var storage;
-
-  var message = "child-response";
-
-  // This script expects to be loaded as sub1.ält.example.org
-  if (window.location.host != "sub1.ält.example.org:8000") {
-    message += "\n child not loaded as sub1.ält.example.org:8000";
-  }
-
-  try {
-    storage = globalStorage["sub1.ält.example.org"];
-  }
-  catch (ex) {
-    message += "\n failed globalStorage[sub1.ält.example.org]";
-  }
-
-  window.parent.postMessage(message, "http://mochi.test:8888");
-}
-
-window.addEventListener("load", run, false);
-  </script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/iframe_bug409349.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Child window at 127.0.0.1</title>
-  <script type="application/javascript">
-  
-function run()
-{
-  var storage;
-  
-  var message = "child-response";
-  
-  try {
-    storage = globalStorage["127.0.0.1"];
-  }
-  catch (ex) {
-    message += "\n failed globalStorage[\"127.0.0.1\"]";
-  }
-  
-  try {
-    storage = globalStorage["126.0.0.1"];
-    message += "\n passed globalStorage[\"126.0.0.1\"]";
-  }
-  catch (ex) {
-  }
-  
-  try {
-    storage = globalStorage["0.0.1"];
-    message += "\n passed globalStorage[\"0.0.1\"]";
-  }
-  catch (ex) {
-  }
-  
-  try {
-    storage = globalStorage["126.0.0"];
-    message += "\n passed globalStorage[\"126.0.0\"]";
-  }
-  catch (ex) {
-  }
-  
-  try {
-    storage = globalStorage["X.126.0.0.1"];
-    message += "\n passed globalStorage[\"X.126.0.0.1\"]";
-  }
-  catch (ex) {
-  }
-  
-  try {
-    storage = globalStorage["X.0.0.1"];
-    message += "\n passed globalStorage[\"X.0.0.1\"]";
-  }
-  catch (ex) {
-  }
-
-  window.parent.postMessage(message, "http://mochi.test:8888");
-}
-
-window.addEventListener("load", run, false);
-  </script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/iframe_bug424093.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Child window at test1.example.org</title>
-  <script type="application/javascript">
-
-function run()
-{
-  var storage;
-
-  var message = "child-response";
-
-  // This script expects to be loaded as test1.example.org
-  if (window.location.host != "test1.example.org") {
-    message += "\n child not loaded as test1.example.org";
-  }
-
-  document.domain = "example.org";
-
-  try {
-    storage = globalStorage["test1.example.org"];
-    message += "\n passed globalStorage[\"test1.example.org\"]";
-  }
-  catch (ex) {
-  }
-
-  try {
-    storage = globalStorage["example.org"];
-  }
-  catch (ex) {
-    message += "\n failed globalStorage[\"example.org\"]";
-  }
-
-  window.parent.postMessage(message, "http://mochi.test:8888");
-}
-
-window.addEventListener("load", run, false);
-  </script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/iframe_bug463000.html
+++ /dev/null
@@ -1,152 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Child window for the private browsing test</title>
-  <script type="application/javascript">
-
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-var _PBSvc = null;
-function get_PBSvc() {
-  if (_PBSvc)
-    return _PBSvc;
-
-  try {
-    _PBSvc = Cc["@mozilla.org/privatebrowsing;1"].
-             getService(Ci.nsIPrivateBrowsingService);
-    return _PBSvc;
-  } catch (e) {}
-  return null;
-}
-
-function run()
-{
-  var storage;
-
-  var message = "child-response";
-
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var prefBranch = Cc["@mozilla.org/preferences-service;1"].
-                   getService(Ci.nsIPrefBranch);
-  prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-
-  var pb = get_PBSvc();
-  // The private browsing service might not be available
-  if (pb) {
-    try {
-      storage = globalStorage["example.org"];
-    }
-    catch (ex) {
-      message += "\n failed globalStorage[\"example.org\"]";
-    }
-
-    // save Pair-A
-    try {
-      storage.key1 = "value-1";
-    }
-    catch (ex) {
-      message += "\n failed to store Pair-A";
-    }
-
-    // ensure that Pair-A exists
-    try {
-      if (storage.key1 != "value-1")
-        throw "error";
-    }
-    catch (ex) {
-      if (ex == "error")
-        message += "\n Pair-A was not saved correctly";
-      else
-        message += "\n Unexpected exception encountered while checking Pair-A: " + ex;
-    }
-
-    // enter the private browsing mode
-    try {
-      pb.privateBrowsingEnabled = true;
-    }
-    catch (ex) {
-      message += "\n failed to enter the private browsing mode";
-    }
-
-    // ensure that Pair-A does not exist
-    try {
-      // because of bug 426436, |typeof storage.key1 != "undefined"| wouldn't work here
-      if (storage.key1 != "")
-        throw "error";
-    }
-    catch (ex) {
-      if (ex == "error")
-        message += "\n Pair-A existed unexpectedly";
-      else
-        message += "\n Unexpected exception encountered while checking Pair-A (2): " + ex;
-    }
-
-    // attempt to save Pair-B
-    try {
-      storage.key2 = "value-2";
-    }
-    catch (ex) {
-      message += "\n failed to store Pair-B";
-    }
-
-    // ensure that Pair-B exists
-    try {
-      if (storage.key2 != "value-2")
-        throw "error";
-    }
-    catch (ex) {
-      if (ex == "error")
-        message += "\n Pair-B was not retrieved correctly";
-      else
-        message += "\n Unexpected exception encountered while checking Pair-B: " + ex;
-    }
-
-    // exit the private browsing mode
-    try {
-      pb.privateBrowsingEnabled = false;
-    }
-    catch (ex) {
-      message += "\n failed to exit the private browsing mode";
-    }
-
-    // ensure that Pair-A exists
-    try {
-      if (storage.key1 != "value-1")
-        throw "error";
-    }
-    catch (ex) {
-      if (ex == "error")
-        message += "\n Pair-A was not retrieved correctly";
-      else
-        message += "\n Unexpected exception encountered while checking Pair-A (3): " + ex;
-    }
-
-    // ensure that Pair-B does not exist
-    try {
-      // because of bug 426436, |typeof storage.key2 != "undefined"| wouldn't work here
-      if (storage.key2 != "")
-        throw "error";
-    }
-    catch (ex) {
-      if (ex == "error")
-        message += "\n Pair-B existed unexpectedly";
-      else
-        message += "\n Unexpected exception encountered while checking Pair-B (2): " + ex;
-    }
-  }
-
-  prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
-
-  window.parent.postMessage(message, "http://mochi.test:8888");
-}
-
-window.addEventListener("load", run, false);
-  </script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/test_bug407839.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=407839
--->
-<head>
-  <title>Test for Bug 407839</title>
-  <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=407839">Mozilla Bug 407839</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-
-<iframe name="child" src="http://TEST1.example.org/tests/dom/tests/mochitest/bugs/iframe_bug407839-1.html"></iframe>
-<iframe name="idn" src="http://sub1.ält.example.org:8000/tests/dom/tests/mochitest/bugs/iframe_bug407839-2.html"></iframe>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-/** Test for Bug 407839 **/
-
-SimpleTest.waitForExplicitFinish();
-
-var gNumMessages = 0;
-
-function receiveMessage(evt)
-{
-  is(evt.data, "child-response", "got wrong response");
-
-  if (++gNumMessages == 2) {
-    SimpleTest.finish();
-  }
-}
-
-window.addEventListener("message", receiveMessage, false);
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/test_bug409349.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Cannot get globalStorage objects for partial IP addresses</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-
-<iframe name="child" src="http://127.0.0.1:8888/tests/dom/tests/mochitest/bugs/iframe_bug409349.html"></iframe>
-
-<pre id="test">
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-function receiveMessage(evt)
-{
-  is(evt.origin, "http://127.0.0.1:8888", "wrong sender");
-  ok(evt.source === window.frames.child, "wrong sender");
-
-  is(evt.data, "child-response", "got wrong response");
-
-  SimpleTest.finish();
-}
-
-window.addEventListener("message", receiveMessage, false);
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/test_bug424093.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=424093
--->
-<head>
-  <title>Test for Bug 424093</title>
-  <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=424093">Mozilla Bug 424093</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-
-<iframe name="child" src="http://test1.example.org/tests/dom/tests/mochitest/bugs/iframe_bug424093.html"></iframe>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-/** Test for Bug 424093 **/
-
-SimpleTest.waitForExplicitFinish();
-
-function receiveMessage(evt)
-{
-  is(evt.data, "child-response", "got wrong response");
-
-  SimpleTest.finish();
-}
-
-window.addEventListener("message", receiveMessage, false);
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/bugs/test_bug463000.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=463000
--->
-<head>
-  <title>Test for Bug 463000</title>
-  <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=463000">Mozilla Bug 463000</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-
-<iframe src="http://example.org/tests/dom/tests/mochitest/bugs/iframe_bug463000.html"></iframe>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-/** Test for Bug 463000 **/
-
-SimpleTest.waitForExplicitFinish();
-
-function receiveMessage(evt)
-{
-  is(evt.data, "child-response", "got wrong response");
-
-  SimpleTest.finish();
-}
-
-window.addEventListener("message", receiveMessage, false);
-
-</script>
-</pre>
-</body>
-</html>
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -46,19 +46,16 @@ include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
 		test_dom_fullscreen_warning.xul \
 		dom_fullscreen_warning.xul \
 		test_fullscreen.xul \
 		fullscreen.xul \
 		test_fullscreen_preventdefault.xul \
 		fullscreen_preventdefault.xul \
-		test_domstorage.xul \
-		domstorage_global.xul \
-		domstorage_global.js \
 		focus_window2.xul \
 		focus_frameset.html \
 		child_focus_frame.html \
 		test_focus_switchbinding.xul \
 		test_focus.xul \
 		window_focus.xul \
 		test_focused_link_scroll.xul \
 		test_geolocation.xul \
deleted file mode 100644
--- a/dom/tests/mochitest/chrome/domstorage_global.js
+++ /dev/null
@@ -1,168 +0,0 @@
-ok(globalStorage === this["globalStorage"], "globalStorage is global check 1")
-ok(globalStorage === window["globalStorage"], "globalStorage is global check 2")
-
-function test_DOMStorage_global()
-{
-  var currentDomain = "mozilla.com";
-
-  var globalStorage = window.globalStorage;
-  is(globalStorage instanceof StorageList, true, "globalStorage property");
-
-  var storage = globalStorage.namedItem(currentDomain);
-  is(storage instanceof StorageObsolete, true, "StorageList namedItem");
-
-  var storage2 = globalStorage[currentDomain];
-  is(storage2 instanceof StorageObsolete, true, "StorageList property syntax");
-
-  is(storage, storage2, "StorageList namedItem and array return same value");
-
-  // the initial value should be null
-  test_DOMStorage_global_Item(storage, "sample", null, 0, "initial");
-
-  // if no key is supplied, the return value will be null
-  is(storage.getItem("", "Test"), null, "getItem no key");
-
-  exh = false;
-  try {
-    storage.key(0);
-  }
-  catch (ex) { exh = true; }
-  is(exh, true, "key index 0 too high");
-
-  // change the value
-  storage.setItem("sample", "This is the first message");
-  var item = test_DOMStorage_global_Item(storage, "sample", "This is the first message", 1, "setItem");
-
-  // change value using property syntax
-  storage.test = "Second message";
-  test_DOMStorage_global_Item(storage, "test", "Second message", 2, "setItem property");
-
-  // change the first value using property syntax
-  storage.sample = "Third message is this";
-  var item2 = test_DOMStorage_global_Item(storage, "sample", "Third message is this", 2, "setItem property again");
-
-  is(item.value, "Third message is this", "other item reference holds updated value");
-
-  // change the second value using setItem
-  storage.setItem("test", "Look at this, the fourth message");
-  test_DOMStorage_global_Item(storage, "test", "Look at this, the fourth message", 2, "setItem again");
-
-  // don't use this test currently. The spec says that the same object should
-  // always be returned, but this doesn't happen in chrome due to the wrappers
-  // being different
-  // is(item, item2, "same item always returned");
-
-  // using an empty key should not change the value
-  storage.setItem("", "Message Number Five");
-  test_DOMStorage_global_Item(storage, "test", "Look at this, the fourth message", 2, "setItem no key");
-  is(storage.getItem("", "Test"), null, "getItem no key");
-
-  // now test iteration through the keys
-  var key1 = storage.key(0);
-  var key2 = storage.key(1);
-  is(key1 != key2 && (key1 == "sample" || key1 == "test") &&
-                                (key2 == "sample" || key2 == "test"), true, "key");
-  exh = false;
-  try {
-    storage.key(2);
-  }
-  catch (ex) { exh = true; }
-  is(exh, true, "key index 2 too high");
-
-  storage.removeItem("sample");
-  test_DOMStorage_global_Item(storage, "sample", null, 1, "removeItem");
-
-  is(item.value, "", "other item reference holds deleted value");
-
-  delete storage.test;
-  test_DOMStorage_global_Item(storage, "test", null, 0, "delete item");
-
-  storage.removeItem("test");
-
-  // now test size constraints
-
-  // create a string which is 1MB - 4 bytes long. The key will use up this
-  // extra 4 bytes though.
-  var stringbit = "---abcdefghijklmnopqrstuvwxyz---";
-  var longstring = "This is quite a long string:";
-  for (var l = 0; l < 32767; l++)
-    longstring += stringbit;
-
-  var s;
-  for (s = 0; s < 5; s++)
-    storage.setItem("key" + s, longstring);
-
-  // at this point, there will be 5MB of data stored, so no more is allowed
-  exh = false;
-  try {
-    storage.setItem("keyfail", "One");
-  }
-  catch (ex) { exh = true; }
-  is(exh, true, "per-domain size constraint");
-
-  // change the first item, to free up space
-  storage.setItem("key1", "This");
-
-  // there is just under 1MB of space available, so this should fail 
-  exh = false;
-  try {
-    storage.setItem("keyfail", longstring);
-  }
-  catch (ex) { exh = true; }
-  is(exh, true, "per-domain size constraint second check");
-
-  // now clear up another value, and set it back again
-  storage.removeItem("key2");
-  storage.setItem("key2", longstring);
-
-  // this should still fail
-  exh = false;
-  try {
-    storage.setItem(keyfail, longstring);
-  }
-  catch (ex) { exh = true; }
-  is(exh, true, "per-domain size constraint third check");
-
-  // this should be stored OK
-  storage.setItem("key2", "Simple string");
-
-  for (s = 0; s < 5; s++)
-    storage.removeItem("key" + s);
-}
-
-function test_DOMStorage_global_Item(storage, key, expectedvalue, expectedlength, testid)
-{
-  var item = storage.getItem(key);
-  if (expectedvalue != null)
-    is(item instanceof StorageItem, true, testid + " is a Storage");
-
-  is(expectedvalue == null ? item : "" + item, expectedvalue, testid + " getItem");
-
-  var item2 = storage[key];
-  // skip this check for this test, as the property isn't actually removed
-  if (testid != "removeItem") {
-    if (item === null)
-      is(item2, undefined, testid + " get property syntax");
-    else
-      is(item2, item, testid + " get property syntax");
-  }
-  if (expectedvalue != null)
-    is(item2 instanceof StorageItem, true, testid + " property syntax is a Storage");
-
-  if (expectedvalue != null)
-    is(item.value, expectedvalue, testid + " value");
-
-  is(storage.length, expectedlength, testid + " length");
-
-  return item;
-}
-
-function is(left, right, str)
-{
-  window.opener.wrappedJSObject.SimpleTest.is(left, right, str);
-}
-
-function ok(val, str)
-{
-  window.opener.wrappedJSObject.SimpleTest.ok(val, str);
-}
deleted file mode 100644
--- a/dom/tests/mochitest/chrome/domstorage_global.xul
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<!--
-  Test for Persistent Storage in chrome
-  -->
-<window id="sample-window" width="400" height="400"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-<script src="domstorage_global.js"/>
-
-<script>
-test_DOMStorage_global();
-window.opener.wrappedJSObject.done();
-</script>
-
-<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
-
-</window>
deleted file mode 100644
--- a/dom/tests/mochitest/chrome/test_domstorage.xul
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<!--
-  Test for Persistent Storage in chrome
-  -->
-<window id="sample-window" width="400" height="400"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>      
-
-<script>
-SimpleTest.waitForExplicitFinish();
-
-var newwindow = window.open("domstorage_global.xul", "testwindow", "chrome");
-
-function done()
-{
-  SimpleTest.finish();
-  newwindow.close();
-}
-</script>
-
-<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
-
-</window>
--- a/dom/tests/mochitest/general/Makefile.in
+++ b/dom/tests/mochitest/general/Makefile.in
@@ -74,16 +74,17 @@ include $(topsrcdir)/config/rules.mk
 		test_vibrator.html \
 		browserFrameHelpers.js \
 		test_browserFrame1.html \
 		test_browserFrame2.html \
 		test_browserFrame3.html \
 		test_browserFrame4.html \
 		test_browserFrame5.html \
 		test_browserFrame6.html \
+		test_browserFrame7.html \
 		test_for_of.html \
 		test_focus_legend_noparent.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_innerScreen.xul \
 		test_offsets.xul \
 		test_offsets.js \
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_browserFrame7.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=725796
+-->
+<head>
+  <title>Test for Bug 725796</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserFrameHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725796">Mozilla Bug 725796</a>
+
+<!--
+  Test that an <iframe mozbrowser> is a window.{top,parent,frameElement} barrier.
+
+  If <iframe mozbrowser> is changed to run in a separate process, this test
+  will not work.
+-->
+
+<script type="application/javascript;version=1.7">
+"use strict";
+
+browserFrameHelpers.setEnabledPref(true);
+browserFrameHelpers.addToWhitelist();
+
+var iframe = document.createElement('iframe');
+iframe.mozbrowser = true;
+document.body.appendChild(iframe);
+
+var innerIframe = document.createElement('iframe');
+iframe.contentDocument.body.appendChild(innerIframe);
+
+var iframeCw = iframe.contentWindow;
+var innerCw = innerIframe.contentWindow;
+
+is(iframeCw.top, iframeCw, 'iframe top');
+is(iframeCw.parent, iframeCw, 'iframe parent');
+is(iframeCw.frameElement, null, 'iframe frameElement');
+
+is(innerCw.top, iframeCw, 'inner iframe top');
+is(innerCw.parent, iframeCw, 'inner iframe parent');
+is(innerCw.frameElement, innerIframe, 'inner iframe frameElement');
+
+</script>
+</body>
+</html>
deleted file mode 100644
--- a/dom/tests/mochitest/globalstorage/Makefile.in
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# ***** 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.org code.
-#
-# The Initial Developer of the Original Code is
-# Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2010
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# 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
-# 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 *****
-
-DEPTH		= ../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir	= dom/tests/mochitest/globalstorage
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES	= \
-		test_bug614116.html \
-		iframe_bug614116-1.html \
-		iframe_bug614116-2.html \
-		$(NULL)
-
-libs:: 	$(_TEST_FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
deleted file mode 100644
--- a/dom/tests/mochitest/globalstorage/iframe_bug614116-1.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <body onload="loaded()">
-    <script>
-      function loaded() {
-        parent.postMessage("loaded", "http://mochi.test:8888");
-      }
-
-      function onMessageReceived(e) {
-        switch (e.data) {
-        case "getdata":
-          parent.postMessage("data:" + globalStorage["example.com"].data, "http://mochi.test:8888");
-          break;
-        case "setdata":
-          var didSucceed = true;
-          try {
-            globalStorage["example.com"].data = "value2";
-          } catch(e) {
-            didSucceed = false;
-          }
-          parent.postMessage("success:" + didSucceed, "http://mochi.test:8888");
-          parent.postMessage("dataset2:" + globalStorage["example.com"].data, "http://mochi.test:8888");
-          break;
-        }
-      }
-
-      addEventListener("message", onMessageReceived, false);
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/globalstorage/iframe_bug614116-2.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <body onload="loaded()">
-    <script>
-      function loaded() {
-        parent.postMessage("loaded", "http://mochi.test:8888");
-      }
-
-      function onMessageReceived(e) {
-        switch (e.data) {
-        case "getdata":
-          parent.postMessage("data2:" + globalStorage["example.com"].data, "http://mochi.test:8888");
-          break;
-        case "setdata":
-          globalStorage["example.com"].data = "value";
-          parent.postMessage("dataset:" + globalStorage["example.com"].data, "http://mochi.test:8888");
-          break;
-        }
-      }
-
-      addEventListener("message", onMessageReceived, false);
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/globalstorage/test_bug614116.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=614116
--->
-<head>
-  <title>Test for Bug 614116</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=614116">Mozilla Bug 614116</a>
-<p id="display"></p>
-<div id="content">
-<iframe id="http"></iframe>
-<iframe id="https"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 614116 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  const httpDomain = "http://example.com";
-  const httpsDomain = "https://example.com";
-  const path = "/tests/dom/tests/mochitest/globalstorage/";
-
-  var pm = Components.classes["@mozilla.org/permissionmanager;1"]
-                     .getService(Components.interfaces.nsIPermissionManager);
-  var ios = Components.classes["@mozilla.org/network/io-service;1"]
-                      .getService(Components.interfaces.nsIIOService);
-  pm.add(ios.newURI(httpDomain, null, null), "cookie", Components.interfaces.nsICookiePermission.ACCESS_SESSION);
-  pm.add(ios.newURI(httpsDomain, null, null), "cookie", Components.interfaces.nsICookiePermission.ACCESS_SESSION);
-
-  var http = document.getElementById("http");
-  var https = document.getElementById("https");
-
-  function finishTest() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    pm.remove("example.com", "cookie");
-    SimpleTest.finish();
-  }
-
-  var loaded = 0;
-  function onMessageReceived(e) {
-    switch (e.data) {
-    case "loaded":
-      ++loaded;
-      ok(loaded <= 2, "Two iframes should be loaded at most");
-      if (loaded == 2) {
-        https.contentWindow.postMessage("setdata", httpsDomain);
-      }
-      break;
-    default:
-      if (e.data.indexOf("dataset:") == 0) {
-        is(e.data.substr(8), "value", "Correct value should be set");
-        http.contentWindow.postMessage("getdata", httpDomain);
-      } else if (e.data.indexOf("data:") == 0) {
-        is(e.data.substr(5), "undefined", "Data should not be available in HTTP mode");
-        http.contentWindow.postMessage("setdata", httpDomain);
-      } else if (e.data.indexOf("dataset2:") == 0) {
-        is(e.data.substr(9), "undefined", "Correct value should be set");
-        https.contentWindow.postMessage("getdata", httpsDomain);
-      } else if (e.data.indexOf("data2:") == 0) {
-        is(e.data.substr(6), "value", "Data should not be modified in HTTP mode");
-        finishTest();
-      } else if (e.data.indexOf("success:") == 0) {
-        is(e.data.substr(8), "false", "Setting the value in HTTP mode should fail");
-      }
-    }
-  }
-
-  window.addEventListener("message", onMessageReceived, false);
-
-  http.src = httpDomain + path + "iframe_bug614116-1.html";
-  https.src = httpsDomain + path + "iframe_bug614116-2.html";
-});
-
-</script>
-</pre>
-</body>
-</html>
--- a/dom/tests/mochitest/localstorage/test_localStorageBase.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageBase.html
@@ -89,36 +89,39 @@ function startTest()
   localStorage.setItem("key1", "value1");
   is(localStorage.length, 1, "The storage has one key-value pair");
   is(localStorage.key(0), "key1");
   is(localStorage.getItem("key1"), "value1");
 
   // add a second key
   localStorage.setItem("key2", "value2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // This test might not be accurate because order is not preserved
-  is(localStorage.key(0), "key2");
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2");
+  var firstKey = localStorage.key(0);
+  var secondKey = localStorage.key(1);
+  ok((firstKey == 'key1' && secondKey == 'key2') ||
+     (firstKey == 'key2' && secondKey == 'key1'),
+     'Both keys should be present.');
 
   // change the second key
   localStorage.setItem("key2", "value2-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2-2");
 
   // change the first key
   localStorage.setItem("key1", "value1-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1-2");
   is(localStorage.getItem("key2"), "value2-2");
 
   // remove the second key
   localStorage.removeItem("key2");
   is(localStorage.length, 1, "The storage has one key-value pair");
--- a/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing.html
@@ -108,36 +108,39 @@ function doTest()
   localStorage.setItem("key1", "value1");
   is(localStorage.length, 1, "The storage has one key-value pair");
   is(localStorage.key(0), "key1");
   is(localStorage.getItem("key1"), "value1");
 
   // add a second key
   localStorage.setItem("key2", "value2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // This test might not be accurate because order is not preserved
-  is(localStorage.key(0), "key2");
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2");
+  var firstKey = localStorage.key(0);
+  var secondKey = localStorage.key(1);
+  ok((firstKey == 'key1' && secondKey == 'key2') ||
+     (firstKey == 'key2' && secondKey == 'key1'),
+     'Both keys should be present.');
 
   // change the second key
   localStorage.setItem("key2", "value2-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2-2");
 
   // change the first key
   localStorage.setItem("key1", "value1-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1-2");
   is(localStorage.getItem("key2"), "value2-2");
 
   // remove the second key
   localStorage.removeItem("key2");
   is(localStorage.length, 1, "The storage has one key-value pair");
--- a/dom/tests/mochitest/localstorage/test_localStorageBaseSessionOnly.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageBaseSessionOnly.html
@@ -99,36 +99,39 @@ function startTest()
   localStorage.setItem("key1", "value1");
   is(localStorage.length, 1, "The storage has one key-value pair");
   is(localStorage.key(0), "key1");
   is(localStorage.getItem("key1"), "value1");
 
   // add a second key
   localStorage.setItem("key2", "value2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // This test might not be accurate because order is not preserved
-  is(localStorage.key(0), "key2");
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2");
+  var firstKey = localStorage.key(0);
+  var secondKey = localStorage.key(1);
+  ok((firstKey == 'key1' && secondKey == 'key2') ||
+     (firstKey == 'key2' && secondKey == 'key1'),
+     'Both keys should be present.');
 
   // change the second key
   localStorage.setItem("key2", "value2-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1");
   is(localStorage.getItem("key2"), "value2-2");
 
   // change the first key
   localStorage.setItem("key1", "value1-2");
   is(localStorage.length, 2, "The storage has two key-value pairs");
-  is(localStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(localStorage.key(0), "key2");
+  is(localStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(localStorage.key(1), secondKey);
   checkException(function() {localStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {localStorage.key(2);}, INDEX_SIZE_ERR);
   is(localStorage.getItem("key1"), "value1-2");
   is(localStorage.getItem("key2"), "value2-2");
 
   // remove the second key
   localStorage.removeItem("key2");
   is(localStorage.length, 1, "The storage has one key-value pair");
--- a/dom/tests/mochitest/sessionstorage/test_sessionStorageBase.html
+++ b/dom/tests/mochitest/sessionstorage/test_sessionStorageBase.html
@@ -91,36 +91,39 @@ function startTest()
   sessionStorage.setItem("key1", "value1");
   is(sessionStorage.length, 1, "The storage has one key-value pair");
   is(sessionStorage.key(0), "key1");
   is(sessionStorage.getItem("key1"), "value1");
 
   // add a second key
   sessionStorage.setItem("key2", "value2");
   is(sessionStorage.length, 2, "The storage has two key-value pairs");
-  is(sessionStorage.key(1), "key1"); // This test might not be accurate because order is not preserved
-  is(sessionStorage.key(0), "key2");
   is(sessionStorage.getItem("key1"), "value1");
   is(sessionStorage.getItem("key2"), "value2");
+  var firstKey = sessionStorage.key(0);
+  var secondKey = sessionStorage.key(1);
+  ok((firstKey == 'key1' && secondKey == 'key2') ||
+     (firstKey == 'key2' && secondKey == 'key1'),
+     'Both keys should be present.');
 
   // change the second key
   sessionStorage.setItem("key2", "value2-2");
   is(sessionStorage.length, 2, "The storage has two key-value pairs");
-  is(sessionStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(sessionStorage.key(0), "key2");
+  is(sessionStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(sessionStorage.key(1), secondKey);
   checkException(function() {sessionStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {sessionStorage.key(2);}, INDEX_SIZE_ERR);
   is(sessionStorage.getItem("key1"), "value1");
   is(sessionStorage.getItem("key2"), "value2-2");
 
   // change the first key
   sessionStorage.setItem("key1", "value1-2");
   is(sessionStorage.length, 2, "The storage has two key-value pairs");
-  is(sessionStorage.key(1), "key1"); // After key value changes the order must be preserved
-  is(sessionStorage.key(0), "key2");
+  is(sessionStorage.key(0), firstKey); // After key value changes the order must be preserved
+  is(sessionStorage.key(1), secondKey);
   checkException(function() {sessionStorage.key(-1);}, INDEX_SIZE_ERR);
   checkException(function() {sessionStorage.key(2);}, INDEX_SIZE_ERR);
   is(sessionStorage.getItem("key1"), "value1-2");
   is(sessionStorage.getItem("key2"), "value2-2");
 
   // remove the second key
   sessionStorage.removeItem("key2");
   is(sessionStorage.length, 1, "The storage has one key-value pair");
--- a/dom/tests/mochitest/storageevent/Makefile.in
+++ b/dom/tests/mochitest/storageevent/Makefile.in
@@ -42,28 +42,23 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir	= dom/tests/mochitest/storageevent
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES	= \
-    frameGlobalStorageMaster.html \
-    frameGlobalStorageSlaveEqual.html \
-    frameGlobalStorageSlaveNotEqual.html \
     frameLocalStorageMaster.html \
     frameLocalStorageSlaveEqual.html \
     frameLocalStorageSlaveNotEqual.html \
     frameSessionStorageMasterEqual.html \
     frameSessionStorageMasterNotEqual.html \
     frameSessionStorageSlaveEqual.html \
     frameSessionStorageSlaveNotEqual.html \
-    test_storageGlobalStorageEventCheckNoPropagation.html \
-    test_storageGlobalStorageEventCheckPropagation.html \
     test_storageLocalStorageEventCheckNoPropagation.html \
     test_storageLocalStorageEventCheckPropagation.html \
     test_storageSessionStorageEventCheckPropagation.html \
     test_storageSessionStorageEventCheckNoPropagation.html \
     interOriginFrame.js \
     interOriginTest2.js \
     $(NULL)
 
deleted file mode 100644
--- a/dom/tests/mochitest/storageevent/frameGlobalStorageMaster.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>master frame for event storage propagation</title>
-
-<script type="text/javascript" src="interOriginFrame.js"></script>
-<script type="text/javascript">
-
-var currentStep = 1;
-var gotEvent = false;
-
-function bind()
-{
-  document.body.addEventListener("storage", function(event)
-  {
-    gotEvent = true;
-  }, false);
-}
-
-function doStep()
-{
-  switch (currentStep)
-  {
-    case 1:
-      var storage = globalStorage[location.host];
-      storage.setItem("X", "1");
-      storage.setItem("X", "2");
-      storage.setItem("X", "2");
-      storage.removeItem("X");
-      storage.removeItem("X");
-      storage.removeItem("Y");
-      storage.setItem("X", "2");
-      break;
-
-    case 3:
-      todo(gotEvent, false, "Expected no events");
-      return finishTest();
-  }
-
-  // Increase by two to distinguish each test step order
-  // in both master doStep and slave doStep functions.
-  ++currentStep;
-  ++currentStep;
-
-  return true;
-}
-
-</script>
-
-</head>
-
-<body onload="bind(); postMsg('frame loaded');">
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/storageevent/frameGlobalStorageSlaveEqual.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>slave for storage event propagation</title>
-
-<script type="text/javascript" src="interOriginFrame.js"></script>
-<script type="text/javascript">
-
-var currentStep = 2;
-
-var events = [];
-
-function bind()
-{
-  document.body.addEventListener("storage", function(event)
-  {
-    events.push(event);
-  }, false);
-}
-
-function doStep()
-{
-  function checkEvent()
-  {
-    var event = events.shift();
-    ok(event);
-    if (!event)
-      return;
-    is(event.domain, "example.com");
-  }
-
-  switch (currentStep)
-  {
-    case 2:
-      is(events.length, 4, "Expected 5 events");
-      checkEvent();
-      checkEvent();
-      checkEvent();
-      checkEvent();
-      break;
-  }
-
-  // Increase by two to distinguish each test step order
-  // in both master doStep and slave doStep functions.
-  ++currentStep;
-  ++currentStep;
-
-  return true;
-}
-
-</script>
-
-</head>
-
-<body onload="bind(); postMsg('frame loaded');">
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/storageevent/frameGlobalStorageSlaveNotEqual.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>slave for storage event propagation</title>
-
-<script type="text/javascript" src="interOriginFrame.js"></script>
-<script type="text/javascript">
-
-var currentStep = 2;
-var gotEvent = false;
-
-function bind()
-{
-  document.body.addEventListener("storage", function(event)
-  {
-    gotEvent = true;
-  }, false);
-}
-
-function doStep()
-{
-  switch (currentStep)
-  {
-    case 2:
-      is(gotEvent, false, "Expected no events");
-      break;
-  }
-
-  // Increase by two to distinguish each test step order
-  // in both master doStep and slave doStep functions.
-  ++currentStep;
-  ++currentStep;
-
-  return true;
-}
-
-</script>
-
-</head>
-
-<body onload="bind(); postMsg('frame loaded');">
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/storageevent/test_storageGlobalStorageEventCheckNoPropagation.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>storage event propagation test</title>
-
-<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="interOriginTest2.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-<!--
-  This test loads two frames from different
-  origins and checks that entries of localStorage
-  objects don't leak each between other.
-
-  The subsystem is based on postMessage and addEventListener
-  to send messages among different origins. The subsystem waits
-  for both frames be loaded and then alternately calls each frames'
-  doStep() function that on each call proceeds with a single step
-  of the test on its side. This way the subsystem alternate between
-  both frames until both sequences completely finish.
--->
-
-<script type="text/javascript">
-
-function startTest()
-{
-  masterFrameOrigin = "http://example.com:80";
-  slaveFrameOrigin = "http://example.org:80";
-
-  masterFrame.location = masterFrameOrigin + framePath + "frameGlobalStorageMaster.html";
-  slaveFrame.location = slaveFrameOrigin + framePath + "frameGlobalStorageSlaveNotEqual.html";
-}
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-
-</head>
-
-<body onload="startTest();">
-  <iframe src="" name="masterFrame"></iframe>
-  <iframe src="" name="slaveFrame"></iframe>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/storageevent/test_storageGlobalStorageEventCheckPropagation.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>storage event propagation test</title>
-
-<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="interOriginTest2.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-<!--
-  This test loads two frames from different
-  origins and checks that entries of localStorage
-  objects don't leak each between other.
-
-  The subsystem is based on postMessage and addEventListener
-  to send messages among different origins. The subsystem waits
-  for both frames be loaded and then alternately calls each frames'
-  doStep() function that on each call proceeds with a single step
-  of the test on its side. This way the subsystem alternate between
-  both frames until both sequences completely finish.
--->
-
-<script type="text/javascript">
-
-function startTest()
-{
-  masterFrameOrigin = "http://example.com:80";
-  slaveFrameOrigin = "http://example.com:80";
-
-  masterFrame.location = masterFrameOrigin + framePath + "frameGlobalStorageMaster.html";
-  slaveFrame.location = slaveFrameOrigin + framePath + "frameGlobalStorageSlaveEqual.html";
-}
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-
-</head>
-
-<body onload="startTest();">
-  <iframe src="" name="masterFrame"></iframe>
-  <iframe src="" name="slaveFrame"></iframe>
-</body>
-</html>
--- a/editor/composer/src/nsComposeTxtSrvFilter.cpp
+++ b/editor/composer/src/nsComposeTxtSrvFilter.cpp
@@ -41,17 +41,16 @@
 #include "nsString.h"
 #include "nsINameSpaceManager.h"
 
 nsComposeTxtSrvFilter::nsComposeTxtSrvFilter() :
   mIsForMail(false)
 {
 
   mBlockQuoteAtom  = do_GetAtom("blockquote");
-  mPreAtom         = do_GetAtom("pre");
   mSpanAtom        = do_GetAtom("span");
   mTableAtom       = do_GetAtom("table");
   mMozQuoteAtom    = do_GetAtom("_moz_quote");
   mClassAtom       = do_GetAtom("class");
   mTypeAtom        = do_GetAtom("type");
   mScriptAtom      = do_GetAtom("script");
   mTextAreaAtom    = do_GetAtom("textarea");
   mSelectAreaAtom  = do_GetAtom("select");
@@ -74,17 +73,17 @@ nsComposeTxtSrvFilter::Skip(nsIDOMNode* 
   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
   if (content) {
     nsIAtom *tag = content->Tag();
     if (tag == mBlockQuoteAtom) {
       if (mIsForMail) {
         *_retval = content->AttrValueIs(kNameSpaceID_None, mTypeAtom,
                                         mCiteAtom, eIgnoreCase);
       }
-    } else if (tag == mPreAtom || tag == mSpanAtom) {
+    } else if (tag == mSpanAtom) {
       if (mIsForMail) {
         *_retval = content->AttrValueIs(kNameSpaceID_None, mMozQuoteAtom,
                                         mTrueAtom, eIgnoreCase);
         if (!*_retval) {
           *_retval = content->AttrValueIs(kNameSpaceID_None, mClassAtom,
                                           mMozSignatureAtom, eCaseMatters);
         }
       }         
--- a/editor/composer/src/nsComposeTxtSrvFilter.h
+++ b/editor/composer/src/nsComposeTxtSrvFilter.h
@@ -61,18 +61,17 @@ public:
   NS_DECL_NSITEXTSERVICESFILTER
 
   // Helper - Intializer
   void Init(bool aIsForMail) { mIsForMail = aIsForMail; }
 
 protected:
   bool              mIsForMail;
   nsCOMPtr<nsIAtom> mBlockQuoteAtom;
-  nsCOMPtr<nsIAtom> mPreAtom;          // mail plain text quotes are wrapped in pre tags
-  nsCOMPtr<nsIAtom> mSpanAtom;         //or they may be wrapped in span tags (editor.quotesPreformatted). 
+  nsCOMPtr<nsIAtom> mSpanAtom;         // mail plain text quotes are wrapped in span tags
   nsCOMPtr<nsIAtom> mMozQuoteAtom;     // _moz_quote_
   nsCOMPtr<nsIAtom> mTableAtom;
   nsCOMPtr<nsIAtom> mClassAtom;
   nsCOMPtr<nsIAtom> mTypeAtom;
   nsCOMPtr<nsIAtom> mScriptAtom;
   nsCOMPtr<nsIAtom> mTextAreaAtom;
   nsCOMPtr<nsIAtom> mSelectAreaAtom;
   nsCOMPtr<nsIAtom> mMapAtom;
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -1963,104 +1963,73 @@ NS_IMETHODIMP nsHTMLEditor::InsertAsQuot
 NS_IMETHODIMP
 nsHTMLEditor::InsertAsPlaintextQuotation(const nsAString & aQuotedText,
                                          bool aAddCites,
                                          nsIDOMNode **aNodeInserted)
 {
   if (mWrapToWindow)
     return nsPlaintextEditor::InsertAsQuotation(aQuotedText, aNodeInserted);
 
-  nsresult rv;
-
-  // The quotesPreformatted pref is a temporary measure. See bug 69638.
-  // Eventually we'll pick one way or the other.
-  bool quotesInPre = false;
-  nsCOMPtr<nsIPrefBranch> prefBranch =
-    do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-  if (NS_SUCCEEDED(rv) && prefBranch)
-    prefBranch->GetBoolPref("editor.quotesPreformatted", &quotesInPre);
-
   nsCOMPtr<nsIDOMNode> preNode;
   // get selection
   nsCOMPtr<nsISelection> selection;
-  rv = GetSelection(getter_AddRefs(selection));
+  nsresult rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
-  if (!selection)
-  {
-    NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-  }
-  else
-  {
-    nsAutoEditBatch beginBatching(this);
-    nsAutoRules beginRulesSniffing(this, kOpInsertQuotation, nsIEditor::eNext);
+  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
+
+  nsAutoEditBatch beginBatching(this);
+  nsAutoRules beginRulesSniffing(this, kOpInsertQuotation, nsIEditor::eNext);
 
-    // give rules a chance to handle or cancel
-    nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertElement);
-    bool cancel, handled;
-    rv = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (cancel) return NS_OK; // rules canceled the operation
-    if (!handled)
+  // give rules a chance to handle or cancel
+  nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertElement);
+  bool cancel, handled;
+  rv = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (cancel) return NS_OK; // rules canceled the operation
+  if (!handled)
+  {
+    // Wrap the inserted quote in a <span> so it won't be wrapped:
+    rv = DeleteSelectionAndCreateNode(NS_LITERAL_STRING("span"), getter_AddRefs(preNode));
+
+    // If this succeeded, then set selection inside the pre
+    // so the inserted text will end up there.
+    // If it failed, we don't care what the return value was,
+    // but we'll fall through and try to insert the text anyway.
+    if (NS_SUCCEEDED(rv) && preNode)
     {
-      // Wrap the inserted quote in a <pre> so it won't be wrapped:
-      nsAutoString tag;
-      if (quotesInPre)
-        tag.AssignLiteral("pre");
-      else
-        tag.AssignLiteral("span");
-
-      rv = DeleteSelectionAndCreateNode(tag, getter_AddRefs(preNode));
-      
-      // If this succeeded, then set selection inside the pre
-      // so the inserted text will end up there.
-      // If it failed, we don't care what the return value was,
-      // but we'll fall through and try to insert the text anyway.
-      if (NS_SUCCEEDED(rv) && preNode)
+      // Add an attribute on the pre node so we'll know it's a quotation.
+      // Do this after the insertion, so that
+      nsCOMPtr<nsIDOMElement> preElement(do_QueryInterface(preNode));
+      if (preElement)
       {
-        // Add an attribute on the pre node so we'll know it's a quotation.
-        // Do this after the insertion, so that 
-        nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
-        if (preElement)
-        {
-          preElement->SetAttribute(NS_LITERAL_STRING("_moz_quote"),
-                                   NS_LITERAL_STRING("true"));
-          if (quotesInPre)
-          {
-            // set style to not have unwanted vertical margins
-            preElement->SetAttribute(NS_LITERAL_STRING("style"),
-                                     NS_LITERAL_STRING("margin: 0 0 0 0px;"));
-          }
-          else
-          {
-            // turn off wrapping on spans
-            preElement->SetAttribute(NS_LITERAL_STRING("style"),
-                                     NS_LITERAL_STRING("white-space: pre;"));
-          }
-        }
+        preElement->SetAttribute(NS_LITERAL_STRING("_moz_quote"),
+                                 NS_LITERAL_STRING("true"));
+        // turn off wrapping on spans
+        preElement->SetAttribute(NS_LITERAL_STRING("style"),
+                                 NS_LITERAL_STRING("white-space: pre;"));
+      }
+      // and set the selection inside it:
+      selection->Collapse(preNode, 0);
+    }
 
-        // and set the selection inside it:
-        selection->Collapse(preNode, 0);
-      }
+    if (aAddCites)
+      rv = nsPlaintextEditor::InsertAsQuotation(aQuotedText, aNodeInserted);
+    else
+      rv = nsPlaintextEditor::InsertText(aQuotedText);
+    // Note that if !aAddCites, aNodeInserted isn't set.
+    // That's okay because the routines that use aAddCites
+    // don't need to know the inserted node.
 
-      if (aAddCites)
-        rv = nsPlaintextEditor::InsertAsQuotation(aQuotedText, aNodeInserted);
-      else
-        rv = nsPlaintextEditor::InsertText(aQuotedText);
-      // Note that if !aAddCites, aNodeInserted isn't set.
-      // That's okay because the routines that use aAddCites
-      // don't need to know the inserted node.
-
-      if (aNodeInserted && NS_SUCCEEDED(rv))
-      {
-        *aNodeInserted = preNode;
-        NS_IF_ADDREF(*aNodeInserted);
-      }
+    if (aNodeInserted && NS_SUCCEEDED(rv))
+    {
+      *aNodeInserted = preNode;
+      NS_IF_ADDREF(*aNodeInserted);
     }
   }
-    
+
   // Set the selection to just after the inserted node:
   if (NS_SUCCEEDED(rv) && preNode)
   {
     nsCOMPtr<nsIDOMNode> parent;
     PRInt32 offset;
     if (NS_SUCCEEDED(GetNodeLocation(preNode, address_of(parent), &offset)) && parent)
       selection->Collapse(parent, offset+1);
   }
--- a/editor/txmgr/src/nsTransactionItem.cpp
+++ b/editor/txmgr/src/nsTransactionItem.cpp
@@ -101,18 +101,17 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsT
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransactionItem, Release)
 
 nsresult
 nsTransactionItem::AddChild(nsTransactionItem *aTransactionItem)
 {
   NS_ENSURE_TRUE(aTransactionItem, NS_ERROR_NULL_POINTER);
 
   if (!mUndoStack) {
-    mUndoStack = new nsTransactionStack();
-    NS_ENSURE_TRUE(mUndoStack, NS_ERROR_OUT_OF_MEMORY);
+    mUndoStack = new nsTransactionStack(nsTransactionStack::FOR_UNDO);
   }
 
   mUndoStack->Push(aTransactionItem);
 
   return NS_OK;
 }
 
 nsresult
@@ -182,30 +181,34 @@ nsTransactionItem::GetChild(PRInt32 aInd
 
   result = GetNumberOfUndoItems(&numItems);
 
   NS_ENSURE_SUCCESS(result, result);
 
   if (numItems > 0 && aIndex < numItems) {
     NS_ENSURE_TRUE(mUndoStack, NS_ERROR_FAILURE);
 
-    return mUndoStack->GetItem(aIndex, aChild);
+    nsRefPtr<nsTransactionItem> child = mUndoStack->GetItem(aIndex);
+    child.forget(aChild);
+    return *aChild ? NS_OK : NS_ERROR_FAILURE;
   }
 
   // Adjust the index for the redo stack:
 
   aIndex -=  numItems;
 
   result = GetNumberOfRedoItems(&numItems);
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(mRedoStack && numItems != 0 && aIndex < numItems, NS_ERROR_FAILURE);
 
-  return mRedoStack->GetItem(numItems - aIndex - 1, aChild);
+  nsRefPtr<nsTransactionItem> child = mRedoStack->GetItem(aIndex);
+  child.forget(aChild);
+  return *aChild ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsTransactionItem::DoTransaction()
 {
   if (mTransaction)
     return mTransaction->DoTransaction();
   return NS_OK;
@@ -238,30 +241,27 @@ nsresult
 nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr)
 {
   nsRefPtr<nsTransactionItem> item;
   nsresult result = NS_OK;
   PRInt32 sz = 0;
 
   if (mUndoStack) {
     if (!mRedoStack && mUndoStack) {
-      mRedoStack = new nsTransactionRedoStack();
-      NS_ENSURE_TRUE(mRedoStack, NS_ERROR_OUT_OF_MEMORY);
+      mRedoStack = new nsTransactionStack(nsTransactionStack::FOR_REDO);
     }
 
     /* Undo all of the transaction items children! */
-    result = mUndoStack->GetSize(&sz);
-
-    NS_ENSURE_SUCCESS(result, result);
+    sz = mUndoStack->GetSize();
 
     while (sz-- > 0) {
-      result = mUndoStack->Peek(getter_AddRefs(item));
+      item = mUndoStack->Peek();
 
-      if (NS_FAILED(result) || !item) {
-        return result;
+      if (!item) {
+        return NS_ERROR_FAILURE;
       }
 
       nsCOMPtr<nsITransaction> t;
 
       result = item->GetTransaction(getter_AddRefs(t));
 
       if (NS_FAILED(result)) {
         return result;
@@ -277,25 +277,18 @@ nsTransactionItem::UndoChildren(nsTransa
 
       if (doInterrupt) {
         return NS_OK;
       }
 
       result = item->UndoTransaction(aTxMgr);
 
       if (NS_SUCCEEDED(result)) {
-        result = mUndoStack->Pop(getter_AddRefs(item));
-
-        if (NS_SUCCEEDED(result)) {
-          result = mRedoStack->Push(item);
-
-          /* XXX: If we got an error here, I doubt we can recover!
-           * XXX: Should we just push the item back on the undo stack?
-           */
-        }
+        item = mUndoStack->Pop();
+        mRedoStack->Push(item);
       }
 
       nsresult result2 = aTxMgr->DidUndoNotify(t, result);
 
       if (NS_SUCCEEDED(result)) {
         result = result2;
       }
     }
@@ -326,32 +319,28 @@ nsTransactionItem::RedoTransaction(nsTra
   return NS_OK;
 }
 
 nsresult
 nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr)
 {
   nsRefPtr<nsTransactionItem> item;
   nsresult result = NS_OK;
-  PRInt32 sz = 0;
 
   if (!mRedoStack)
     return NS_OK;
 
   /* Redo all of the transaction items children! */
-  result = mRedoStack->GetSize(&sz);
-
-  NS_ENSURE_SUCCESS(result, result);
-
+  PRInt32 sz = mRedoStack->GetSize();
 
   while (sz-- > 0) {
-    result = mRedoStack->Peek(getter_AddRefs(item));
+    item = mRedoStack->Peek();
 
-    if (NS_FAILED(result) || !item) {
-      return result;
+    if (!item) {
+      return NS_ERROR_FAILURE;
     }
 
     nsCOMPtr<nsITransaction> t;
 
     result = item->GetTransaction(getter_AddRefs(t));
 
     if (NS_FAILED(result)) {
       return result;
@@ -367,24 +356,18 @@ nsTransactionItem::RedoChildren(nsTransa
 
     if (doInterrupt) {
       return NS_OK;
     }
 
     result = item->RedoTransaction(aTxMgr);
 
     if (NS_SUCCEEDED(result)) {
-      result = mRedoStack->Pop(getter_AddRefs(item));
-
-      if (NS_SUCCEEDED(result)) {
-        result = mUndoStack->Push(item);
-
-        // XXX: If we got an error here, I doubt we can recover!
-        // XXX: Should we just push the item back on the redo stack?
-      }
+      item = mRedoStack->Pop();
+      mUndoStack->Push(item);
     }
 
     nsresult result2 = aTxMgr->DidUndoNotify(t, result);
 
     if (NS_SUCCEEDED(result)) {
       result = result2;
     }
   }
@@ -397,30 +380,32 @@ nsTransactionItem::GetNumberOfUndoItems(
 {
   NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
 
   if (!mUndoStack) {
     *aNumItems = 0;
     return NS_OK;
   }
 
-  return mUndoStack->GetSize(aNumItems);
+  *aNumItems = mUndoStack->GetSize();
+  return *aNumItems ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsTransactionItem::GetNumberOfRedoItems(PRInt32 *aNumItems)
 {
   NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
 
   if (!mRedoStack) {
     *aNumItems = 0;
     return NS_OK;
   }
 
-  return mRedoStack->GetSize(aNumItems);
+  *aNumItems = mRedoStack->GetSize();
+  return *aNumItems ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsTransactionItem::RecoverFromUndoError(nsTransactionManager *aTxMgr)
 {
   //
   // If this method gets called, we never got to the point where we
   // successfully called UndoTransaction() for the transaction item itself.
--- a/editor/txmgr/src/nsTransactionItem.h
+++ b/editor/txmgr/src/nsTransactionItem.h
@@ -38,24 +38,23 @@
 #ifndef nsTransactionItem_h__
 #define nsTransactionItem_h__
 
 #include "nsITransaction.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsTransactionStack;
-class nsTransactionRedoStack;
 class nsTransactionManager;
 
 class nsTransactionItem
 {
   nsCOMPtr<nsITransaction> mTransaction;
   nsTransactionStack      *mUndoStack;
-  nsTransactionRedoStack  *mRedoStack;
+  nsTransactionStack      *mRedoStack;
   nsAutoRefCnt             mRefCnt;
 
 public:
 
   nsTransactionItem(nsITransaction *aTransaction);
   virtual ~nsTransactionItem();
   nsrefcnt AddRef();
   nsrefcnt Release();
--- a/editor/txmgr/src/nsTransactionList.cpp
+++ b/editor/txmgr/src/nsTransactionList.cpp
@@ -70,20 +70,20 @@ NS_IMETHODIMP nsTransactionList::GetNumI
   NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
 
   *aNumItems = 0;
 
   nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
 
   NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
 
-  nsresult result = NS_ERROR_FAILURE;
+  nsresult result = NS_OK;
 
   if (mTxnStack)
-    result = mTxnStack->GetSize(aNumItems);
+    *aNumItems = mTxnStack->GetSize();
   else if (mTxnItem)
     result = mTxnItem->GetNumberOfChildren(aNumItems);
 
   return result;
 }
 
 /* boolean itemIsBatch (in long aIndex); */
 NS_IMETHODIMP nsTransactionList::ItemIsBatch(PRInt32 aIndex, bool *aIsBatch)
@@ -93,20 +93,20 @@ NS_IMETHODIMP nsTransactionList::ItemIsB
   *aIsBatch = false;
 
   nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
 
   NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
 
   nsRefPtr<nsTransactionItem> item;
 
-  nsresult result = NS_ERROR_FAILURE;
+  nsresult result = NS_OK;
 
   if (mTxnStack)
-    result = mTxnStack->GetItem(aIndex, getter_AddRefs(item));
+    item = mTxnStack->GetItem(aIndex);
   else if (mTxnItem)
     result = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
 
   return item->GetIsBatch(aIsBatch);
@@ -120,20 +120,20 @@ NS_IMETHODIMP nsTransactionList::GetItem
   *aItem = 0;
 
   nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
 
   NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
 
   nsRefPtr<nsTransactionItem> item;
 
-  nsresult result = NS_ERROR_FAILURE;
+  nsresult result = NS_OK;
 
   if (mTxnStack)
-    result = mTxnStack->GetItem(aIndex, getter_AddRefs(item));
+    item = mTxnStack->GetItem(aIndex);
   else if (mTxnItem)
     result = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
 
   return item->GetTransaction(aItem);
@@ -147,20 +147,20 @@ NS_IMETHODIMP nsTransactionList::GetNumC
   *aNumChildren = 0;
 
   nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
 
   NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
 
   nsRefPtr<nsTransactionItem> item;
 
-  nsresult result = NS_ERROR_FAILURE;
+  nsresult result = NS_OK;
 
   if (mTxnStack)
-    result = mTxnStack->GetItem(aIndex, getter_AddRefs(item));
+    item = mTxnStack->GetItem(aIndex);
   else if (mTxnItem)
     result = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
 
   return item->GetNumberOfChildren(aNumChildren);
@@ -174,20 +174,20 @@ NS_IMETHODIMP nsTransactionList::GetChil
   *aTxnList = 0;
 
   nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
 
   NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
 
   nsRefPtr<nsTransactionItem> item;
 
-  nsresult result = NS_ERROR_FAILURE;
+  nsresult result = NS_OK;
 
   if (mTxnStack)
-    result = mTxnStack->GetItem(aIndex, getter_AddRefs(item));
+    item = mTxnStack->GetItem(aIndex);
   else if (mTxnItem)
     result = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
 
   *aTxnList = (nsITransactionList *)new nsTransactionList(txMgr, item);
--- a/editor/txmgr/src/nsTransactionManager.cpp
+++ b/editor/txmgr/src/nsTransactionManager.cpp
@@ -43,16 +43,19 @@
 #include "nsVoidArray.h"
 #include "nsTransactionManager.h"
 #include "nsTransactionList.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 
 nsTransactionManager::nsTransactionManager(PRInt32 aMaxTransactionCount)
   : mMaxTransactionCount(aMaxTransactionCount)
+  , mDoStack(nsTransactionStack::FOR_UNDO)
+  , mUndoStack(nsTransactionStack::FOR_UNDO)
+  , mRedoStack(nsTransactionStack::FOR_REDO)
 {
 }
 
 nsTransactionManager::~nsTransactionManager()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionManager)
@@ -115,39 +118,30 @@ nsTransactionManager::DoTransaction(nsIT
 
   return result;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::UndoTransaction()
 {
   nsresult result       = NS_OK;
-  nsRefPtr<nsTransactionItem> tx;
 
   // It is illegal to call UndoTransaction() while the transaction manager is
   // executing a  transaction's DoTransaction() method! If this happens,
   // the UndoTransaction() request is ignored, and we return NS_ERROR_FAILURE.
 
-  result = mDoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  nsRefPtr<nsTransactionItem> tx = mDoStack.Peek();
 
   if (tx) {
     return NS_ERROR_FAILURE;
   }
 
   // Peek at the top of the undo stack. Don't remove the transaction
   // until it has successfully completed.
-  result = mUndoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  tx = mUndoStack.Peek();
 
   // Bail if there's nothing on the stack.
   if (!tx) {
     return NS_OK;
   }
 
   nsCOMPtr<nsITransaction> t;
 
@@ -167,57 +161,46 @@ nsTransactionManager::UndoTransaction()
 
   if (doInterrupt) {
     return NS_OK;
   }
 
   result = tx->UndoTransaction(this);
 
   if (NS_SUCCEEDED(result)) {
-    result = mUndoStack.Pop(getter_AddRefs(tx));
-
-    if (NS_SUCCEEDED(result))
-      result = mRedoStack.Push(tx);
+    tx = mUndoStack.Pop();
+    mRedoStack.Push(tx);
   }
 
   nsresult result2 = DidUndoNotify(t, result);
 
   if (NS_SUCCEEDED(result))
     result = result2;
 
   return result;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::RedoTransaction()
 {
   nsresult result       = NS_OK;
-  nsRefPtr<nsTransactionItem> tx;
 
   // It is illegal to call RedoTransaction() while the transaction manager is
   // executing a  transaction's DoTransaction() method! If this happens,
   // the RedoTransaction() request is ignored, and we return NS_ERROR_FAILURE.
 
-  result = mDoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  nsRefPtr<nsTransactionItem> tx = mDoStack.Peek();
 
   if (tx) {
     return NS_ERROR_FAILURE;
   }
 
   // Peek at the top of the redo stack. Don't remove the transaction
   // until it has successfully completed.
-  result = mRedoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  tx = mRedoStack.Peek();
 
   // Bail if there's nothing on the stack.
   if (!tx) {
     return NS_OK;
   }
 
   nsCOMPtr<nsITransaction> t;
 
@@ -237,20 +220,18 @@ nsTransactionManager::RedoTransaction()
 
   if (doInterrupt) {
     return NS_OK;
   }
 
   result = tx->RedoTransaction(this);
 
   if (NS_SUCCEEDED(result)) {
-    result = mRedoStack.Pop(getter_AddRefs(tx));
-
-    if (NS_SUCCEEDED(result))
-      result = mUndoStack.Push(tx);
+    tx = mRedoStack.Pop();
+    mUndoStack.Push(tx);
   }
 
   nsresult result2 = DidRedoNotify(t, result);
 
   if (NS_SUCCEEDED(result))
     result = result2;
 
   return result;
@@ -302,36 +283,31 @@ nsTransactionManager::BeginBatch()
     result = result2;
 
   return result;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::EndBatch()
 {
-  nsRefPtr<nsTransactionItem> tx;
   nsCOMPtr<nsITransaction> ti;
   nsresult result;
 
   // XXX: Need to add some mechanism to detect the case where the transaction
   //      at the top of the do stack isn't the dummy transaction, so we can
   //      throw an error!! This can happen if someone calls EndBatch() within
   //      the DoTransaction() method of a transaction.
   //
   //      For now, we can detect this case by checking the value of the
   //      dummy transaction's mTransaction field. If it is our dummy
   //      transaction, it should be NULL. This may not be true in the
   //      future when we allow users to execute a transaction when beginning
   //      a batch!!!!
 
-  result = mDoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  nsRefPtr<nsTransactionItem> tx = mDoStack.Peek();
 
   if (tx)
     tx->GetTransaction(getter_AddRefs(ti));
 
   if (!tx || ti) {
     return NS_ERROR_FAILURE;
   }
 
@@ -355,155 +331,141 @@ nsTransactionManager::EndBatch()
     result = result2;
 
   return result;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::GetNumberOfUndoItems(PRInt32 *aNumItems)
 {
-  return mUndoStack.GetSize(aNumItems);
+  *aNumItems = mUndoStack.GetSize();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::GetNumberOfRedoItems(PRInt32 *aNumItems)
 {
-  return mRedoStack.GetSize(aNumItems);
+  *aNumItems = mRedoStack.GetSize();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::GetMaxTransactionCount(PRInt32 *aMaxCount)
 {
   NS_ENSURE_TRUE(aMaxCount, NS_ERROR_NULL_POINTER);
 
   *aMaxCount = mMaxTransactionCount;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::SetMaxTransactionCount(PRInt32 aMaxCount)
 {
   PRInt32 numUndoItems  = 0, numRedoItems = 0, total = 0;
-  nsRefPtr<nsTransactionItem> tx;
-  nsresult result;
 
   // It is illegal to call SetMaxTransactionCount() while the transaction
   // manager is executing a  transaction's DoTransaction() method because
   // the undo and redo stacks might get pruned! If this happens, the
   // SetMaxTransactionCount() request is ignored, and we return
   // NS_ERROR_FAILURE.
 
-  result = mDoStack.Peek(getter_AddRefs(tx));
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  nsRefPtr<nsTransactionItem> tx = mDoStack.Peek();
 
   if (tx) {
     return NS_ERROR_FAILURE;
   }
 
   // If aMaxCount is less than zero, the user wants unlimited
   // levels of undo! No need to prune the undo or redo stacks!
 
   if (aMaxCount < 0) {
     mMaxTransactionCount = -1;
-    return result;
+    return NS_OK;
   }
 
-  result = mUndoStack.GetSize(&numUndoItems);
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  numUndoItems = mUndoStack.GetSize();
 
-  result = mRedoStack.GetSize(&numRedoItems);
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  numRedoItems = mRedoStack.GetSize();
 
   total = numUndoItems + numRedoItems;
 
   // If aMaxCount is greater than the number of transactions that currently
   // exist on the undo and redo stack, there is no need to prune the
   // undo or redo stacks!
 
   if (aMaxCount > total ) {
     mMaxTransactionCount = aMaxCount;
-    return result;
+    return NS_OK;
   }
 
   // Try getting rid of some transactions on the undo stack! Start at
   // the bottom of the stack and pop towards the top.
 
   while (numUndoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) {
-    result = mUndoStack.PopBottom(getter_AddRefs(tx));
+    tx = mUndoStack.PopBottom();
 
-    if (NS_FAILED(result) || !tx) {
-      return result;
+    if (!tx) {
+      return NS_ERROR_FAILURE;
     }
 
     --numUndoItems;
   }
 
   // If necessary, get rid of some transactions on the redo stack! Start at
   // the bottom of the stack and pop towards the top.
 
   while (numRedoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) {
-    result = mRedoStack.PopBottom(getter_AddRefs(tx));
+    tx = mRedoStack.PopBottom();
 
-    if (NS_FAILED(result) || !tx) {
-      return result;
+    if (!tx) {
+      return NS_ERROR_FAILURE;
     }
 
     --numRedoItems;
   }
 
   mMaxTransactionCount = aMaxCount;
 
-  return result;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::PeekUndoStack(nsITransaction **aTransaction)
 {
-  nsRefPtr<nsTransactionItem> tx;
   nsresult result;
 
   NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
 
   *aTransaction = 0;
 
-  result = mUndoStack.Peek(getter_AddRefs(tx));
+  nsRefPtr<nsTransactionItem> tx = mUndoStack.Peek();
 
-  if (NS_FAILED(result) || !tx) {
-    return result;
+  if (!tx) {
+    return NS_OK;
   }
 
   result = tx->GetTransaction(aTransaction);
 
   return result;
 }
 
 NS_IMETHODIMP
 nsTransactionManager::PeekRedoStack(nsITransaction **aTransaction)
 {
-  nsRefPtr<nsTransactionItem> tx;
   nsresult result;
 
   NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
 
   *aTransaction = 0;
 
-  result = mRedoStack.Peek(getter_AddRefs(tx));
+  nsRefPtr<nsTransactionItem> tx = mRedoStack.Peek();
 
-  if (NS_FAILED(result) || !tx) {
-    return result;
+  if (!tx) {
+    return NS_OK;
   }
 
   result = tx->GetTransaction(aTransaction);
 
   return result;
 }
 
 NS_IMETHODIMP
@@ -544,23 +506,25 @@ nsTransactionManager::RemoveListener(nsI
   NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
 
   return mListeners.RemoveObject(aListener) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsTransactionManager::ClearUndoStack()
 {
-  return mUndoStack.Clear();
+  mUndoStack.Clear();
+  return NS_OK;
 }
 
 nsresult
 nsTransactionManager::ClearRedoStack()
 {
-  return mRedoStack.Clear();
+  mRedoStack.Clear();
+  return NS_OK;
 }
 
 nsresult
 nsTransactionManager::WillDoNotify(nsITransaction *aTransaction, bool *aInterrupt)
 {
   nsresult result = NS_OK;
   for (PRInt32 i = 0, lcount = mListeners.Count(); i < lcount; i++)
   {
@@ -797,43 +761,38 @@ nsTransactionManager::BeginTransaction(n
   // XXX: POSSIBLE OPTIMIZATION
   //      We could use a factory that pre-allocates/recycles transaction items.
   nsRefPtr<nsTransactionItem> tx = new nsTransactionItem(aTransaction);
 
   if (!tx) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  result = mDoStack.Push(tx);
-
-  if (NS_FAILED(result)) {
-    return result;
-  }
+  mDoStack.Push(tx);
 
   result = tx->DoTransaction();
 
   if (NS_FAILED(result)) {
-    mDoStack.Pop(getter_AddRefs(tx));
+    tx = mDoStack.Pop();
     return result;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsTransactionManager::EndTransaction()
 {
   nsCOMPtr<nsITransaction> tint;
-  nsRefPtr<nsTransactionItem> tx;
   nsresult result              = NS_OK;
 
-  result = mDoStack.Pop(getter_AddRefs(tx));
+  nsRefPtr<nsTransactionItem> tx = mDoStack.Pop();
 
-  if (NS_FAILED(result) || !tx)
-    return result;
+  if (!tx)
+    return NS_ERROR_FAILURE;
 
   result = tx->GetTransaction(getter_AddRefs(tint));
 
   if (NS_FAILED(result)) {
     // XXX: What do we do with the transaction item at this point?
     return result;
   }
 
@@ -859,23 +818,21 @@ nsTransactionManager::EndTransaction()
     result = tint->GetIsTransient(&isTransient);
 
   if (NS_FAILED(result) || isTransient || !mMaxTransactionCount) {
     // XXX: Should we be clearing the redo stack if the transaction
     //      is transient and there is nothing on the do stack?
     return result;
   }
 
-  nsRefPtr<nsTransactionItem> top;
-
   // Check if there is a transaction on the do stack. If there is,
   // the current transaction is a "sub" transaction, and should
   // be added to the transaction at the top of the do stack.
 
-  result = mDoStack.Peek(getter_AddRefs(top));
+  nsRefPtr<nsTransactionItem> top = mDoStack.Peek();
   if (top) {
     result = top->AddChild(tx);
 
     // XXX: What do we do if this fails?
 
     return result;
   }
 
@@ -885,18 +842,17 @@ nsTransactionManager::EndTransaction()
 
   if (NS_FAILED(result)) {
     // XXX: What do we do if this fails?
   }
 
   // Check if we can coalesce this transaction with the one at the top
   // of the undo stack.
 
-  top = 0;
-  result = mUndoStack.Peek(getter_AddRefs(top));
+  top = mUndoStack.Peek();
 
   if (tint && top) {
     bool didMerge = false;
     nsCOMPtr<nsITransaction> topTransaction;
 
     result = top->GetTransaction(getter_AddRefs(topTransaction));
 
     if (topTransaction) {
@@ -924,32 +880,21 @@ nsTransactionManager::EndTransaction()
         }
       }
     }
   }
 
   // Check to see if we've hit the max level of undo. If so,
   // pop the bottom transaction off the undo stack and release it!
 
-  PRInt32 sz = 0;
-
-  result = mUndoStack.GetSize(&sz);
+  PRInt32 sz = mUndoStack.GetSize();
 
   if (mMaxTransactionCount > 0 && sz >= mMaxTransactionCount) {
-    nsRefPtr<nsTransactionItem> overflow;
-
-    result = mUndoStack.PopBottom(getter_AddRefs(overflow));
-
-    // XXX: What do we do in the case where this fails?
+    nsRefPtr<nsTransactionItem> overflow = mUndoStack.PopBottom();
   }
 
   // Push the transaction on the undo stack:
 
-  result = mUndoStack.Push(tx);
+  mUndoStack.Push(tx);
 
-  if (NS_FAILED(result)) {
-    // XXX: What do we do in the case where a clear fails?
-    //      Remove the transaction from the stack, and release it?
-  }
-
-  return result;
+  return NS_OK;
 }
 
--- a/editor/txmgr/src/nsTransactionManager.h
+++ b/editor/txmgr/src/nsTransactionManager.h
@@ -43,30 +43,29 @@
 #include "nsCOMArray.h"
 #include "nsITransactionListener.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsITransaction;
 class nsITransactionListener;
 class nsTransactionItem;
 class nsTransactionStack;
-class nsTransactionRedoStack;
 
 /** implementation of a transaction manager object.
  *
  */
 class nsTransactionManager : public nsITransactionManager
                            , public nsSupportsWeakReference
 {
 private:
 
   PRInt32                mMaxTransactionCount;
   nsTransactionStack     mDoStack;
   nsTransactionStack     mUndoStack;
-  nsTransactionRedoStack mRedoStack;
+  nsTransactionStack     mRedoStack;
   nsCOMArray<nsITransactionListener> mListeners;
 
 public:
 
   /** The default constructor.
    */
   nsTransactionManager(PRInt32 aMaxTransactionCount=-1);
 
--- a/editor/txmgr/src/nsTransactionStack.cpp
+++ b/editor/txmgr/src/nsTransactionStack.cpp
@@ -36,160 +36,98 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsITransaction.h"
 #include "nsTransactionItem.h"
 #include "nsTransactionStack.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Util.h"
 
-nsTransactionStack::nsTransactionStack()
+nsTransactionStack::nsTransactionStack(nsTransactionStack::Type aType)
   : mQue(0)
+  , mType(aType)
 {
-} 
+}
 
 nsTransactionStack::~nsTransactionStack()
 {
   Clear();
 }
 
-nsresult
+void
 nsTransactionStack::Push(nsTransactionItem *aTransaction)
 {
-  NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
+  if (!aTransaction) {
+    return;
+  }
 
   /* nsDeque's Push() method adds new items at the back
    * of the deque.
    */
   NS_ADDREF(aTransaction);
   mQue.Push(aTransaction);
-
-  return NS_OK;
 }
 
-nsresult
-nsTransactionStack::Pop(nsTransactionItem **aTransaction)
+already_AddRefed<nsTransactionItem>
+nsTransactionStack::Pop()
 {
-  NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
-
   /* nsDeque is a FIFO, so the top of our stack is actually
    * the back of the deque.
    */
-  *aTransaction = (nsTransactionItem *)mQue.Pop();
-
-  return NS_OK;
+  return static_cast<nsTransactionItem*> (mQue.Pop());
 }
 
-nsresult
-nsTransactionStack::PopBottom(nsTransactionItem **aTransaction)
+already_AddRefed<nsTransactionItem>
+nsTransactionStack::PopBottom()
 {
-  NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
-
   /* nsDeque is a FIFO, so the bottom of our stack is actually
    * the front of the deque.
    */
-  *aTransaction = (nsTransactionItem *)mQue.PopFront();
-
-  return NS_OK;
+  return static_cast<nsTransactionItem*> (mQue.PopFront());
 }
 
-nsresult
-nsTransactionStack::Peek(nsTransactionItem **aTransaction)
+already_AddRefed<nsTransactionItem>
+nsTransactionStack::Peek()
 {
-  NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
-
-  if (!mQue.GetSize()) {
-    *aTransaction = 0;
-    return NS_OK;
+  nsTransactionItem* transaction = nsnull;
+  if (mQue.GetSize()) {
+    NS_IF_ADDREF(transaction = static_cast<nsTransactionItem*>(mQue.Last()));
   }
 
-  NS_IF_ADDREF(*aTransaction = static_cast<nsTransactionItem*>(mQue.Last()));
-
-  return NS_OK;
+  return transaction;
 }
 
-nsresult
-nsTransactionStack::GetItem(PRInt32 aIndex, nsTransactionItem **aTransaction)
+already_AddRefed<nsTransactionItem>
+nsTransactionStack::GetItem(PRInt32 aIndex)
 {
-  NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
+  nsTransactionItem* transaction = nsnull;
+  if (aIndex >= 0 && aIndex < mQue.GetSize()) {
+    NS_IF_ADDREF(transaction =
+                 static_cast<nsTransactionItem*>(mQue.ObjectAt(aIndex)));
+  }
 
-  if (aIndex < 0 || aIndex >= mQue.GetSize())
-    return NS_ERROR_FAILURE;
-
-  NS_IF_ADDREF(*aTransaction =
-               static_cast<nsTransactionItem*>(mQue.ObjectAt(aIndex)));
-
-  return NS_OK;
+  return transaction;
 }
 
-nsresult
-nsTransactionStack::Clear(void)
+void
+nsTransactionStack::Clear()
 {
   nsRefPtr<nsTransactionItem> tx;
-  nsresult result    = NS_OK;
 
-  /* Pop all transactions off the stack and release them. */
-
-  result = Pop(getter_AddRefs(tx));
-
-  NS_ENSURE_SUCCESS(result, result);
-
-  while (tx) {
-    result = Pop(getter_AddRefs(tx));
-
-    NS_ENSURE_SUCCESS(result, result);
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsTransactionStack::GetSize(PRInt32 *aStackSize)
-{
-  NS_ENSURE_TRUE(aStackSize, NS_ERROR_NULL_POINTER);
-
-  *aStackSize = mQue.GetSize();
-
-  return NS_OK;
+  do {
+    tx = mType == FOR_UNDO ? Pop() : PopBottom();
+  } while (tx);
 }
 
 void
 nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb)
 {
   for (PRInt32 i = 0, qcount = mQue.GetSize(); i < qcount; ++i) {
     nsTransactionItem *item =
       static_cast<nsTransactionItem*>(mQue.ObjectAt(i));
     if (item) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mQue[i]");
       cb.NoteNativeChild(item, &NS_CYCLE_COLLECTION_NAME(nsTransactionItem));
     }
   }
 }
-
-nsTransactionRedoStack::~nsTransactionRedoStack()
-{
-  Clear();
-}
-
-nsresult
-nsTransactionRedoStack::Clear(void)
-{
-  nsRefPtr<nsTransactionItem> tx;
-  nsresult result       = NS_OK;
-
-  /* When clearing a Redo stack, we have to clear from the
-   * bottom of the stack towards the top!
-   */
-
-  result = PopBottom(getter_AddRefs(tx));
-
-  NS_ENSURE_SUCCESS(result, result);
-
-  while (tx) {
-    result = PopBottom(getter_AddRefs(tx));
-
-    NS_ENSURE_SUCCESS(result, result);
-  }
-
-  return NS_OK;
-}
-
--- a/editor/txmgr/src/nsTransactionStack.h
+++ b/editor/txmgr/src/nsTransactionStack.h
@@ -34,41 +34,37 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTransactionStack_h__
 #define nsTransactionStack_h__
 
 #include "nsDeque.h"
+#include "nsCOMPtr.h"
 
 class nsTransactionItem;
 
 class nsTransactionStack
 {
-  nsDeque mQue;
+public:
+  enum Type { FOR_UNDO, FOR_REDO };
 
-public:
-
-  nsTransactionStack();
-  virtual ~nsTransactionStack();
+  explicit nsTransactionStack(Type aType);
+  ~nsTransactionStack();
 
-  virtual nsresult Push(nsTransactionItem *aTransactionItem);
-  virtual nsresult Pop(nsTransactionItem **aTransactionItem);
-  virtual nsresult PopBottom(nsTransactionItem **aTransactionItem);
-  virtual nsresult Peek(nsTransactionItem **aTransactionItem);
-  virtual nsresult GetItem(PRInt32 aIndex, nsTransactionItem **aTransactionItem);
-  virtual nsresult Clear(void);
-  virtual nsresult GetSize(PRInt32 *aStackSize);
+  void Push(nsTransactionItem *aTransactionItem);
+  already_AddRefed<nsTransactionItem> Pop();
+  already_AddRefed<nsTransactionItem> PopBottom();
+  already_AddRefed<nsTransactionItem> Peek();
+  already_AddRefed<nsTransactionItem> GetItem(PRInt32 aIndex);
+  void Clear();
+  PRInt32 GetSize() { return mQue.GetSize(); }
 
   void DoUnlink() { Clear(); }
   void DoTraverse(nsCycleCollectionTraversalCallback &cb);
-};
 
-class nsTransactionRedoStack: public nsTransactionStack
-{
-public:
-
-  virtual ~nsTransactionRedoStack();
-  virtual nsresult Clear(void);
+private:
+  nsDeque mQue;
+  const Type mType;
 };
 
 #endif // nsTransactionStack_h__
--- a/gfx/2d/UserData.h
+++ b/gfx/2d/UserData.h
@@ -30,16 +30,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 ***** */
 
+#ifndef MOZILLA_GFX_USERDATA_H_
+#define MOZILLA_GFX_USERDATA_H_
 
 #include <stdlib.h>
 #include "mozilla/mozalloc.h"
 
 namespace mozilla {
 namespace gfx {
 
 struct UserDataKey {
@@ -51,30 +53,48 @@ class UserData
 {
   typedef void (*destroyFunc)(void *data);
 public:
   UserData() : count(0), entries(NULL) {}
 
   /* Attaches untyped userData associated with key. destroy is called on destruction */
   void Add(UserDataKey *key, void *userData, destroyFunc destroy)
   {
+    // XXX we should really warn if user data with key has already been added,
+    // since in that case Get() will return the old user data!
+
     // We could keep entries in a std::vector instead of managing it by hand
     // but that would propagate an stl dependency out which we'd rather not
     // do (see bug 666609). Plus, the entries array is expect to stay small
     // so doing a realloc everytime we add a new entry shouldn't be too costly
     entries = static_cast<Entry*>(moz_xrealloc(entries, sizeof(Entry)*(count+1)));
 
     entries[count].key      = key;
     entries[count].userData = userData;
     entries[count].destroy  = destroy;
 
     count++;
   }
 
-  //XXX: we probably want to add a way to remove Keys
+  /* Remove and return user data associated with key, without destroying it */
+  void* Remove(UserDataKey *key)
+  {
+    for (int i=0; i<count; i++) {
+      if (key == entries[i].key) {
+        void *userData = entries[i].userData;
+        // decrement before looping so entries[i+1] doesn't read past the end:
+        --count;
+        for (;i<count; i++) {
+          entries[i] = entries[i+1];
+        }
+        return userData;
+      }
+    }
+    return NULL;
+  }
 
   /* Retrives the userData for the associated key */
   void *Get(UserDataKey *key)
   {
     for (int i=0; i<count; i++) {
       if (key == entries[i].key) {
         return entries[i].userData;
       }
@@ -100,9 +120,9 @@ private:
   int count;
   Entry *entries;
 
 };
 
 }
 }
 
-
+#endif /* MOZILLA_GFX_USERDATA_H_ */
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -79,16 +79,17 @@ CPPSRCS = \
         SymbolTable.cpp \
         VariableInfo.cpp \
         compilerdebug.cpp \
         ossource_nspr.cpp \
         util.cpp \
         ValidateLimitations.cpp \
         ForLoopUnroll.cpp \
         MapLongVariableNames.cpp \
+        spooky.cpp \
         BuiltInFunctionEmulator.cpp \
         $(NULL)
 
 # flex/yacc generated files
 CPPSRCS += \
         glslang_lex.cpp \
         glslang_tab.cpp \
         $(NULL)
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -2,21 +2,21 @@ This is the ANGLE project, from http://c
 
 Current revision: r963
 
 == Applied local patches ==
 
 In this order:
   angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
-  angle-limit-identifiers-to-250-chars.patch - see bug 675625
   angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
   angle-castrate-bug-241.patch - see bug 699033 / angle bug 241
   angle-enforce-readpixels-spec.patch - see bug 724476.
   angle-impl-read-bgra.patch - see bug 724476.
+  gfx/angle/angle-long-identifier-hash-spooky.patch - see bug 676071
 
 In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
 
 == How to update this ANGLE copy ==
 
 1. Unapply patches
 2. Apply diff with new ANGLE version
 3. Reapply patches.
deleted file mode 100644
--- a/gfx/angle/angle-limit-identifiers-to-250-chars.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-# HG changeset patch
-# Parent 761ca19e4ce1afe03e58beaea20149ba1ef243c4
-diff --git a/gfx/angle/src/compiler/preprocessor/length_limits.h b/gfx/angle/src/compiler/preprocessor/length_limits.h
---- a/gfx/angle/src/compiler/preprocessor/length_limits.h
-+++ b/gfx/angle/src/compiler/preprocessor/length_limits.h
-@@ -10,12 +10,14 @@
- 
- #if !defined(__LENGTH_LIMITS_H)
- #define __LENGTH_LIMITS_H 1
- 
- // These constants are factored out from the rest of the headers to
- // make it easier to reference them from the compiler sources.
- 
- // These lengths do not include the NULL terminator.
--#define MAX_SYMBOL_NAME_LEN 256
-+// see bug 675625: NVIDIA driver crash with lengths >= 253
-+// this is only an interim fix, the real fix is name mapping, see ANGLE bug 144 / r619
-+#define MAX_SYMBOL_NAME_LEN 250
- #define MAX_STRING_LEN 511
- 
- #endif // !(defined(__LENGTH_LIMITS_H)
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-long-identifier-hash-spooky.patch
@@ -0,0 +1,756 @@
+# HG changeset patch
+# Parent 69255fe4cb94f1681bc9200db37c0ad3de171abc
+
+diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
+--- a/gfx/angle/Makefile.in
++++ b/gfx/angle/Makefile.in
+@@ -79,16 +79,17 @@ CPPSRCS = \
+         SymbolTable.cpp \
+         VariableInfo.cpp \
+         compilerdebug.cpp \
+         ossource_nspr.cpp \
+         util.cpp \
+         ValidateLimitations.cpp \
+         ForLoopUnroll.cpp \
+         MapLongVariableNames.cpp \
++        spooky.cpp \
+         BuiltInFunctionEmulator.cpp \
+         $(NULL)
+ 
+ # flex/yacc generated files
+ CPPSRCS += \
+         glslang_lex.cpp \
+         glslang_tab.cpp \
+         $(NULL)
+diff --git a/gfx/angle/src/compiler/MapLongVariableNames.cpp b/gfx/angle/src/compiler/MapLongVariableNames.cpp
+--- a/gfx/angle/src/compiler/MapLongVariableNames.cpp
++++ b/gfx/angle/src/compiler/MapLongVariableNames.cpp
+@@ -1,27 +1,30 @@
+ //
+ // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ //
+ 
+ #include "compiler/MapLongVariableNames.h"
++#include "spooky.h"
+ 
+ namespace {
+ 
+ TString mapLongName(int id, const TString& name, bool isGlobal)
+ {
+     ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
+     TStringStream stream;
+-    stream << "webgl_";
+-    if (isGlobal)
+-        stream << "g";
+-    stream << id << "_";
+-    stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
++    uint64 hash = SpookyHash::Hash64(name.data(), name.length(), 0);
++    stream << "webgl_"
++           << name.substr(0, 9)
++           << "_"
++           << std::hex
++           << hash;
++    ASSERT(stream.str().length() == MAX_SHORTENED_IDENTIFIER_SIZE);
+     return stream.str();
+ }
+ 
+ LongNameMap* gLongNameMapInstance = NULL;
+ 
+ }  // anonymous namespace
+ 
+ LongNameMap::LongNameMap()
+diff --git a/gfx/angle/src/compiler/spooky.cpp b/gfx/angle/src/compiler/spooky.cpp
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/src/compiler/spooky.cpp
+@@ -0,0 +1,348 @@
++// Spooky Hash
++// A 128-bit noncryptographic hash, for checksums and table lookup
++// By Bob Jenkins.  Public domain.
++//   Oct 31 2010: published framework, disclaimer ShortHash isn't right
++//   Nov 7 2010: disabled ShortHash
++//   Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
++
++#include <memory.h>
++#include <string.h>
++#include "spooky.h"
++
++#define ALLOW_UNALIGNED_READS 1
++
++//
++// short hash ... it could be used on any message, 
++// but it's used by Spooky just for short messages.
++//
++void SpookyHash::Short(
++    const void *message,
++    size_t length,
++    uint64 *hash1,
++    uint64 *hash2)
++{
++    uint64 buf[sc_numVars];
++    union 
++    { 
++        const uint8 *p8; 
++        uint32 *p32;
++        uint64 *p64; 
++        size_t i; 
++    } u;
++
++    u.p8 = (const uint8 *)message;
++    
++    if (!ALLOW_UNALIGNED_READS && (u.i & 0x7))
++    {
++        memcpy(buf, message, length);
++        u.p64 = buf;
++    }
++
++    size_t remainder = length%32;
++    uint64 a=*hash1;
++    uint64 b=*hash2;
++    uint64 c=sc_const;
++    uint64 d=sc_const;
++
++    if (length > 15)
++    {
++        const uint64 *end = u.p64 + (length/32)*4;
++        
++        // handle all complete sets of 32 bytes
++        for (; u.p64 < end; u.p64 += 4)
++        {
++            c += u.p64[0];
++            d += u.p64[1];
++            ShortMix(a,b,c,d);
++            a += u.p64[2];
++            b += u.p64[3];
++        }
++        
++        //Handle the case of 16+ remaining bytes.
++        if (remainder >= 16)
++        {
++            c += u.p64[0];
++            d += u.p64[1];
++            ShortMix(a,b,c,d);
++            u.p64 += 2;
++            remainder -= 16;
++        }
++    }
++    
++    // Handle the last 0..15 bytes, and its length
++    d = ((uint64)length) << 56;
++    switch (remainder)
++    {
++    case 15:
++    d += ((uint64)u.p8[14]) << 48;
++    case 14:
++        d += ((uint64)u.p8[13]) << 40;
++    case 13:
++        d += ((uint64)u.p8[12]) << 32;
++    case 12:
++        d += u.p32[2];
++        c += u.p64[0];
++        break;
++    case 11:
++        d += ((uint64)u.p8[10]) << 16;
++    case 10:
++        d += ((uint64)u.p8[9]) << 8;
++    case 9:
++        d += (uint64)u.p8[8];
++    case 8:
++        c += u.p64[0];
++        break;
++    case 7:
++        c += ((uint64)u.p8[6]) << 48;
++    case 6:
++        c += ((uint64)u.p8[5]) << 40;
++    case 5:
++        c += ((uint64)u.p8[4]) << 32;
++    case 4:
++        c += u.p32[0];
++        break;
++    case 3:
++        c += ((uint64)u.p8[2]) << 16;
++    case 2:
++        c += ((uint64)u.p8[1]) << 8;
++    case 1:
++        c += (uint64)u.p8[0];
++        break;
++    case 0:
++        c += sc_const;
++        d += sc_const;
++    }
++    ShortEnd(a,b,c,d);
++    *hash1 = a;
++    *hash2 = b;
++}
++
++
++
++
++// do the whole hash in one call
++void SpookyHash::Hash128(
++    const void *message, 
++    size_t length, 
++    uint64 *hash1, 
++    uint64 *hash2)
++{
++    if (length < sc_bufSize)
++    {
++        Short(message, length, hash1, hash2);
++        return;
++    }
++
++    uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
++    uint64 buf[sc_numVars];
++    uint64 *end;
++    union 
++    { 
++        const uint8 *p8; 
++        uint64 *p64; 
++        size_t i; 
++    } u;
++    size_t remainder;
++    
++    h0=h3=h6=h9  = *hash1;
++    h1=h4=h7=h10 = *hash2;
++    h2=h5=h8=h11 = sc_const;
++    
++    u.p8 = (const uint8 *)message;
++    end = u.p64 + (length/sc_blockSize)*sc_numVars;
++
++    // handle all whole sc_blockSize blocks of bytes
++    if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
++    {
++        while (u.p64 < end)
++        { 
++            Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++	    u.p64 += sc_numVars;
++        }
++    }
++    else
++    {
++        while (u.p64 < end)
++        {
++            memcpy(buf, u.p64, sc_blockSize);
++            Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++	    u.p64 += sc_numVars;
++        }
++    }
++
++    // handle the last partial block of sc_blockSize bytes
++    remainder = (length - ((const uint8 *)end-(const uint8 *)message));
++    memcpy(buf, end, remainder);
++    memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder);
++    ((uint8 *)buf)[sc_blockSize-1] = remainder;
++    Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++    
++    // do some final mixing 
++    End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++    *hash1 = h0;
++    *hash2 = h1;
++}
++
++
++
++// init spooky state
++void SpookyHash::Init(uint64 seed1, uint64 seed2)
++{
++    m_length = 0;
++    m_remainder = 0;
++    m_state[0] = seed1;
++    m_state[1] = seed2;
++}
++
++
++// add a message fragment to the state
++void SpookyHash::Update(const void *message, size_t length)
++{
++    uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
++    size_t newLength = length + m_remainder;
++    uint8  remainder;
++    union 
++    { 
++        const uint8 *p8; 
++        uint64 *p64; 
++        size_t i; 
++    } u;
++    const uint64 *end;
++    
++    // Is this message fragment too short?  If it is, stuff it away.
++    if (newLength < sc_bufSize)
++    {
++        memcpy(&((uint8 *)m_data)[m_remainder], message, length);
++        m_length = length + m_length;
++        m_remainder = (uint8)newLength;
++        return;
++    }
++    
++    // init the variables
++    if (m_length < sc_bufSize)
++    {
++        h0=h3=h6=h9  = m_state[0];
++        h1=h4=h7=h10 = m_state[1];
++        h2=h5=h8=h11 = sc_const;
++    }
++    else
++    {
++        h0 = m_state[0];
++        h1 = m_state[1];
++        h2 = m_state[2];
++        h3 = m_state[3];
++        h4 = m_state[4];
++        h5 = m_state[5];
++        h6 = m_state[6];
++        h7 = m_state[7];
++        h8 = m_state[8];
++        h9 = m_state[9];
++        h10 = m_state[10];
++        h11 = m_state[11];
++    }
++    m_length = length + m_length;
++    
++    // if we've got anything stuffed away, use it now
++    if (m_remainder)
++    {
++        uint8 prefix = sc_bufSize-m_remainder;
++        memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix);
++        u.p64 = m_data;
++        Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++        Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++        u.p8 = ((const uint8 *)message) + prefix;
++        length -= prefix;
++    }
++    else
++    {
++        u.p8 = (const uint8 *)message;
++    }
++    
++    // handle all whole blocks of sc_blockSize bytes
++    end = u.p64 + (length/sc_blockSize)*sc_numVars;
++    remainder = (uint8)(length-((const uint8 *)end-u.p8));
++    if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
++    {
++        while (u.p64 < end)
++        { 
++            Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++	    u.p64 += sc_numVars;
++        }
++    }
++    else
++    {
++        while (u.p64 < end)
++        { 
++            memcpy(m_data, u.p8, sc_blockSize);
++            Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++	    u.p64 += sc_numVars;
++        }
++    }
++
++    // stuff away the last few bytes
++    m_remainder = remainder;
++    memcpy(m_data, end, remainder);
++    
++    // stuff away the variables
++    m_state[0] = h0;
++    m_state[1] = h1;
++    m_state[2] = h2;
++    m_state[3] = h3;
++    m_state[4] = h4;
++    m_state[5] = h5;
++    m_state[6] = h6;
++    m_state[7] = h7;
++    m_state[8] = h8;
++    m_state[9] = h9;
++    m_state[10] = h10;
++    m_state[11] = h11;
++}
++
++
++// report the hash for the concatenation of all message fragments so far
++void SpookyHash::Final(uint64 *hash1, uint64 *hash2)
++{
++    // init the variables
++    if (m_length < sc_bufSize)
++    {
++        Short( m_data, m_length, hash1, hash2);
++        return;
++    }
++    
++    const uint64 *data = (const uint64 *)m_data;
++    uint8 remainder = m_remainder;
++    
++    uint64 h0 = m_state[0];
++    uint64 h1 = m_state[1];
++    uint64 h2 = m_state[2];
++    uint64 h3 = m_state[3];
++    uint64 h4 = m_state[4];
++    uint64 h5 = m_state[5];
++    uint64 h6 = m_state[6];
++    uint64 h7 = m_state[7];
++    uint64 h8 = m_state[8];
++    uint64 h9 = m_state[9];
++    uint64 h10 = m_state[10];
++    uint64 h11 = m_state[11];
++
++    if (remainder >= sc_blockSize)
++    {
++        // m_data can contain two blocks; handle any whole first block
++        Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++	data += sc_numVars;
++	remainder -= sc_blockSize;
++    }
++
++    // mix in the last partial block, and the length mod sc_blockSize
++    memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder));
++
++    ((uint8 *)data)[sc_blockSize-1] = remainder;
++    Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++    
++    // do some final mixing
++    End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
++
++    *hash1 = h0;
++    *hash2 = h1;
++}
++
+diff --git a/gfx/angle/src/compiler/spooky.h b/gfx/angle/src/compiler/spooky.h
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/src/compiler/spooky.h
+@@ -0,0 +1,293 @@
++//
++// SpookyHash: a 128-bit noncryptographic hash function
++// By Bob Jenkins, public domain
++//   Oct 31 2010: alpha, framework + SpookyHash::Mix appears right
++//   Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right
++//   Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas
++//   Feb  2 2012: production, same bits as beta
++//   Feb  5 2012: adjusted definitions of uint* to be more portable
++// 
++// Up to 4 bytes/cycle for long messages.  Reasonably fast for short messages.
++// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
++//
++// This was developed for and tested on 64-bit x86-compatible processors.
++// It assumes the processor is little-endian.  There is a macro
++// controlling whether unaligned reads are allowed (by default they are).
++// This should be an equally good hash on big-endian machines, but it will
++// compute different results on them than on little-endian machines.
++//
++// Google's CityHash has similar specs to SpookyHash, and CityHash is faster
++// on some platforms.  MD4 and MD5 also have similar specs, but they are orders
++// of magnitude slower.  CRCs are two or more times slower, but unlike 
++// SpookyHash, they have nice math for combining the CRCs of pieces to form 
++// the CRCs of wholes.  There are also cryptographic hashes, but those are even 
++// slower than MD5.
++//
++
++#include <stddef.h>
++
++#ifdef _MSC_VER
++# define INLINE __forceinline
++  typedef  unsigned __int64 uint64;
++  typedef  unsigned __int32 uint32;
++  typedef  unsigned __int16 uint16;
++  typedef  unsigned __int8  uint8;
++#else
++# include <stdint.h>
++# define INLINE inline
++  typedef  uint64_t  uint64;
++  typedef  uint32_t  uint32;
++  typedef  uint16_t  uint16;
++  typedef  uint8_t   uint8;
++#endif
++
++
++class SpookyHash
++{
++public:
++    //
++    // SpookyHash: hash a single message in one call, produce 128-bit output
++    //
++    static void Hash128(
++        const void *message,  // message to hash
++        size_t length,        // length of message in bytes
++        uint64 *hash1,        // in/out: in seed 1, out hash value 1
++        uint64 *hash2);       // in/out: in seed 2, out hash value 2
++
++    //
++    // Hash64: hash a single message in one call, return 64-bit output
++    //
++    static uint64 Hash64(
++        const void *message,  // message to hash
++        size_t length,        // length of message in bytes
++        uint64 seed)          // seed
++    {
++        uint64 hash1 = seed;
++        Hash128(message, length, &hash1, &seed);
++        return hash1;
++    }
++
++    //
++    // Hash32: hash a single message in one call, produce 32-bit output
++    //
++    static uint32 Hash32(
++        const void *message,  // message to hash
++        size_t length,        // length of message in bytes
++        uint32 seed)          // seed
++    {
++        uint64 hash1 = seed, hash2 = seed;
++        Hash128(message, length, &hash1, &hash2);
++        return (uint32)hash1;
++    }
++
++    //
++    // Init: initialize the context of a SpookyHash
++    //
++    void Init(
++        uint64 seed1,       // any 64-bit value will do, including 0
++        uint64 seed2);      // different seeds produce independent hashes
++    
++    //
++    // Update: add a piece of a message to a SpookyHash state
++    //
++    void Update(
++        const void *message,  // message fragment
++        size_t length);       // length of message fragment in bytes
++
++
++    //
++    // Final: compute the hash for the current SpookyHash state
++    //
++    // This does not modify the state; you can keep updating it afterward
++    //
++    // The result is the same as if SpookyHash() had been called with
++    // all the pieces concatenated into one message.
++    //
++    void Final(
++        uint64 *hash1,    // out only: first 64 bits of hash value.
++        uint64 *hash2);   // out only: second 64 bits of hash value.
++
++    //
++    // left rotate a 64-bit value by k bytes
++    //
++    static INLINE uint64 Rot64(uint64 x, int k)
++    {
++        return (x << k) | (x >> (64 - k));
++    }
++
++    //
++    // This is used if the input is 96 bytes long or longer.
++    //
++    // The internal state is fully overwritten every 96 bytes.
++    // Every input bit appears to cause at least 128 bits of entropy
++    // before 96 other bytes are combined, when run forward or backward
++    //   For every input bit,
++    //   Two inputs differing in just that input bit
++    //   Where "differ" means xor or subtraction
++    //   And the base value is random
++    //   When run forward or backwards one Mix
++    // I tried 3 pairs of each; they all differed by at least 212 bits.
++    //
++    static INLINE void Mix(
++        const uint64 *data, 
++        uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3,
++        uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7,
++        uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11)
++    {
++      s0 += data[0];    s2 ^= s10;    s11 ^= s0;    s0 = Rot64(s0,11);    s11 += s1;
++      s1 += data[1];    s3 ^= s11;    s0 ^= s1;    s1 = Rot64(s1,32);    s0 += s2;
++      s2 += data[2];    s4 ^= s0;    s1 ^= s2;    s2 = Rot64(s2,43);    s1 += s3;
++      s3 += data[3];    s5 ^= s1;    s2 ^= s3;    s3 = Rot64(s3,31);    s2 += s4;
++      s4 += data[4];    s6 ^= s2;    s3 ^= s4;    s4 = Rot64(s4,17);    s3 += s5;
++      s5 += data[5];    s7 ^= s3;    s4 ^= s5;    s5 = Rot64(s5,28);    s4 += s6;
++      s6 += data[6];    s8 ^= s4;    s5 ^= s6;    s6 = Rot64(s6,39);    s5 += s7;
++      s7 += data[7];    s9 ^= s5;    s6 ^= s7;    s7 = Rot64(s7,57);    s6 += s8;
++      s8 += data[8];    s10 ^= s6;    s7 ^= s8;    s8 = Rot64(s8,55);    s7 += s9;
++      s9 += data[9];    s11 ^= s7;    s8 ^= s9;    s9 = Rot64(s9,54);    s8 += s10;
++      s10 += data[10];    s0 ^= s8;    s9 ^= s10;    s10 = Rot64(s10,22);    s9 += s11;
++      s11 += data[11];    s1 ^= s9;    s10 ^= s11;    s11 = Rot64(s11,46);    s10 += s0;
++    }
++
++    //
++    // Mix all 12 inputs together so that h0, h1 are a hash of them all.
++    //
++    // For two inputs differing in just the input bits
++    // Where "differ" means xor or subtraction
++    // And the base value is random, or a counting value starting at that bit
++    // The final result will have each bit of h0, h1 flip
++    // For every input bit,
++    // with probability 50 +- .3%
++    // For every pair of input bits,
++    // with probability 50 +- 3%
++    //
++    // This does not rely on the last Mix() call having already mixed some