Merge latest green changeset from mozilla-central to maple
authorBenoit Girard <b56girard@gmail.com>
Mon, 05 Mar 2012 13:41:15 -0500
changeset 89294 7c9f942b9becdb29912997dcda0bfe53d78b6451
parent 89293 17c65d32c7b891e70435561b965b71c355bd28ac (current diff)
parent 88226 433cfbd2a0da3f9cc7c1391f95a28404966c6466 (diff)
child 89295 f99d62aca00a57893150b7d63eeacfbd72338780
push id22242
push userkgupta@mozilla.com
push dateWed, 14 Mar 2012 15:19:09 +0000
treeherdermozilla-central@936ef50fa498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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;