Merge from Tracemonkey.
authorDavid Mandelin <dmandelin@mozilla.com>
Wed, 28 Jul 2010 11:16:36 -0700
changeset 53226 ce7ea12f6b79d4849d5f43bed668166f545093aa
parent 53225 1f21eec5216796219a8a237a8b14b4698fbda35e (current diff)
parent 48618 a422d93d397e06eafaf274047a9dff561686f538 (diff)
child 53227 aabc31b1b29e17290a8c0ebb982e9adfe9b1c8c7
push idunknown
push userunknown
push dateunknown
milestone2.0b3pre
Merge from Tracemonkey.
accessible/src/msaa/nsRootAccessibleWrap.cpp
build/automation.py.in
caps/src/nsScriptSecurityManager.cpp
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/canvas/src/CustomQS_Canvas2D.h
content/canvas/src/CustomQS_WebGL.h
content/html/content/public/nsIRadioControlElement.h
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
content/svg/content/src/nsISVGLength.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsJSEnvironment.cpp
gfx/layers/basic/ThebesLayerBuffer.cpp
gfx/layers/basic/ThebesLayerBuffer.h
js/ipc/ObjectWrapperParent.cpp
js/jetpack/JetpackChild.cpp
js/jetpack/JetpackChild.h
js/jsd/jsd_val.c
js/src/config/rules.mk
js/src/configure.in
js/src/jsapi-tests/testExtendedEq.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsbool.cpp
js/src/jsbuiltins.cpp
js/src/jsbuiltins.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jslock.h
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsopcode.cpp
js/src/jsparse.cpp
js/src/jsproxy.cpp
js/src/jsprvtd.h
js/src/jspubtd.h
js/src/jsrecursion.cpp
js/src/jsregexp.cpp
js/src/jsregexp.h
js/src/jsscope.cpp
js/src/jsscope.h
js/src/jsscopeinlines.h
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jsstr.h
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jstypedarray.cpp
js/src/jsvalue.h
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/jsxml.h
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/tests/jstests.py
js/src/xpconnect/idl/nsIXPConnect.idl
js/src/xpconnect/src/Makefile.in
js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
js/src/xpconnect/src/XPCCrossOriginWrapper.cpp
js/src/xpconnect/src/XPCDispInterface.cpp
js/src/xpconnect/src/XPCNativeWrapper.cpp
js/src/xpconnect/src/XPCNativeWrapper.h
js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
js/src/xpconnect/src/XPCWrapper.cpp
js/src/xpconnect/src/XPCWrapper.h
js/src/xpconnect/src/dom_quickstubs.qsconf
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/qsgen.py
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcconvert.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcquickstubs.cpp
js/src/xpconnect/src/xpcquickstubs.h
js/src/xpconnect/src/xpcwrappednative.cpp
js/src/xpconnect/src/xpcwrappednativeinfo.cpp
js/src/xpconnect/src/xpcwrappednativejsops.cpp
js/src/xpconnect/src/xpcwrappednativescope.cpp
modules/libpref/src/init/all.js
toolkit/locales/en-US/chrome/global/headsUpDisplay.dtd
widget/src/windows/nsKeyboardLayout.cpp
widget/src/windows/nsKeyboardLayout.h
xpcom/io/nsLocalFileOSX.h
xpcom/io/nsLocalFileOSX.mm
--- a/README.txt
+++ b/README.txt
@@ -3,17 +3,17 @@ project pages with documentation can be 
 
     https://developer.mozilla.org/en/Mozilla_Source_Code_Directory_Structure
 
 For information on how to build Mozilla from the source code, see:
 
     http://developer.mozilla.org/en/docs/Build_Documentation
 
 To have your bug fix / feature added to Mozilla, you should create a patch and
-submit it to Bugzilla (http://bugzilla.mozilla.org). Instructions are at:
+submit it to Bugzilla (https://bugzilla.mozilla.org). Instructions are at:
 
     http://developer.mozilla.org/en/docs/Creating_a_patch
     http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree
 
 If you have a question about developing Mozilla, and can't find the solution
 on http://developer.mozilla.org, you can try asking your question in a
 mozilla.* Usenet group, or on IRC at irc.mozilla.org. [The Mozilla news groups
 are accessible on Google Groups, or news.mozilla.org with a NNTP reader.]
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1245,17 +1245,18 @@ nsDocAccessible::ContentInserted(nsIDocu
   // unless an accessible can be created for the passed in node, which it
   // can't do unless the node is visible. The right thing happens there so
   // no need for an extra visibility check here.
   InvalidateCacheSubtree(aChild, nsIAccessibilityService::NODE_APPEND);
 }
 
 void
 nsDocAccessible::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
-                                nsIContent* aChild, PRInt32 /* unused */)
+                                nsIContent* aChild, PRInt32 /* unused */,
+                                nsIContent* aPreviousSibling)
 {
   // It's no needed to invalidate the subtree of the removed element,
   // because we get notifications directly from content (see
   // nsGenericElement::doRemoveChildAt) *before* the frame for the content is
   // destroyed, or any other side effects occur . That allows us to correctly
   // calculate the TEXT_REMOVED event if there is one and coalesce events from
   // the same subtree.
 }
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -46,17 +46,16 @@ LIBRARY_NAME = accessibility_toolkit_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
-  nsRootAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
   nsARIAGridAccessibleWrap.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULListboxAccessibleWrap.cpp \
   nsXULTreeGridAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -214,20 +214,26 @@ STDMETHODIMP nsAccessibleWrap::get_accPa
 
         nsIViewManager* viewManager = view->GetViewManager();
         if (!viewManager)
           return E_UNEXPECTED;
 
         nsIView *rootView;
         viewManager->GetRootView(rootView);
         if (rootView == view) {
-          // If the current object has a widget but was created by an
-          // outer object with its own outer window, then
-          // we want the native accessible for that outer window
-          hwnd = ::GetParent(hwnd);
+          // If the client accessible (OBJID_CLIENT) has a window but its window
+          // was created by an outer window then we want the native accessible
+          // for that outer window. If the accessible was created for outer
+          // window (if the outer window has inner windows then they share the
+          // same client accessible with it) then return native accessible for
+          // the outer window.
+          HWND parenthwnd = ::GetParent(hwnd);
+          if (parenthwnd)
+            hwnd = parenthwnd;
+
           NS_ASSERTION(hwnd, "No window handle for window");
         }
       }
       else {
         // If a frame is a scrollable frame, then it has one window for the client area,
         // not an extra parent window for just the scrollbars
         nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
         if (scrollFrame) {
@@ -362,77 +368,18 @@ nsAccessibleWrap::get_accDescription(VAR
 {
 __try {
   *pszDescription = NULL;
 
   nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_FAIL;
 
-  // For items that are a choice in a list of choices, use MSAA description
-  // field to shoehorn positional info, it's becoming a defacto standard use for
-  // the field.
-
   nsAutoString description;
-
-  // Try to get group position to make a positional description string.
-  PRInt32 groupLevel = 0;
-  PRInt32 itemsInGroup = 0;
-  PRInt32 positionInGroup = 0;
-  GroupPosition(&groupLevel, &itemsInGroup, &positionInGroup);
-
-  if (positionInGroup > 0) {
-    if (groupLevel > 0) {
-      // XXX: How do we calculate the number of children? Now we append
-      // " with [numChildren]c" for tree item. In the future we may need to
-      // use the ARIA owns property to calculate that if it's present.
-      PRInt32 numChildren = 0;
-
-      PRUint32 currentRole = nsAccUtils::Role(xpAccessible);
-      if (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
-        PRInt32 childCount = xpAccessible->GetChildCount();
-        for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
-          nsAccessible *child = xpAccessible->GetChildAt(childIdx);
-          currentRole = nsAccUtils::Role(child);
-          if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
-            PRInt32 groupChildCount = child->GetChildCount();
-            for (PRInt32 groupChildIdx = 0; groupChildIdx < groupChildCount;
-                 groupChildIdx++) {
-              nsAccessible *groupChild = child->GetChildAt(groupChildIdx);
-              currentRole = nsAccUtils::Role(groupChild);
-              numChildren +=
-                (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
-            }
-            break;
-          }
-        }
-      }
-
-      if (numChildren) {
-        nsTextFormatter::ssprintf(description,
-                                  NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
-                                  groupLevel, positionInGroup, itemsInGroup,
-                                  numChildren);
-      } else {
-        nsTextFormatter::ssprintf(description,
-                                  NS_LITERAL_STRING("L%d, %d of %d").get(),
-                                  groupLevel, positionInGroup, itemsInGroup);
-      }
-    } else { // Position has no level
-      nsTextFormatter::ssprintf(description,
-                                NS_LITERAL_STRING("%d of %d").get(),
-                                positionInGroup, itemsInGroup);
-    }
-  } else if (groupLevel > 0) {
-    nsTextFormatter::ssprintf(description, NS_LITERAL_STRING("L%d").get(),
-                              groupLevel);
-  }
-
-  if (description.IsEmpty())
-    xpAccessible->GetDescription(description);
+  xpAccessible->GetDescription(description);
 
   *pszDescription = ::SysAllocStringLen(description.get(),
                                         description.Length());
   return *pszDescription ? S_OK : E_OUTOFMEMORY;
 
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
deleted file mode 100644
--- a/accessible/src/msaa/nsRootAccessibleWrap.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C++; 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) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Original Author: Aaron Leventhal (aaronl@netscape.com)
- *
- * 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 ***** */
-
-#include "nsRootAccessibleWrap.h"
-#include "nsIAccessible.h"
-#include "nsIAccessibleDocument.h"
-#include "nsIServiceManager.h"
-
-/* For documentation of the accessibility architecture, 
- * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
- */
-
-////////////////////////////////////////////////////////////////////////////////
-// nsRootAccessibleWrap
-////////////////////////////////////////////////////////////////////////////////
-
-nsRootAccessibleWrap::
-  nsRootAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
-                       nsIWeakReference *aShell) :
-  nsRootAccessible(aDocument, aRootContent, aShell)
-{
-}
-
-nsRootAccessibleWrap::~nsRootAccessibleWrap()
-{
-}
-
--- a/accessible/src/msaa/nsRootAccessibleWrap.h
+++ b/accessible/src/msaa/nsRootAccessibleWrap.h
@@ -38,20 +38,13 @@
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef _nsRootAccessibleWrap_H_
 #define _nsRootAccessibleWrap_H_
 
-#include "nsCOMPtr.h"
 #include "nsRootAccessible.h"
 
-class nsRootAccessibleWrap: public nsRootAccessible
-{
-public:
-  nsRootAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
-                       nsIWeakReference *aShell);
-  virtual ~nsRootAccessibleWrap();
-};
+typedef class nsRootAccessible nsRootAccessibleWrap;
 
 #endif
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
@@ -374,37 +374,40 @@ var stringBundle;
     if (!experiment) {
       // Possible that experiments aren't done loading yet.  Try again in
       // a few seconds.
       contentDiv.innerHTML =
         stringBundle.GetStringFromName("testpilot.statusPage.loading");
       window.setTimeout(function() { loadExperimentPage(); }, 2000);
       return;
     }
+
+    // Let the experiment fill in its web content (asynchronous)
     experiment.getWebContent(function(webContent) {
       contentDiv.innerHTML = webContent;
+
+      // Metadata and start/end date should be filled in for every experiment:
+      showMetaData();
+      getTestEndingDate(eid);
+      if (experiment._recursAutomatically &&
+        experiment.status != TaskConstants.STATUS_FINISHED) {
+        showRecurControls(experiment);
+      }
+
+      // Do whatever the experiment's web content wants done on load
+      // (Usually drawing a graph) - must be done after innerHTML is set.
+      experiment.webContent.onPageLoad(experiment, document, jQuery);
     });
 
     experiment.getDataPrivacyContent(function(dataPrivacyContent) {
       if (dataPrivacyContent && dataPrivacyContent.length > 0) {
         dataPrivacyDiv.innerHTML = dataPrivacyContent;
         dataPrivacyDiv.removeAttribute("hidden");
       }
     });
-
-    // Metadata and start/end date should be filled in for every experiment:
-    showMetaData();
-    getTestEndingDate(eid);
-    if (experiment._recursAutomatically &&
-        experiment.status != TaskConstants.STATUS_FINISHED) {
-      showRecurControls(experiment);
-    }
-
-    // Do whatever the experiment's web content wants done on load:
-    experiment.webContent.onPageLoad(experiment, document, jQuery);
   }
 
   function onStatusPageLoad() {
     setStrings(PAGE_TYPE_STATUS);
     /* If an experiment ID (eid) is provided in the url params, show status
      * for that experiment.  If not, show the main menu with status for all
      * installed experiments. */
     let eidString = getUrlParam("eid");
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
@@ -565,17 +565,17 @@ let TestPilotSetup = {
 		[task.title], 1),
 	      this._stringBundle.GetStringFromName(
 		"testpilot.notification.newTestPilotStudy"),
 	      "new-study", false, false,
 	      this._stringBundle.GetStringFromName("testpilot.moreInfo"),
 	      task.defaultUrl, false, function() {
                 /* on close callback (Bug 575767) -- when the "new study
                  * starting" popup is dismissed, then the study can start. */
-                task.changeStatus(TaskConstants.STATUS_IN_PROGRESS, true);
+                task.changeStatus(TaskConstants.STATUS_STARTING, true);
                 TestPilotSetup.reloadRemoteExperiments();
               });
             return;
           } else if (task.taskType == TaskConstants.TYPE_SURVEY) {
 	    this._showNotification(
 	      task, false,
 	      this._stringBundle.formatStringFromName(
 		"testpilot.notification.newTestPilotSurvey.message",
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
@@ -614,21 +614,24 @@ TestPilotExperiment.prototype = {
       this._logger.info("Study now starting.");
       let uuidGenerator =
         Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
       let uuid = uuidGenerator.generateUUID().toString();
       // remove the brackets from the generated UUID
       if (uuid.indexOf("{") == 0) {
         uuid = uuid.substring(1, (uuid.length - 1));
       }
+      Application.prefs.setValue(GUID_PREF_PREFIX + this._id, uuid);
       // clear the data before starting.
-      this._dataStore.wipeAllData();
-      this.changeStatus(TaskConstants.STATUS_STARTING, true);
-      Application.prefs.setValue(GUID_PREF_PREFIX + this._id, uuid);
-      this.onExperimentStartup();
+      let self = this;
+      this._dataStore.wipeAllData(function() {
+        // Experiment is now in progress.
+        self.changeStatus(TaskConstants.STATUS_IN_PROGRESS, true);
+        self.onExperimentStartup();
+      });
     }
 
     // What happens when a test finishes:
     if (this._status < TaskConstants.STATUS_FINISHED &&
 	currentDate > this._endDate) {
       let self = this;
       let setDataDeletionDate = true;
       this._logger.info("Passed End Date - Switched Task Status to Finished");
--- a/browser/base/content/aboutRobots.xhtml
+++ b/browser/base/content/aboutRobots.xhtml
@@ -80,17 +80,17 @@
           buttonClicked = true;
         }
       }
     ]]></script>
 
     <style type="text/css"><![CDATA[
       #errorPageContainer {
         background: url('chrome://browser/content/aboutRobots-icon.png') left 0 no-repeat -moz-Field;
-        -moz-background-origin: content;
+        background-origin: content-box;
       }
 
       #errorTrailerDescText {
         float: right;
       }
 
       body[dir=rtl] #errorPageContainer {
         background-image: url('chrome://browser/content/aboutRobots-icon-rtl.png');
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -43,24 +43,24 @@
                 label="&spellAddToDictionary.label;"
                 accesskey="&spellAddToDictionary.accesskey;"
                 oncommand="InlineSpellCheckerUI.addToDictionary();"/>
       <menuseparator id="spell-suggestions-separator"/>
       <menuitem id="context-openlinkincurrent"
                 label="&openLinkCmdInCurrent.label;"
                 accesskey="&openLinkCmdInCurrent.accesskey;"
                 oncommand="gContextMenu.openLinkInCurrent();"/>
+      <menuitem id="context-openlinkintab"
+                label="&openLinkCmdInTab.label;"
+                accesskey="&openLinkCmdInTab.accesskey;"
+                oncommand="gContextMenu.openLinkInTab();"/>
       <menuitem id="context-openlink"
                 label="&openLinkCmd.label;"
                 accesskey="&openLinkCmd.accesskey;"
                 oncommand="gContextMenu.openLink();"/>
-      <menuitem id="context-openlinkintab"
-                label="&openLinkCmdInTab.label;"
-                accesskey="&openLinkCmdInTab.accesskey;"
-                oncommand="gContextMenu.openLinkInTab();"/>
       <menuseparator id="context-sep-open"/>
       <menuitem id="context-bookmarklink"
                 label="&bookmarkThisLinkCmd.label;"
                 accesskey="&bookmarkThisLinkCmd.accesskey;"
                 oncommand="gContextMenu.bookmarkLink();"/>
       <menuitem id="context-savelink"
                 label="&saveLinkCmd.label;"
                 accesskey="&saveLinkCmd.accesskey;"
@@ -245,24 +245,24 @@
                 oncommand="BrowserSearch.loadSearch(getBrowserSelection(), true);"/>
       <menuseparator id="frame-sep"/>
       <menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
         <menupopup>
           <menuitem id="context-showonlythisframe"
                     label="&showOnlyThisFrameCmd.label;"
                     accesskey="&showOnlyThisFrameCmd.accesskey;"
                     oncommand="gContextMenu.showOnlyThisFrame();"/>
+          <menuitem id="context-openframeintab"
+                    label="&openFrameCmdInTab.label;"
+                    accesskey="&openFrameCmdInTab.accesskey;"
+                    oncommand="gContextMenu.openFrameInTab();"/>
           <menuitem id="context-openframe"
                     label="&openFrameCmd.label;"
                     accesskey="&openFrameCmd.accesskey;"
                     oncommand="gContextMenu.openFrame();"/>
-          <menuitem id="context-openframeintab"
-                    label="&openFrameCmdInTab.label;"
-                    accesskey="&openFrameCmdInTab.accesskey;"
-                    oncommand="gContextMenu.openFrameInTab();"/>
           <menuseparator/>
           <menuitem id="context-reloadframe"
                     label="&reloadFrameCmd.label;"
                     accesskey="&reloadFrameCmd.accesskey;"
                     oncommand="gContextMenu.reloadFrame();"/>
           <menuseparator/>
           <menuitem id="context-bookmarkframe"
                     label="&bookmarkThisFrameCmd.label;"
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -43,113 +43,85 @@
 // One of the possible values for the mousewheel.* preferences.
 // From nsEventStateManager.cpp.
 const MOUSE_SCROLL_ZOOM = 3;
 
 /**
  * Controls the "full zoom" setting and its site-specific preferences.
  */
 var FullZoom = {
-
-  //**************************************************************************//
-  // Name & Values
-
-  // The name of the setting.  Identifies the setting in the prefs database.
+  // Identifies the setting in the content prefs database.
   name: "browser.content.full-zoom",
 
   // The global value (if any) for the setting.  Lazily loaded from the service
   // when first requested, then updated by the pref change listener as it changes.
   // If there is no global value, then this should be undefined.
   get globalValue() {
-    var globalValue = this._cps.getPref(null, this.name);
+    var globalValue = Services.contentPrefs.getPref(null, this.name);
     if (typeof globalValue != "undefined")
       globalValue = this._ensureValid(globalValue);
     delete this.globalValue;
     return this.globalValue = globalValue;
   },
 
-
-  //**************************************************************************//
-  // Convenience Getters
-
-  // Content Pref Service
-  get _cps() {
-    delete this._cps;
-    return this._cps = Cc["@mozilla.org/content-pref/service;1"].
-                       getService(Ci.nsIContentPrefService);
-  },
-
   // browser.zoom.siteSpecific preference cache
   _siteSpecificPref: undefined,
 
   // browser.zoom.updateBackgroundTabs preference cache
   updateBackgroundTabs: undefined,
 
   // whether we are in private browsing mode
   _inPrivateBrowsing: false,
 
   get siteSpecific() {
     return !this._inPrivateBrowsing && this._siteSpecificPref;
   },
 
   //**************************************************************************//
   // nsISupports
 
-  // We can't use the Ci shortcut here because it isn't defined yet.
-  interfaces: [Components.interfaces.nsIDOMEventListener,
-               Components.interfaces.nsIObserver,
-               Components.interfaces.nsIContentPrefObserver,
-               Components.interfaces.nsISupportsWeakReference,
-               Components.interfaces.nsISupports],
-
-  QueryInterface: function FullZoom_QueryInterface(aIID) {
-    if (!this.interfaces.some(function (v) aIID.equals(v)))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    return this;
-  },
-
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
+                                         Ci.nsIObserver,
+                                         Ci.nsIContentPrefObserver,
+                                         Ci.nsISupportsWeakReference,
+                                         Ci.nsISupports]),
 
   //**************************************************************************//
   // Initialization & Destruction
 
   init: function FullZoom_init() {
     // Listen for scrollwheel events so we can save scrollwheel-based changes.
     window.addEventListener("DOMMouseScroll", this, false);
 
     // Register ourselves with the service so we know when our pref changes.
-    this._cps.addObserver(this.name, this);
+    Services.contentPrefs.addObserver(this.name, this);
 
     // We disable site-specific preferences in Private Browsing mode, because the
     // content preferences module is disabled
-    let os = Cc["@mozilla.org/observer-service;1"].
-             getService(Ci.nsIObserverService);
-    os.addObserver(this, "private-browsing", true);
+    Services.obs.addObserver(this, "private-browsing", true);
 
     // Retrieve the initial status of the Private Browsing mode.
     this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
                               getService(Ci.nsIPrivateBrowsingService).
                               privateBrowsingEnabled;
 
     this._siteSpecificPref =
       gPrefService.getBoolPref("browser.zoom.siteSpecific");
     this.updateBackgroundTabs =
       gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
     // Listen for changes to the browser.zoom branch so we can enable/disable
     // updating background tabs and per-site saving and restoring of zoom levels.
     gPrefService.addObserver("browser.zoom.", this, true);
   },
 
   destroy: function FullZoom_destroy() {
-    let os = Cc["@mozilla.org/observer-service;1"].
-             getService(Ci.nsIObserverService);
-    os.removeObserver(this, "private-browsing");
+    Services.obs.removeObserver(this, "private-browsing");
     gPrefService.removeObserver("browser.zoom.", this);
-    this._cps.removeObserver(this.name, this);
+    Services.contentPrefs.removeObserver(this.name, this);
     window.removeEventListener("DOMMouseScroll", this, false);
-    delete this._cps;
   },
 
 
   //**************************************************************************//
   // Event Handlers
 
   // nsIDOMEventListener
 
@@ -226,39 +198,39 @@ var FullZoom = {
         }
         break;
     }
   },
 
   // nsIContentPrefObserver
 
   onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
-    if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
+    if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
       this._applyPrefToSetting(aValue);
     else if (aGroup == null) {
       this.globalValue = this._ensureValid(aValue);
 
       // If the current page doesn't have a site-specific preference,
       // then its zoom should be set to the new global preference now that
       // the global preference has changed.
-      if (!this._cps.hasPref(gBrowser.currentURI, this.name))
+      if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
         this._applyPrefToSetting();
     }
   },
 
   onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
-    if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
+    if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
       this._applyPrefToSetting();
     else if (aGroup == null) {
       this.globalValue = undefined;
 
       // If the current page doesn't have a site-specific preference,
       // then its zoom should be set to the default preference now that
       // the global preference has changed.
-      if (!this._cps.hasPref(gBrowser.currentURI, this.name))
+      if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
         this._applyPrefToSetting();
     }
   },
 
   // location change observer
 
   /**
    * Called when the location of a tab changes.
@@ -277,17 +249,17 @@ var FullZoom = {
 
     // Avoid the cps roundtrip and apply the default/global pref.
     if (aURI.spec == "about:blank") {
       this._applyPrefToSetting(undefined, aBrowser);
       return;
     }
 
     var self = this;
-    this._cps.getPref(aURI, this.name, function(aResult) {
+    Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
       // Check that we're still where we expect to be in case this took a while.
       let isSaneURI = (aBrowser && aBrowser.currentURI) ?
         aURI.equals(aBrowser.currentURI) : false;
       if (!aBrowser || isSaneURI)
         self._applyPrefToSetting(aResult, aBrowser);
     });
   },
 
@@ -361,22 +333,22 @@ var FullZoom = {
   },
 
   _applySettingToPref: function FullZoom__applySettingToPref() {
     if (!this.siteSpecific || gInPrintPreviewMode ||
         content.document instanceof Ci.nsIImageDocument)
       return;
 
     var zoomLevel = ZoomManager.zoom;
-    this._cps.setPref(gBrowser.currentURI, this.name, zoomLevel);
+    Services.contentPrefs.setPref(gBrowser.currentURI, this.name, zoomLevel);
   },
 
   _removePref: function FullZoom__removePref() {
     if (!(content.document instanceof Ci.nsIImageDocument))
-      this._cps.removePref(gBrowser.currentURI, this.name);
+      Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
   },
 
 
   //**************************************************************************//
   // Utilities
 
   _ensureValid: function FullZoom__ensureValid(aValue) {
     if (isNaN(aValue))
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -37,47 +37,47 @@
 #
 # ***** END LICENSE BLOCK *****
 
        <menubar id="main-menubar"
                 style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
             <menu id="file-menu" label="&fileMenu.label;"
                   accesskey="&fileMenu.accesskey;">
               <menupopup id="menu_FilePopup">
+                <menuitem id="menu_newNavigatorTab"
+                          label="&tabCmd.label;"
+                          command="cmd_newNavigatorTab"
+                          key="key_newNavigatorTab"
+                          accesskey="&tabCmd.accesskey;"/>
                 <menuitem id="menu_newNavigator"
                           label="&newNavigatorCmd.label;"
                           accesskey="&newNavigatorCmd.accesskey;"
                           key="key_newNavigator"
                           command="cmd_newNavigator"/>
-                <menuitem id="menu_newNavigatorTab"
-                          label="&tabCmd.label;"
-                          command="cmd_newNavigatorTab"
-                          key="key_newNavigatorTab"
-                          accesskey="&tabCmd.accesskey;"/>
                 <menuitem id="menu_openLocation"
                           label="&openLocationCmd.label;"
                           command="Browser:OpenLocation"
                           key="focusURLBar"
                           accesskey="&openLocationCmd.accesskey;"/>
                 <menuitem id="menu_openFile"
                           label="&openFileCmd.label;"
                           command="Browser:OpenFile"
                           key="openFileKb"
                           accesskey="&openFileCmd.accesskey;"/>
+                <menuitem id="menu_close"
+                          label="&closeCmd.label;"
+                          key="key_close"
+                          accesskey="&closeCmd.accesskey;"
+                          command="cmd_close"/>
                 <menuitem id="menu_closeWindow"
                           hidden="true"
                           command="cmd_closeWindow"
                           key="key_closeWindow"
                           label="&closeWindow.label;"
                           accesskey="&closeWindow.accesskey;"/>
-                <menuitem id="menu_close"
-                          label="&closeCmd.label;"
-                          key="key_close"
-                          accesskey="&closeCmd.accesskey;"
-                          command="cmd_close"/>
                 <menuseparator/>
                 <menuitem id="menu_savePage"
                           label="&savePageCmd.label;"
                           accesskey="&savePageCmd.accesskey;"
                           key="key_savePage"
                           command="Browser:SavePage"/>
                 <menuitem id="menu_sendLink"
                           label="&sendPageCmd.label;"
@@ -607,20 +607,20 @@
                         accesskey="&inspectMenu.accesskey;"
                         key="key_inspect"
                         command="Tools:Inspect"/>
               <menuitem id="javascriptConsole"
                         label="&errorConsoleCmd.label;"
                         accesskey="&errorConsoleCmd.accesskey;"
                         key="key_errorConsole"
                         oncommand="toJavaScriptConsole();"/>
-              <menuitem id="headsUpDisplayConsole"
-                        label="&hudConsoleCmd.label;"
-                        accesskey="&hudConsoleCmd.accesskey;"
-                        key="key_hudConsole"
+              <menuitem id="webConsole"
+                        label="&webConsoleCmd.label;"
+                        accesskey="&webConsoleCmd.accesskey;"
+                        key="key_webConsole"
                         oncommand="HUDConsoleUI.toggleHUD();"/>
               <menuitem id="menu_pageInfo"
                         accesskey="&pageInfoCmd.accesskey;"
                         label="&pageInfoCmd.label;"
 #ifndef XP_WIN
                         key="key_viewInfo"
 #endif
                         command="View:PageInfo"/>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -39,65 +39,59 @@
 # ***** END LICENSE BLOCK *****
 
 
 var StarUI = {
   _itemId: -1,
   uri: null,
   _batching: false,
 
-  // nsISupports
-  QueryInterface: function SU_QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIDOMEventListener) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_NOINTERFACE;
-  },
-
   _element: function(aID) {
     return document.getElementById(aID);
   },
 
   // Edit-bookmark panel
   get panel() {
     delete this.panel;
     var element = this._element("editBookmarkPanel");
     // initially the panel is hidden
     // to avoid impacting startup / new window performance
     element.hidden = false;
     element.addEventListener("popuphidden", this, false);
     element.addEventListener("keypress", this, false);
     return this.panel = element;
   },
 
-  // list of command elements (by id) to disable when the panel is opened
-  _blockedCommands: ["cmd_close", "cmd_closeWindow"],
+  // Array of command elements to disable when the panel is opened.
+  get _blockedCommands() {
+    delete this._blockedCommands;
+    return this._blockedCommands =
+      ["cmd_close", "cmd_closeWindow"].map(function (id) this._element(id), this);
+  },
+
   _blockCommands: function SU__blockCommands() {
-    for each(var key in this._blockedCommands) {
-      var elt = this._element(key);
+    this._blockedCommands.forEach(function (elt) {
       // make sure not to permanently disable this item (see bug 409155)
       if (elt.hasAttribute("wasDisabled"))
-        continue;
-      if (elt.getAttribute("disabled") == "true")
+        return;
+      if (elt.getAttribute("disabled") == "true") {
         elt.setAttribute("wasDisabled", "true");
-      else {
+      } else {
         elt.setAttribute("wasDisabled", "false");
         elt.setAttribute("disabled", "true");
       }
-    }
+    });
   },
 
   _restoreCommandsState: function SU__restoreCommandsState() {
-    for each(var key in this._blockedCommands) {
-      var elt = this._element(key);
+    this._blockedCommands.forEach(function (elt) {
       if (elt.getAttribute("wasDisabled") != "true")
         elt.removeAttribute("disabled");
       elt.removeAttribute("wasDisabled");
-    }
+    });
   },
 
   // nsIDOMEventListener
   handleEvent: function SU_handleEvent(aEvent) {
     switch (aEvent.type) {
       case "popuphidden":
         if (aEvent.originalTarget == this.panel) {
           if (!this._element("editBookmarkPanelContent").hidden)
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -230,17 +230,17 @@
 #endif
 #ifdef XP_GNOME
     <key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/>
     <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/>
 #else
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #endif
     <key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift"/>
-    <key id="key_hudConsole" key="&hudConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
+    <key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
     <key id="key_inspect" key="&inspectMenu.commandkey;" command="Tools:Inspect" modifiers="accel,shift"/>
     <key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile"  modifiers="accel"/>
     <key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>
     <key id="printKb" key="&printCmd.commandkey;" command="cmd_print"  modifiers="accel"/>
     <key id="key_close" key="&closeCmd.key;" command="cmd_close" modifiers="accel"/>
     <key id="key_closeWindow" key="&closeCmd.key;" command="cmd_closeWindow" modifiers="accel,shift"/>
     <key id="key_undo"
          key="&undoCmd.key;"
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -75,17 +75,17 @@ toolbar[printpreview="true"] {
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
   -moz-box-ordinal-group: 50;
 }
 
 #TabsToolbar {
   -moz-box-ordinal-group: 100;
 }
 
-#navigator-toolbox[tabsontop="true"] > #TabsToolbar {
+#TabsToolbar[tabsontop="true"] {
   -moz-box-ordinal-group: 10;
 }
 
 %ifdef MENUBAR_CAN_AUTOHIDE
 #main-window[inFullscreen] > #appmenu-button-container {
   display: none;
 }
 %endif
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7770,16 +7770,22 @@ var TabContextMenu = {
     document.getElementById("context_undoCloseTab").hidden =
       Cc["@mozilla.org/browser/sessionstore;1"].
       getService(Ci.nsISessionStore).
       getClosedTabCount(window) == 0;
       
     // Only one of pin/unpin should be visible
     document.getElementById("context_pinTab").hidden = this.contextTab.pinned;
     document.getElementById("context_unpinTab").hidden = !this.contextTab.pinned;
+
+    // Disable "Close other Tabs" if there is only one unpinned tab and
+    // hide it when the user rightclicked on a pinned tab.
+    var unpinnedTabs = gBrowser.tabs.length - gBrowser._numPinnedTabs;
+    document.getElementById("context_closeOtherTabs").disabled = unpinnedTabs <= 1;
+    document.getElementById("context_closeOtherTabs").hidden = this.contextTab.pinned;
   }
 };
 
 XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
   Cu.import("resource://gre/modules/HUDService.jsm");
   try {
     return HUDService.consoleUI;
   }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -104,27 +104,21 @@
 # All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the 
 # browser-sets.inc file for sharing with hiddenWindow.xul.
 #include browser-sets.inc
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
-      <menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
-                command="cmd_newNavigatorTab"/>
-      <menuseparator/>
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.reloadAllTabs();"/>
-      <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
-                tbattr="tabbrowser-multiple"
-                oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
       <menuseparator/>
       <menuitem id="context_openTabInWindow" label="&openTabInNewWindow.label;"
                 accesskey="&openTabInNewWindow.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
       <menuitem id="context_pinTab" label="&pinTab.label;"
                 accesskey="&pinTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
@@ -135,21 +129,23 @@
       <menuitem id="context_bookmarkTab"
                 label="&bookmarkThisTab.label;"
                 accesskey="&bookmarkThisTab.accesskey;"
                 oncommand="BookmarkThisTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_bookmarkAllTabs"
                 label="&bookmarkAllTabs.label;"
                 accesskey="&bookmarkAllTabs.accesskey;"
                 command="Browser:BookmarkAllTabs"/>
+      <menuseparator/>
+      <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
+                oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
       <menuitem id="context_undoCloseTab"
                 label="&undoCloseTab.label;"
                 accesskey="&undoCloseTab.accesskey;"
                 command="History:UndoCloseTab"/>
-      <menuseparator/>
       <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
                 oncommand="gBrowser.removeTab(TabContextMenu.contextTab);"/>
     </menupopup>
 
     <menupopup id="backForwardMenu"
                onpopupshowing="return FillHistoryMenu(event.target);"
                oncommand="gotoHistoryIndex(event);"
                onclick="checkForMiddleClick(this, event);"/>
--- a/browser/base/content/credits.xhtml
+++ b/browser/base/content/credits.xhtml
@@ -214,16 +214,17 @@
           &credit.thanks2; <a href="" link="about:credits" onclick="visitLink(event);">&credit.contributors2;</a>
         </div>
 
         <div class="creditsGroup">
           <ul>
             <li>Josh Aas</li>
             <li>Robert Accettura</li>
             <li>Lucas Adamski</li>
+            <li>Raymond Etornam Agbeame</li>
             <li>Ehsan Akhgari</li>
             <li>Sean Alamares</li>
             <li>Pedro Alves</li>
             <li>David Anderson</li>
             <li>Harvey Anderson</li>
             <li>Smokey Ardisson</li>
             <li>Rob Arnold</li>
             <li>Tomoya Asai</li>
@@ -398,16 +399,17 @@
             <li>Bob Lord</li>
             <li>Phil Machalski</li>
             <li>Joel Maher</li>
             <li>Ere Maijala</li>
             <li>David Mandelin</li>
             <li>Gervase Markham</li>
             <li>Sean Martell</li>
             <li>Jim Mathies</li>
+            <li>Blair McBride</li>
             <li>Erica McClure</li>
             <li>Graeme McCutcheon</li>
             <li>Patrick McManus</li>
             <li>Heather Meeker</li>
             <li>Walter Meinl</li>
             <li>Myk Melez</li>
             <li>Federico Mena-Quintero</li>
             <li>Mark Mentovai</li>
@@ -573,16 +575,17 @@
             <li>Steve Won</li>
             <li>Justin Wood</li>
             <li>Michael Wu</li>
             <li>Masahiro Yamada</li>
             <li>Satoko Takita Yamaguchi (Chibi)</li>
             <li>Christine Yen</li>
             <li>Kohei Yoshino</li>
             <li>Shigeru Yoshitake</li>
+            <li>Tanner M. Young</li>
             <li>Boris Zbarsky</li>
             <li>Marco Zehe</li>
             <li>Matthew Zeier</li>
           </ul>
 
           <div dir="&locale.dir;">
             &credit.translation;
           </div>
--- a/browser/base/content/openLocation.xul
+++ b/browser/base/content/openLocation.xul
@@ -75,18 +75,18 @@
                   oninput="doEnabling();"/>
         <button label="&chooseFile.label;" oncommand="onChooseFile();"/>
       </hbox>
       <hbox align="center">
         <label value="&openWhere.label;"/>
         <menulist id="openWhereList">
           <menupopup>
             <menuitem value="0" id="currentWindow" label="&topTab.label;"/>
+            <menuitem value="3" label="&newTab.label;"/>
             <menuitem value="1" label="&newWindow.label;"/>
-            <menuitem value="3" label="&newTab.label;"/>
           </menupopup>
         </menulist>
         <spacer flex="1"/>
       </hbox>
     </vbox>
   </hbox> 
            
 </dialog>
--- a/browser/base/content/stylePanel.jsm
+++ b/browser/base/content/stylePanel.jsm
@@ -49,16 +49,19 @@
  *  Christoph Dorn
  *  Steven Roussey (AppCenter Inc, Network54)
  */
 
 var EXPORTED_SYMBOLS = ["style"];
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
 
 var style = {
 
   /**
    * initialize domUtils
    */
   initialize: function CSS_initialize()
   {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1211,18 +1211,19 @@
         </body>
       </method>
 
       <method name="warnAboutClosingTabs">
       <parameter name="aAll"/>
       <body>
         <![CDATA[
           var tabsToClose = this.tabs.length;
+
           if (!aAll)
-            --tabsToClose;
+            tabsToClose -= 1 + gBrowser._numPinnedTabs;
           if (tabsToClose <= 1)
             return true;
 
           const pref = "browser.tabs.warnOnClose";
           var shouldPrompt = Services.prefs.getBoolPref(pref);
 
           if (!shouldPrompt)
             return true;
@@ -1259,21 +1260,24 @@
         ]]>
       </body>
       </method>
 
       <method name="removeAllTabsBut">
         <parameter name="aTab"/>
         <body>
           <![CDATA[
+            if (aTab.pinned)
+              return;
+
             if (this.warnAboutClosingTabs(false)) {
               this.selectedTab = aTab;
 
               for (let i = this.tabs.length - 1; i >= 0; --i) {
-                if (this.tabs[i] != aTab)
+                if (this.tabs[i] != aTab && !this.tabs[i].pinned)
                   this.removeTab(this.tabs[i]);
               }
             }
           ]]>
         </body>
       </method>
 
       <method name="removeCurrentTab">
@@ -2304,17 +2308,18 @@
   </binding>
 
   <binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox-clicktoscroll">
     <implementation>
       <!-- Override scrollbox.xml method, since our scrollbox's children are
            inherited from the binding parent -->
       <method name="_getScrollableElements">
         <body><![CDATA[
-          return document.getBindingParent(this).childNodes;
+          return Array.filter(document.getBindingParent(this).childNodes,
+                              this._canScrollToElement, this);
         ]]></body>
       </method>
       <method name="_canScrollToElement">
         <parameter name="tab"/>
         <body>
           return !tab.pinned;
         </body>
       </method>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -131,27 +131,27 @@ endif
                  browser_bug537474.js \
                  browser_bug550565.js \
                  browser_bug553455.js \
                  browser_bug555224.js \
                  browser_bug555767.js \
                  browser_bug556061.js \
                  browser_bug562649.js \
                  browser_bug563588.js \
+                 browser_bug577121.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_discovery.js \
                  browser_drag.js \
                  browser_gestureSupport.js \
                  browser_getshortcutoruri.js \
                  browser_inspector_initialization.js \
                  browser_inspector_treeSelection.js \
                  browser_inspector_highlighter.js \
                  browser_inspector_stylePanel.js \
-                 browser_overflowScroll.js \
                  browser_pageInfo.js \
                  browser_page_style_menu.js \
                  browser_pinnedTabs.js \
                  browser_plainTextLinks.js \
                  browser_pluginnotification.js \
                  browser_popupUI.js \
                  browser_relatedTabs.js \
                  browser_sanitize-passwordDisabledHosts.js \
@@ -176,18 +176,28 @@ endif
                  zoom_test.html \
                  dummy_page.html \
                  browser_tabMatchesInAwesomebar.js \
                  file_bug550565_popup.html \
                  file_bug550565_favicon.ico \
     $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-_BROWSER_FILES += browser_bug462289.js
+_BROWSER_FILES += \
+		browser_bug462289.js \
+		$(NULL)
 else
-_BROWSER_FILES += browser_customize.js
+_BROWSER_FILES += \
+		browser_customize.js \
+		$(NULL)
+endif
+
+ifneq (gtk2,$(MOZ_WIDGET_TOOLKIT))
+_BROWSER_FILES += \
+		browser_overflowScroll.js \
+		$(NULL)
 endif
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug577121.js
@@ -0,0 +1,56 @@
+/* ***** 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 bug 577121 test.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael Kohler <michaelkohler@live.com>.
+ * 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 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 ***** */
+
+function test() {
+  // Open 2 other tabs, and pin the second one. Like that, the initial tab
+  // should get closed.
+  let testTab1 = gBrowser.addTab();
+  let testTab2 = gBrowser.addTab();
+  gBrowser.pinTab(testTab2);
+
+  // Now execute "Close other Tabs" on the first manually opened tab (tab1).
+  // -> tab2 ist pinned, tab1 should remain open and the initial tab should
+  // get closed.
+  gBrowser.removeAllTabsBut(testTab1);
+
+  is(gBrowser.tabs.length, 2, "there are two remaining tabs open");
+  is(gBrowser.tabs[0], testTab2, "pinned tab2 stayed open");
+  is(gBrowser.tabs[1], testTab1, "tab1 stayed open");
+  
+  // Cleanup. Close only one tab because we need an opened tab at the end of
+  // the test.
+  gBrowser.removeTab(testTab2);
+}
--- a/browser/base/content/test/browser_overflowScroll.js
+++ b/browser/base/content/test/browser_overflowScroll.js
@@ -1,85 +1,82 @@
-var tabContainer = gBrowser.tabContainer;
-var tabstrip = tabContainer.mTabstrip;
+var tabstrip = gBrowser.tabContainer.mTabstrip;
 var scrollbox = tabstrip._scrollbox;
 var originalSmoothScroll = tabstrip.smoothScroll;
+var tabs = gBrowser.tabs;
 
 function rect(ele)           ele.getBoundingClientRect();
 function width(ele)          rect(ele).width;
 function left(ele)           rect(ele).left;
 function right(ele)          rect(ele).right;
 function isLeft(ele, msg)    is(left(ele), left(scrollbox), msg);
 function isRight(ele, msg)   is(right(ele), right(scrollbox), msg);
 function elementFromPoint(x) tabstrip._elementFromPoint(x);
 function nextLeftElement()   elementFromPoint(left(scrollbox) - 1);
 function nextRightElement()  elementFromPoint(right(scrollbox) + 1);
+function firstScrollable()   tabs[gBrowser._numPinnedTabs];
 
 function test() {
-  if (TabsOnTop.enabled) {
-    todo(false, "need to figure out why this doesn't work with tabs on top on OS X and Windows 7 (bug 575748)");
-    return;
-  }
-
   waitForExplicitFinish();
 
   // If the previous (or more) test finished with cleaning up the tabs,
   // there may be some pending animations. That can cause a failure of
   // this tests, so, we should test this in another stack.
   setTimeout(doTest, 0);
 }
 
 function doTest() {
   tabstrip.smoothScroll = false;
 
   var tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
   var tabCountForOverflow = Math.ceil(width(tabstrip) / tabMinWidth * 3);
-  while (tabContainer.childNodes.length < tabCountForOverflow)
+  while (tabs.length < tabCountForOverflow)
     gBrowser.addTab("about:blank", {skipAnimation: true});
+  gBrowser.pinTab(tabs[0]);
 
   tabstrip.addEventListener("overflow", runOverflowTests, false);
 }
 
 function runOverflowTests(aEvent) {
   if (aEvent.detail != 1)
     return;
 
   tabstrip.removeEventListener("overflow", runOverflowTests, false);
 
   var upButton = tabstrip._scrollButtonUp;
   var downButton = tabstrip._scrollButtonDown;
   var element;
 
-  gBrowser.selectedTab = tabContainer.firstChild;
-  isLeft(tabContainer.firstChild, "Selecting the first tab scrolls it into view");
+  gBrowser.selectedTab = firstScrollable();
+  isLeft(firstScrollable(), "Selecting the first tab scrolls it into view");
 
   element = nextRightElement();
-  EventUtils.synthesizeMouse(downButton, 0, 0, {});
+  EventUtils.synthesizeMouse(downButton, 1, 1, {});
   isRight(element, "Scrolled one tab to the right with a single click");
 
-  gBrowser.selectedTab = tabContainer.lastChild;
-  isRight(tabContainer.lastChild, "Selecting the last tab scrolls it into view");
+  gBrowser.selectedTab = tabs[tabs.length - 1];
+  isRight(gBrowser.selectedTab, "Selecting the last tab scrolls it into view");
 
   element = nextLeftElement();
-  EventUtils.synthesizeMouse(upButton, 0, 0, {});
+  EventUtils.synthesizeMouse(upButton, 1, 1, {});
   isLeft(element, "Scrolled one tab to the left with a single click");
 
   element = elementFromPoint(left(scrollbox) - width(scrollbox));
-  EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 2});
+  EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 2});
   isLeft(element, "Scrolled one page of tabs with a double click");
 
-  EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 3});
-  isLeft(tabContainer.firstChild, "Scrolled to the start with a triple click");
+  EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 3});
+  isLeft(firstScrollable(), "Scrolled to the start with a triple click");
 
   for (var i = 2; i; i--)
-    EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: -1});
-  isLeft(tabContainer.firstChild, "Remained at the start with the mouse wheel");
+    EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: -1});
+  isLeft(firstScrollable(), "Remained at the start with the mouse wheel");
 
   element = nextRightElement();
-  EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: 1});
+  EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: 1});
   isRight(element, "Scrolled one tab to the right with the mouse wheel");
 
-  while (tabContainer.childNodes.length > 1)
-    gBrowser.removeTab(tabContainer.lastChild);
+  while (tabs.length > 1)
+    gBrowser.removeTab(tabs[0]);
 
   tabstrip.smoothScroll = originalSmoothScroll;
   finish();
 }
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -177,18 +177,18 @@ function runTest(testNum) {
                           "context-viewsource",   true,
                           "context-viewinfo",     true]);
         closeContextMenu();
         openContextMenuFor(link); // Invoke context menu for next test.
         break;
 
     case 3:
         // Context menu for text link
-        checkContextMenu(["context-openlink",      true,
-                          "context-openlinkintab", true,
+        checkContextMenu(["context-openlinkintab", true,
+                          "context-openlink",      true,
                           "---",                   null,
                           "context-bookmarklink",  true,
                           "context-savelink",      true,
                           "context-sendlink",      true,
                           "context-copylink",      true]);
         closeContextMenu();
         openContextMenuFor(mailto); // Invoke context menu for next test.
         break;
@@ -298,18 +298,18 @@ function runTest(testNum) {
                           "context-bookmarkpage", true,
                           "context-savepage",     true,
                           "context-sendpage",     true,
                           "---",                  null,
                           "context-viewbgimage",  false,
                           "context-selectall",    true,
                           "frame",                null,
                               ["context-showonlythisframe", true,
+                               "context-openframeintab",    true,
                                "context-openframe",         true,
-                               "context-openframeintab",    true,
                                "---",                       null,
                                "context-reloadframe",       true,
                                "---",                       null,
                                "context-bookmarkframe",     true,
                                "context-saveframe",         true,
                                "---",                       null,
                                "context-printframe",        true,
                                "---",                       null,
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -549,19 +549,19 @@ FeedWriter.prototype = {
    * @param aURL
    *        The URL string from which to create a display name
    * @returns a string
    */
   _getURLDisplayName: function FW__getURLDisplayName(aURL) {
     var url = makeURI(aURL);
     url.QueryInterface(Ci.nsIURL);
     if (url == null || url.fileName.length == 0)
-      return aURL;
+      return decodeURIComponent(aURL);
 
-    return decodeURI(url.fileName);
+    return decodeURIComponent(url.fileName);
   },
 
   /**
    * Takes a FeedEntry with enclosures, generates the HTML code to represent
    * them, and returns that.
    * @param   entry
    *          FeedEntry with enclosures
    * @returns element
--- a/browser/components/feeds/test/Makefile.in
+++ b/browser/components/feeds/test/Makefile.in
@@ -50,13 +50,15 @@ DIRS = \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =	test_bug408328.html \
 		bug408328-data.xml \
 		test_bug368464.html \
 		bug368464-data.xml \
+		test_bug494328.html \
+		bug494328-data.xml \
 		test_registerHandler.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/feeds/test/bug494328-data.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rss version="2.0">
+  <channel>
+    <title>Channel title</title>
+    <description>Channel description</description>
+    <link>Channel link</link>
+    <item>
+      <title>Episode 1</title>
+      <enclosure url="http://www.example.com/podcasts/Episode%201" length="0" type="audio/x-m4a" />
+    </item>
+    <item>
+      <title>Episode 2</title>
+      <enclosure url="http://www.example.com/podcasts/Episode%20%232" length="0" type="audio/x-m4a" />
+    </item>
+    <item>
+      <title>Episode 3</title>
+      <enclosure url="http://www.example.com/podcasts/Episode%20%233/" length="0" type="audio/x-m4a" />
+    </item>
+    <item>
+      <title>Episode 4</title>
+      <enclosure url="http://www.example.com/podcasts/Is%20This%20Episode%20%234%3F" length="0" type="audio/x-m4a" />
+    </item>
+  </channel>
+</rss>
new file mode 100644
--- /dev/null
+++ b/browser/components/feeds/test/test_bug494328.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=494328
+-->
+<head>
+  <title>Test for bug 494328</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <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=494328">Mozilla Bug 494328</a>
+<p id="display"><iframe id="testFrame" src="bug494328-data.xml"></iframe></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 494328 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
+  var links = $("testFrame").contentDocument.getElementById("feedContent").querySelectorAll("div.enclosure > a");
+  is(links[0].textContent, "Episode 1", "filename decoded incorrectly");
+  is(links[1].textContent, "Episode #2", "filename decoded incorrectly");
+  is(links[2].textContent, "http://www.example.com/podcasts/Episode #3/", "filename decoded incorrectly");
+  is(links[3].textContent, "Is This Episode #4?", "filename decoded incorrectly");
+});
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -129,22 +129,16 @@
              onpopuphiding="this._view.destroyContextMenu();">
     <menuitem id="placesContext_open"
               command="placesCmd_open"
               label="&cmd.open.label;"
               accesskey="&cmd.open.accesskey;"
               default="true"
               selectiontype="single"
               selection="link"/>
-    <menuitem id="placesContext_open:newwindow"
-              command="placesCmd_open:window"
-              label="&cmd.open_window.label;"
-              accesskey="&cmd.open_window.accesskey;"
-              selectiontype="single"
-              selection="link"/>
     <menuitem id="placesContext_open:newtab"
               command="placesCmd_open:tab"
               label="&cmd.open_tab.label;"
               accesskey="&cmd.open_tab.accesskey;"
               selectiontype="single"
               selection="link"/>
     <menuitem id="placesContext_openContainer:tabs"
               oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
@@ -157,16 +151,22 @@
     <menuitem id="placesContext_openLinks:tabs"
               oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
                          view.controller.openSelectionInTabs(event);"
               onclick="checkForMiddleClick(this, event);"
               label="&cmd.open_all_in_tabs.label;"
               accesskey="&cmd.open_all_in_tabs.accesskey;"
               selectiontype="multiple"
               selection="link"/>
+    <menuitem id="placesContext_open:newwindow"
+              command="placesCmd_open:window"
+              label="&cmd.open_window.label;"
+              accesskey="&cmd.open_window.accesskey;"
+              selectiontype="single"
+              selection="link"/>
     <menuseparator id="placesContext_openSeparator"/>
     <menuitem id="placesContext_new:bookmark"
               command="placesCmd_new:bookmark"
               label="&cmd.new_bookmark.label;"
               accesskey="&cmd.new_bookmark.accesskey;"
               selection="any"
               hideifnoinsertionpoint="true"/>
     <menuitem id="placesContext_new:folder"
--- a/browser/components/places/tests/browser/browser_history_sidebar_search.js
+++ b/browser/components/places/tests/browser/browser_history_sidebar_search.js
@@ -124,16 +124,22 @@ function continue_test() {
   }, true);
   toggleSidebar("viewHistorySidebar", true);
 }
 
 function check_sidebar_tree_order(aExpectedRows) {
   var tree = sidebar.contentDocument.getElementById("historyTree");
   var treeView = tree.view;
   var rc = treeView.rowCount;
-  is(rc, aExpectedRows, "All expected tree rows are present");
   var columns = tree.columns;
   is(columns.count, 1, "There should be only 1 column in the sidebar");
+  var found = 0;
   for (var r = 0; r < rc; r++) {
     var node = treeView.nodeForTreeIndex(r);
+    // We could inherit visits from previous tests, skip them since they are
+    // not interesting for us.
+    if (pages.indexOf(node.uri) == -1)
+      continue;
     is(node.uri, pages[r], "Node is in correct position based on its visit date");
+    found++;
   }
+  ok(found, aExpectedRows, "Found all expected results");
 }
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1010,23 +1010,23 @@ SessionStoreService.prototype = {
     
     // fetch the data of closed tab, while removing it from the array
     let closedTab = closedTabs.splice(aIndex, 1).shift();
     let closedTabState = closedTab.state;
 
     // create a new tab
     let browser = aWindow.gBrowser;
     let tab = browser.addTab();
+
+    // restore tab content
+    this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
       
     // restore the tab's position
     browser.moveTabTo(tab, closedTab.pos);
 
-    // restore tab content
-    this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
-
     // focus the tab's content area
     let content = browser.getBrowserForTab(tab).contentWindow;
     aWindow.setTimeout(function() { content.focus(); }, 0);
     
     return tab;
   },
 
   forgetClosedTab: function sss_forgetClosedTab(aWindow, aIndex) {
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -109,12 +109,13 @@ include $(topsrcdir)/config/rules.mk
 	browser_491577.js \
 	browser_493467.js \
 	browser_495495.js \
 	browser_500328.js \
 	browser_514751.js \
 	browser_522545.js \
 	browser_524745.js \
 	browser_528776.js \
+	browser_579879.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_579879.js
@@ -0,0 +1,21 @@
+function test() {
+  waitForExplicitFinish();
+
+  var tab1 = gBrowser.addTab("data:text/plain,foo");
+  gBrowser.pinTab(tab1);
+
+  tab1.linkedBrowser.addEventListener("load", function () {
+    var tab2 = gBrowser.addTab();
+    gBrowser.pinTab(tab2);
+
+    is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 is at the first position");
+    gBrowser.removeTab(tab1);
+    tab1 = undoCloseTab();
+    ok(tab1.pinned, "pinned tab 1 has been restored as a pinned tab");
+    is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 has been restored to the first position");
+
+    gBrowser.removeTab(tab1);
+    gBrowser.removeTab(tab2);
+    finish();
+  }, true);
+}
--- a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm
+++ b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm
@@ -365,16 +365,17 @@ PreviewController.prototype = {
     }
   }
 };
 
 XPCOMUtils.defineLazyGetter(PreviewController.prototype, "canvasPreviewFlags",
   function () { let canvasInterface = Ci.nsIDOMCanvasRenderingContext2D;
                 return canvasInterface.DRAWWINDOW_DRAW_VIEW
                      | canvasInterface.DRAWWINDOW_DRAW_CARET
+                     | canvasInterface.DRAWWINDOW_ASYNC_DECODE_IMAGES
                      | canvasInterface.DRAWWINDOW_DO_NOT_FLUSH;
 });
 
 ////////////////////////////////////////////////////////////////////////////////
 //// TabWindow
 
 /*
  * This class monitors a browser window for changes to its tabs
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-4.0b2pre
+4.0b3pre
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -7,18 +7,16 @@
 <!ENTITY mainWindow.titlemodifier "&brandFullName;">
 <!-- LOCALIZATION NOTE (mainWindow.titlemodifiermenuseparator): DONT_TRANSLATE -->
 <!ENTITY mainWindow.titlemodifiermenuseparator " - ">
 <!-- LOCALIZATION NOTE (mainWindow.titlePrivateBrowsingSuffix): This will be appended to the window's title
                                                                 inside the private browsing mode -->
 <!ENTITY mainWindow.titlePrivateBrowsingSuffix "(Private Browsing)">
 
 <!-- Tab context menu -->
-<!ENTITY  newTab.label                       "New Tab">
-<!ENTITY  newTab.accesskey                   "N">
 <!ENTITY  reloadTab.label                    "Reload Tab">
 <!ENTITY  reloadTab.accesskey                "R">
 <!ENTITY  reloadAllTabs.label                "Reload All Tabs">
 <!ENTITY  reloadAllTabs.accesskey            "A">
 <!ENTITY  closeOtherTabs.label               "Close Other Tabs">
 <!ENTITY  closeOtherTabs.accesskey           "o">
 <!ENTITY  openTabInNewWindow.label           "Open in a New Window">
 <!ENTITY  openTabInNewWindow.accesskey       "W">
@@ -164,19 +162,19 @@
 <!ENTITY downloadsUnix.commandkey     "y">
 <!ENTITY addons.label                 "Add-ons">
 <!ENTITY addons.accesskey             "A">
 
 <!ENTITY errorConsoleCmd.label        "Error Console">
 <!ENTITY errorConsoleCmd.accesskey    "C">
 <!ENTITY errorConsoleCmd.commandkey   "j">
 
-<!ENTITY hudConsoleCmd.label          "Heads Up Display">
-<!ENTITY hudConsoleCmd.accesskey      "U">
-<!ENTITY hudConsoleCmd.commandkey     "k">
+<!ENTITY webConsoleCmd.label          "Web Console">
+<!ENTITY webConsoleCmd.accesskey      "W">
+<!ENTITY webConsoleCmd.commandkey     "k">
 
 <!ENTITY inspectMenu.label            "Inspect">
 <!ENTITY inspectMenu.accesskey        "T">
 <!ENTITY inspectMenu.commandkey       "I">
 
 <!ENTITY inspectButton.label          "Inspect">
 <!ENTITY inspectButton.accesskey      "I">
 <!ENTITY inspectNextButton.label      "Next">
@@ -283,26 +281,26 @@
 
   Do *not* tamper with these values without talking to ben@mozilla.org
 
  -->
 <!ENTITY searchFocus.commandkey       "k">
 <!ENTITY searchFocus.commandkey2      "e">
 <!ENTITY searchFocusUnix.commandkey   "j">
 
+<!ENTITY openLinkCmdInTab.label       "Open Link in New Tab">
+<!ENTITY openLinkCmdInTab.accesskey   "T">
 <!ENTITY openLinkCmd.label            "Open Link in New Window">
 <!ENTITY openLinkCmd.accesskey        "W">
 <!ENTITY openLinkCmdInCurrent.label     "Open Link">
 <!ENTITY openLinkCmdInCurrent.accesskey "O">
-<!ENTITY openLinkCmdInTab.label       "Open Link in New Tab">
-<!ENTITY openLinkCmdInTab.accesskey   "T">
+<!ENTITY openFrameCmdInTab.label      "Open Frame in New Tab">
+<!ENTITY openFrameCmdInTab.accesskey  "T">
 <!ENTITY openFrameCmd.label           "Open Frame in New Window">
 <!ENTITY openFrameCmd.accesskey       "W">
-<!ENTITY openFrameCmdInTab.label      "Open Frame in New Tab">
-<!ENTITY openFrameCmdInTab.accesskey  "T">
 <!ENTITY showOnlyThisFrameCmd.label     "Show Only This Frame">
 <!ENTITY showOnlyThisFrameCmd.accesskey "S">
 <!ENTITY reloadCmd.commandkey         "r">
 <!ENTITY reloadFrameCmd.label         "Reload Frame">
 <!ENTITY reloadFrameCmd.accesskey     "R">
 <!ENTITY viewPartialSourceForSelectionCmd.label "View Selection Source">
 <!ENTITY viewPartialSourceForMathMLCmd.label    "View MathML Source">
 <!-- LOCALIZATION NOTE (viewPartialSourceCmd.accesskey): This accesskey is used for both 
--- a/browser/locales/en-US/chrome/browser/openLocation.dtd
+++ b/browser/locales/en-US/chrome/browser/openLocation.dtd
@@ -1,10 +1,10 @@
 <!-- extracted from content/openLocation.xul -->
 
 <!ENTITY enter.label "Enter the web location (URL), or specify the local file you would like to open:">  
 <!ENTITY chooseFile.label "Choose Fileā€¦">
+<!ENTITY newTab.label "New Tab">
 <!ENTITY newWindow.label "New Window">
-<!ENTITY newTab.label "New Tab">
 <!ENTITY topTab.label "Current Tab">
 <!ENTITY caption.label "Open Web Location">
 <!ENTITY openWhere.label "Open in:">
 <!ENTITY openBtn.label "Open">
--- a/browser/locales/en-US/chrome/browser/search.properties
+++ b/browser/locales/en-US/chrome/browser/search.properties
@@ -1,10 +1,10 @@
 searchtip=Search using %S
 
 cmd_clearHistory=Clear Search History
-cmd_clearHistory_accesskey=C
+cmd_clearHistory_accesskey=H
 
 cmd_showSuggestions=Show Suggestions
 cmd_showSuggestions_accesskey=S
 
 cmd_addFoundEngine=Add "%S"
 
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1250,25 +1250,16 @@ statusbarpanel#statusbar-display {
 }
 .tabbrowser-tab[busy][progress="7"] > .tab-icon-image {
   -moz-image-region: rect(0, 128px, 16px, 112px);
 }
 .tabbrowser-tab[busy][progress="8"] > .tab-icon-image {
   -moz-image-region: rect(0, 144px, 16px, 128px);
 }
 
-#context_newTab {
-  list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-  -moz-image-region: rect(0px 64px 16px 48px);
-}
-
-#context_newTab[disabled] {
-  -moz-image-region: rect(16px 64px 32px 48px);
-}
-
 #context_reloadTab {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
 }
 
 #context_closeOtherTabs {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
 }
 
--- a/browser/themes/gnomestripe/browser/pageInfo.css
+++ b/browser/themes/gnomestripe/browser/pageInfo.css
@@ -169,16 +169,22 @@ groupbox.treebox .groupbox-body {
   white-space: pre-wrap;
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
   margin-top: 2px;
+  margin-bottom: 0;
+}
+
+#mediaSplitter {
+  -moz-appearance: none;
+  height: .8em;
 }
 
 #mediaGrid {
   min-height: 9em;
 }
 
 #mediaLabelColumn {
   min-width: 10em;
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -132,17 +132,16 @@
   border-bottom-color: rgba(0, 0, 0, 0.32);
 }
 
 #navigator-toolbox[tabsontop="true"] > #nav-bar,
 #navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
 #navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
   padding-top: 4px !important;
   background-image: -moz-linear-gradient(rgba(255,255,255,.58), rgba(255,255,255,0)) !important; /* override lwtheme style */
-  -moz-background-origin: border !important;
 }
 
 /* ----- BOOKMARK TOOLBAR ----- */
 
 #personal-bookmarks {
   min-height: 17px; /* 16px button height + 1px margin-bottom */
 }
 
--- a/browser/themes/pinstripe/browser/pageInfo.css
+++ b/browser/themes/pinstripe/browser/pageInfo.css
@@ -117,16 +117,21 @@ groupbox.treebox .groupbox-body {
 #general-security-identity {
   white-space: pre-wrap;
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
+  margin-bottom: 0;
+}
+
+#mediaSplitter {
+  background: none;
 }
 
 #mediaGrid {
   min-height: 9em;
 }
 
 #mediaLabelColumn {
   min-width: 10em;
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -34,34 +34,34 @@
   }
 
   #main-window:not(:-moz-lwtheme)[inFullscreen="true"] {
     -moz-appearance: none;
     background-color: #556;
   }
 
   #toolbar-menubar:not(:-moz-lwtheme),
-  #navigator-toolbox[tabsontop="true"] > #TabsToolbar:not(:-moz-lwtheme),
-  #navigator-toolbox:not([tabsontop="true"]) > #nav-bar:not(:-moz-lwtheme),
-  #navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child:not(:-moz-lwtheme) {
+  #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme),
+  #navigator-toolbox[tabsontop="false"] > #nav-bar:not(:-moz-lwtheme),
+  #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar[tabsontop="false"]:last-child:not(:-moz-lwtheme) {
     background: transparent !important;
     color: black;
     text-shadow: 0 0 .7em white, 0 0 .7em white, 0 1px 0 rgba(255,255,255,.4);
   }
 
   #navigator-toolbox[tabsontop="true"] > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
     border-left: 1px solid ThreeDShadow;
     border-right: 1px solid ThreeDShadow;
   }
 
   /* Make the window draggable by glassed toolbars (bug 555081) */
   #toolbar-menubar:not([autohide="true"]),
-  #navigator-toolbox[tabsontop="true"] > #TabsToolbar,
-  #navigator-toolbox:not([tabsontop="true"]) > #nav-bar,
-  #navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child,
+  #TabsToolbar[tabsontop="true"],
+  #navigator-toolbox[tabsontop="false"] > #nav-bar,
+  #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar[tabsontop="false"]:last-child,
   #navigator-toolbox > toolbar:not(#toolbar-menubar):-moz-lwtheme {
     -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
   }
 
   #browser:not(:-moz-lwtheme),
   #browser-bottombox:not(:-moz-lwtheme) {
     background-color: -moz-dialog;
   }
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -75,21 +75,22 @@
 }
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar)[iconsize="small"],
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar)[defaulticonsize="small"]:not([iconsize]) {
   padding-top: 1px;
   padding-bottom: 1px;
 }
 
-#nav-bar:not(:-moz-lwtheme) {
+#nav-bar:not(:-moz-lwtheme),
+#navigator-toolbox[tabsontop="true"] > #nav-bar {
   background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
 }
 
-#navigator-toolbox:not([tabsontop="true"]) > #toolbar-menubar:not(:-moz-lwtheme) {
+#navigator-toolbox[tabsontop="false"] > #toolbar-menubar:not(:-moz-lwtheme) {
   background-image: -moz-linear-gradient(@toolbarHighlight@, @toolbarHighlight@);
 }
 
 #personal-bookmarks {
   min-height: 24px;
 }
 
 #print-preview-toolbar:not(:-moz-lwtheme) {
@@ -1081,21 +1082,21 @@ richlistitem[type="action"][actiontype="
 #wrapper-navigator-throbber > #navigator-throbber {
   list-style-image: url("chrome://global/skin/icons/notloading_16.png");
 }
 
 /* Tabstrip */
 #TabsToolbar {
   min-height: 0;
   padding: 0;
-  -moz-box-shadow: 0 -1px ThreeDShadow inset;
 }
 
 #TabsToolbar:not(:-moz-lwtheme),
-#navigator-toolbox:not([tabsontop="true"]) > #TabsToolbar {
+#TabsToolbar[tabsontop="false"] {
+  -moz-box-shadow: 0 -1px ThreeDShadow inset;
   background-image: -moz-linear-gradient(transparent, transparent 10%,
                                          rgba(0,0,0,.03) 50%, rgba(0,0,0,.1) 90%, rgba(0,0,0,.2));
 }
 
 .tabbrowser-tabs:-moz-system-metric(touch-enabled) {
   min-height: .73cm;
 }
 
@@ -1134,46 +1135,47 @@ richlistitem[type="action"][actiontype="
 .tabs-newtab-button:-moz-lwtheme-brighttext:hover {
   background-image: -moz-linear-gradient(left, transparent, transparent 1px,
                                                rgba(60%,60%,60%,.6) 1px, rgba(60%,60%,60%,.6));
 }
 
 .tabbrowser-tab:-moz-lwtheme-darktext,
 .tabs-newtab-button:-moz-lwtheme-darktext {
   background-image: -moz-linear-gradient(left, transparent, transparent 1px,
-                                               rgba(255,255,255,.4) 1px, rgba(255,255,255,.4));
+                                               rgba(60%,60%,60%,.5) 1px, rgba(60%,60%,60%,.5));
 }
 
 .tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover,
 .tabs-newtab-button:-moz-lwtheme-darktext:hover {
   background-image: -moz-linear-gradient(left, transparent, transparent 1px,
-                                               rgba(255,255,255,.6) 1px, rgba(255,255,255,.6));
+                                               rgba(80%,80%,80%,.5) 1px, rgba(80%,80%,80%,.5));
 }
 
-.tabbrowser-tab[selected="true"] {
+.tabbrowser-tab[selected="true"]:-moz-lwtheme {
+  background-image: -moz-linear-gradient(left, transparent, transparent 1px,
+                                               @toolbarHighlight@ 1px, @toolbarHighlight@);
+}
+
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
   background-image: -moz-linear-gradient(left, transparent, transparent 1px, white 1px, white);
   color: black;
 }
 
-#navigator-toolbox[tabsontop="true"] > #TabsToolbar > #tabbrowser-tabs > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
+#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
   background-image: -moz-radial-gradient(center top, white, rgba(255,255,255,0) 60%),
                     -moz-linear-gradient(left, transparent, transparent 1px,
                                                @toolbarHighlight@ 1px, @toolbarHighlight@),
                     -moz-linear-gradient(left, transparent, transparent 1px,
                                                -moz-dialog 1px, -moz-dialog);
   background-position: center -2px, -6px -2px, -6px -2px;
   background-size: 100%, 200%, 200%;
   color: -moz-dialogText;
 }
 
-.tabbrowser-tab:-moz-lwtheme[selected="true"] {
-  text-shadow: none;
-}
-
-.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) {
+.tabbrowser-tab:-moz-lwtheme {
   color: inherit;
 }
 
 .tabbrowser-tab[busy] > .tab-icon-image {
   list-style-image: url("chrome://browser/skin/tabbrowser/progress.png") !important;
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 .tabbrowser-tab[busy][stalled] > .tab-icon-image {
index afedf0b0e126516ef1012a0b3d19d3c55e7a551f..79e332945192802356a7b83cea7e21c91120e9d1
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0006xNkl<ZILnQb
z%}Z2K7{-5hW<q0(F%6_CBB`uZSxQzGC<MtE8AUBB(x7M;t=iQxXxm1i56aL#AgOGX
z3k{PH5dxzUmFPpANk?bKnK|cuTin~#+sYTt?s<OaeICwnRF$dWEALR6SkE{NR3GhW
z22fQZ0LDmDb^T4i@l*;bpo(Ha6>v}$rpKNKE{XtHtFBG5o>);84<e{qR4oo+UmE}z
zBkt{<8Q*L@v!H4K^|b#1ism2HTiY|C78MI>K@95X8m&7aH-c;IzjubA&f84%KP59a
zgNgw)s1&_pP*py@I=?vpFkY@i$7$-0R8f}hXT19kQ}6o_n@3C*wFPp?aa_Gj4!=Ct
zu?jG5QA=hg;T;!=pMAlxwie9iUPikgP|W<snk;4|3BZ99*UF1VIs+w&HB7&G$igBx
z(XH&iaGgD;;w*mXVshXuyH2+Gxh4M-Yos&~K~0XD_AVN(-lDc<g|R31Nt-fa`&x)C
zjF6rE;R9?T<;V6*RLPN^{YG+r38&#Mjg3`I_VtpfI81dsOzP8UpnYp)%|jAJZJsYZ
zU6imy_IMjr+gjQC{Skj=CWuCBh|YZlcCP{?uz?~{<WTcL>S`;9#kW(~R7tE9Y-*mg
zDW@Ww_RU3O5z*z~22#M*UMA~oprr5%v3ZsgkJ*x+LvhghOOP4?U~ph)VPk3d27sfg
z^gT-qS|g3?`HYc>GZG4g60Pm8ld9?h9LK2y%7O4Y7+D|#tf*@4FKTdNl?~9UGynhq
M07*qoM6N<$f@CfgNdN!<
index 00b9f55be2147a9bfe0bddd002fe2b4edfcd776f..38a4f105587f772957310c2538f4af2d4e4bc79a
GIT binary patch
literal 680
zc$@*K0$2TsP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0007SNkl<ZILoDy
zUue!@6vsc$@BOjaYa6o-^KX-F5~3mHPnmL|Hbt2zg<QDBjiks8x#7ZvBwP>|NQsm}
z%EctoG_hqV%ihiQZhN=)eV^a+oa5s6=1-L3Tc`8X`JVH9&*^JamH$E5exsG?GfNI;
zMx)ar8va}~#>nK-38zwD#*Z#-s`{<Dxc(BR`_cBA^icle;^w^*jSQf!|2sj0YC4|W
zjiy!>)y{9e+50C2rswI7ciu_kzsOI7!TT^f?i%YioFGV4pa>wKg+M@kobjLz6fla~
z6kX3RG=$CyCQ*h&A3!}1j%}oD#sVtpmM~|<W|EaPKL)A*3dRs5s<2iGto0zSK(K7y
z(@N9oYLdhEczyW*AD`U>p9RT*WKqeYK8I>VWIcg%5=)ajDwd3^C9K`a+-<j6yLAh;
z^9nDnp2SCEsN_NN;K#s?;UXmz0mP!32eI_rKTCQTg3>uO?K;fDmRbg%o#Dg7>ojiK
z25M0^f_M;B0&#+BE}krT7VW>rntexDwqTt0^M}a#B-0kRP}28^(cTUu8bAvnUJ2r3
zkAu%5K0_we$xwfaqV>mFw{|-3Ze7Gyucodhr2oy!_#^eG=1{K$BA{*vi3TA`^Y+R)
zdhT4J_tj(UycX)qK9l~`i7#!SWVoxat^>&;0--A4(uFHqRyHqZ!q*N)XU&H4a>|Qg
zWT20+u!1Q;7f2L)LoDKzP`n~hADBt8HJ7*H%x;S97Z8hUy~qsLkCMQwYD03}7)_v(
zL)Bo~uWjkgj6^dF?gvca85`!89GI9=K(aJU86XK10TX|8{}l>YApZ@v-C_moQfBu6
O0000<MNUMnLSTZ1@JT=b
--- a/browser/themes/winstripe/browser/pageInfo.css
+++ b/browser/themes/winstripe/browser/pageInfo.css
@@ -183,16 +183,23 @@ groupbox tree {
 #general-security-identity {
   white-space: pre-wrap;
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
+  margin-bottom: 0;
+}
+
+#mediaSplitter {
+  border-style: none;
+  background: none;
+  height: .8em;
 }
 
 #mediaGrid {
   min-height: 9em;
 }
 
 #mediaLabelColumn {
   min-width: 10em;
index 75246969787375beda44aa39204227ebf07926bf..fff0fb014c2c2a2acb3efd38a6d174634f8e9636
GIT binary patch
literal 602
zc$@)R0;T<lP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0006ZNkl<ZILnQb
zzfV(f6vaQUuRu)=g3cytg1RACsfYqD4no)wqLZtMvwwoC(ZtDFjVnY6lxQ@8m_R~w
zAy}f67LckG`^x*?dmUbX(8Ph8e7AGYIXU-yJu~CM>y<e?hB?X@ndg(Kn*c!&5C;%(
z!*{P<Xu_$1c_2<P!1F-Wc=>s?Nhl6rDgczj2n-Qe0X0K3dcN<~u}uUjQgzo*SEw)6
zNbnliW(N{R1QwATgpTRC42w%k7|`3@&CtMgT8P)NwTVR;NL4vfnwp(uWj)8}=olj-
zV|>YO@@{?}QN_%deEPQYzZs~3sIr>h;nv_adb-XMilPSZ7Z&-tQ=(EX;m6z7CZ0?^
z1YX3V3>>0{QzZ~1*?yATW`S%m;M;DQANf4V_D*)ok^S+(-VPP_tP!FLPL-{_3S!2I
z<HuNBUZ$|Ujhd0o<rwPk$5m}_?>kf_aVSJbAc|8XlbIpAS>W`Ub8LKH2ZMC#3K!3J
zv9h%fK(QQR;u;x<2tlaK%uKVownnNi&A^q*#9}uPg}uP>r=m^i*Mg56IANz)B$v<8
zmrj$q)WgQ_3R3HW8OavExzSFVuaHc(b8q4f_^lL5VYCQH^|Vf{p&mNSv~-9-sfZGK
ztyB(-M2laqvZ&VESes7^AAk96iTePanKAzO)dy7>ILc@AV*Wxb7Q6lC(ZtUn2qJ<+
oB5?}n0Q@6x`~~)--yD?x0bEIFqxiCuxc~qF07*qoM6N<$g5=2=PXGV_
index 40b8db754af4693edc2bc2b7cd7befcbb1ac444d..c06025e62c3d6d362d6973b1f2b691afac32997a
GIT binary patch
literal 615
zc$@)e0+{`YP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0006mNkl<ZILoDz
z&r6hH5XV2yyU*&frKCYb1W8E|6{eV$Nm<d&Lx-S~;VI~^=@@jXQ`D_fA*dMUCLwl-
zsDtDW+*Kn@O?Th-nVAl|tFCwmdSGCfdFDIweZKQJGvj}bfADM^U{FKyR8=y2lTnl^
zMn3%*c>d~9@4)~r<(o8wCxf@UGKD`<lRSPXm3c8X{Uq}K4X}C;fE#@M?L$K*eWBh*
z^?T_UZr88G9pGF!9tSCHl)@LU5_;}mY{3EMss&)|nuzWAt^%fzc{w%H<5dC<h{Z^>
zIv0cx7#bbr)8}an=xA%FulFXnsLZ`CLM7l;Vw|gVbLBBbjdvr%e4WkH-+vD?V|YAA
zA|u@DyHjqGC@L{t;sgWK%7s<VGx-(n-ndTNxictWk>h=ClDKlGWQvL6RYDC{1%evc
z#%2mD%N#p#ibR#g{4&|bW;WwmrM!liAj(EbSStxy0ctp$WnyZY`TPosF}JWl&$S-5
zcOGg7AYogS^;q~F3mAMH8)Bib#L1S^<mYEGgU&16w6>mQQ*0lA3Y&=$tC5J38+psz
zj~UuKuhQMsNh*pEjP-5dXHiM{s20FPC?-NND8E+MSSl=XxwD%~?H$anB?zEq1ToT)
zqi+8ys|1RP;2a!nKElI+0bIJC<&A)k9I5iskOExf2s=uZx6(V99GS?S_ukiuD(O^2
z92E9!B^8x0qpE?bCT8~C0Zl-*V(uS*u>o7a)?ZETJ9rocp?m-U002ovPDHLkV1iu+
B7}o#*
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -34,16 +34,17 @@
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 import time
 import sys
 import os
+import socket
 
 from automation import Automation
 from devicemanager import DeviceManager
 
 class RemoteAutomation(Automation):
     _devicemanager = None
     
     def __init__(self, deviceManager, appName = ''):
@@ -88,16 +89,42 @@ class RemoteAutomation(Automation):
         try:
             args.remove('-foreground')
         except:
             pass
 #TODO: figure out which platform require NO_EM_RESTART
 #        return app, ['--environ:NO_EM_RESTART=1'] + args
         return app, args
 
+    # Utilities to get the local ip address
+    def getInterfaceIp(self, ifname):
+        if os.name != "nt":
+            import fcntl
+            import struct
+            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+            return socket.inet_ntoa(fcntl.ioctl(
+                                    s.fileno(),
+                                    0x8915,  # SIOCGIFADDR
+                                    struct.pack('256s', ifname[:15])
+                                    )[20:24])
+        else:
+            return None
+
+    def getLanIp(self):
+        ip = socket.gethostbyname(socket.gethostname())
+        if ip.startswith("127.") and os.name != "nt":
+            interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
+            for ifname in interfaces:
+                try:
+                    ip = self.getInterfaceIp(ifname)
+                    break;
+                except IOError:
+                    pass
+        return ip
+
     def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
         return self.RProcess(self._devicemanager, cmd, stdout, stderr, env, cwd)
 
     # be careful here as this inner class doesn't have access to outer class members    
     class RProcess(object):
         # device manager process
         dm = None
         def __init__(self, dm, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
@@ -137,8 +164,9 @@ class RemoteAutomation(Automation):
                     break
 
             if (timer >= timeout):
                 return 1
             return 0
  
         def kill(self):
             self.dm.killProcess(self.procName)
+
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -149,16 +149,17 @@ MOZ_STORAGE = @MOZ_STORAGE@
 MOZ_SAFE_BROWSING = @MOZ_SAFE_BROWSING@
 MOZ_FASTSTART = @MOZ_FASTSTART@
 MOZ_URL_CLASSIFIER = @MOZ_URL_CLASSIFIER@
 MOZ_ZIPWRITER = @MOZ_ZIPWRITER@
 MOZ_MORK = @MOZ_MORK@
 MOZ_MORKREADER = @MOZ_MORKREADER@
 MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@
 MOZ_OGG = @MOZ_OGG@
+MOZ_RAW = @MOZ_RAW@
 MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
 MOZ_WAVE = @MOZ_WAVE@
 MOZ_MEDIA = @MOZ_MEDIA@
 MOZ_VORBIS = @MOZ_VORBIS@
 MOZ_WEBM = @MOZ_WEBM@
 VPX_AS = @VPX_AS@
 VPX_ASFLAGS = @VPX_ASFLAGS@
 VPX_X86_ASM = @VPX_X86_ASM@
--- a/config/config.mk
+++ b/config/config.mk
@@ -318,39 +318,45 @@ STATIC_LIBRARY_NAME=$(LIBRARY_NAME)
 endif
 endif
 
 # This comes from configure
 ifdef MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 
+# No sense in profiling tools
+ifdef INTERNAL_TOOLS
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
+# Don't build SIMPLE_PROGRAMS with PGO, since they don't need it anyway,
+# and we don't have the same build logic to re-link them in the second pass.
+ifdef SIMPLE_PROGRAMS
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
 # Enable profile-based feedback
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_GENERATE
-# No sense in profiling tools
-ifndef INTERNAL_TOOLS
 OS_CFLAGS += $(PROFILE_GEN_CFLAGS)
 OS_CXXFLAGS += $(PROFILE_GEN_CFLAGS)
 OS_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
 ifeq (WINNT,$(OS_ARCH))
 AR_FLAGS += -LTCG
 endif
-endif # INTERNAL_TOOLS
 endif # MOZ_PROFILE_GENERATE
 
 ifdef MOZ_PROFILE_USE
-ifndef INTERNAL_TOOLS
 OS_CFLAGS += $(PROFILE_USE_CFLAGS)
 OS_CXXFLAGS += $(PROFILE_USE_CFLAGS)
 OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
 ifeq (WINNT,$(OS_ARCH))
 AR_FLAGS += -LTCG
 endif
-endif # INTERNAL_TOOLS
 endif # MOZ_PROFILE_USE
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 
 # Does the makefile specifies the internal XPCOM API linkage?
 ifneq (,$(MOZILLA_INTERNAL_API)$(LIBXUL_LIBRARY))
 DEFINES += -DMOZILLA_INTERNAL_API
 endif
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by milestone.pl.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-2.0b2pre
+2.0b3pre
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -462,17 +462,17 @@ XPIDL_GEN_DIR		= _xpidlgen
 ifdef MOZ_UPDATE_XTERM
 # Its good not to have a newline at the end of the titlebar string because it
 # makes the make -s output easier to read.  Echo -n does not work on all
 # platforms, but we can trick sed into doing it.
 UPDATE_TITLE = sed -e "s!Y!$(1) in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2)!" $(MOZILLA_DIR)/config/xterm.str;
 endif
 
 define SUBMAKE # $(call SUBMAKE,target,directory)
-@$(UPDATE_TITLE)
++@$(UPDATE_TITLE)
 +@$(MAKE) $(if $(2),-C $(2)) $(1)
 
 endef # The extra line is important here! don't delete it
 
 ifneq (,$(strip $(DIRS)))
 LOOP_OVER_DIRS = \
   $(foreach dir,$(DIRS),$(call SUBMAKE,$@,$(dir)))
 endif
@@ -573,17 +573,17 @@ endif
 # MacOS X specific stuff
 #
 
 ifeq ($(OS_ARCH),Darwin)
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 EXTRA_DSO_LDOPTS	+= -bundle
 else
-EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name @loader_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
+EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
 endif
 endif
 endif
 
 #
 # On NetBSD a.out systems, use -Bsymbolic.  This fixes what would otherwise be
 # fatal symbol name clashes between components.
 #
@@ -929,17 +929,17 @@ endif
 endif # JAVA_LIBRARY
 endif # !NO_DIST_INSTALL
 	$(LOOP_OVER_DIRS)
 
 ##############################################
 
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_USE
-ifeq ($(OS_ARCH)_$(GNU_CC)$(INTERNAL_TOOLS), WINNT_)
+ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
 # When building with PGO, we have to make sure to re-link
 # in the MOZ_PROFILE_USE phase if we linked in the
 # MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink
 # file in the link rule in the GENERATE phase to indicate
 # that we need a relink.
 ifdef SHARED_LIBRARY
 $(SHARED_LIBRARY): pgo.relink
 endif
@@ -1396,22 +1396,25 @@ host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
+# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
+# 'moc' only knows about #defines it gets on the command line (-D...), not in 
+# included headers like mozilla-config.h
 moc_%.cpp: %.h $(GLOBAL_DEPS)
-	$(MOC) $< $(OUTOPTION)$@ 
+	$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@ 
 
 moc_%.cc: %.cc $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
-	$(ELOG) $(MOC) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
+	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS)
 	$(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
 
@@ -1905,19 +1908,19 @@ chrome::
 	$(MAKE) realchrome
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
 $(FINAL_TARGET)/chrome:
 	$(NSINSTALL) -D $@
 
+libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
 ifneq (,$(wildcard $(JAR_MANIFEST)))
 ifndef NO_DIST_INSTALL
-libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
 	$(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
 	  $(QUIET) -j $(FINAL_TARGET)/chrome \
 	  $(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
 	  $(JAR_MANIFEST)
 endif
 endif
 
 ifneq ($(DIST_FILES),)
--- a/configure.in
+++ b/configure.in
@@ -127,17 +127,17 @@ GTK2_VERSION=2.10.0
 WINDRES_VERSION=2.14.90
 W32API_VERSION=3.8
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 GIO_VERSION=2.0
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
-SQLITE_VERSION=3.6.23.1
+SQLITE_VERSION=3.7.0
 LIBNOTIFY_VERSION=0.4
 
 MSMANIFEST_TOOL=
 
 dnl Set various checks
 dnl ========================================================
 MISSING_X=
 AC_PROG_AWK
@@ -900,17 +900,17 @@ EOF
 
     # If the maximum version supported by this SDK is lower than the target
     # version, error out
     AC_MSG_CHECKING([for Windows SDK being recent enough])
     if $PERL -e "exit(0x$MOZ_WINSDK_TARGETVER > $MOZ_WINSDK_MAXVER)"; then
         AC_MSG_RESULT("yes")
     else
         AC_MSG_RESULT("no")
-        AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.])
+        AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. Alternatively, try running the Windows SDK Configuration Tool and selecting a newer SDK. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.])
     fi
 
     AC_DEFINE_UNQUOTED(MOZ_WINSDK_TARGETVER,0x$MOZ_WINSDK_TARGETVER)
     # Definitions matching sdkddkver.h
     AC_DEFINE_UNQUOTED(MOZ_NTDDI_WS03, 0x05020000)
     AC_DEFINE_UNQUOTED(MOZ_NTDDI_LONGHORN, 0x06000000)
     AC_DEFINE_UNQUOTED(MOZ_NTDDI_WIN7, 0x06010000)
     ;;
@@ -4874,16 +4874,17 @@ MOZ_JSLOADER=1
 MOZ_MATHML=1
 MOZ_MORK=
 MOZ_MORKREADER=1
 MOZ_AUTH_EXTENSION=1
 MOZ_NO_ACTIVEX_SUPPORT=1
 MOZ_NO_INSPECTOR_APIS=
 MOZ_NO_FAST_LOAD=
 MOZ_OGG=1
+MOZ_RAW=1
 MOZ_SYDNEYAUDIO=
 MOZ_VORBIS=
 MOZ_WAVE=1
 MOZ_MEDIA=
 MOZ_WEBM=1
 VPX_AS=
 VPX_ASFLAGS=
 VPX_X86_ASM=
@@ -5822,16 +5823,19 @@ MOZ_ARG_DISABLE_BOOL(xpcom-fastload,
     MOZ_NO_FAST_LOAD=)
 
 AC_SUBST(MOZ_NO_FAST_LOAD)
 
 if test -n "$MOZ_NO_FAST_LOAD"; then
     AC_DEFINE(MOZ_NO_FAST_LOAD)
 fi
 
+AC_SUBST(MOZ_RAW)
+AC_DEFINE(MOZ_RAW)
+
 dnl ========================================================
 dnl = Disable Ogg Codecs
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(ogg,
 [  --disable-ogg           Disable support for OGG media (Theora video and Vorbis audio)],
     MOZ_OGG=,
     MOZ_OGG=1)
 
@@ -7397,23 +7401,37 @@ MOZ_ARG_ENABLE_BOOL(gczeal,
 if test -n "$JS_GC_ZEAL"; then
     AC_DEFINE(JS_GC_ZEAL)
 fi
 
 dnl ======================================================
 dnl = Enable compiling with ccache
 dnl ======================================================
 MOZ_ARG_WITH_STRING(ccache,
-[  --with-ccache=path/to/ccache
+[  --with-ccache[=path/to/ccache]
                           Enable compiling with ccache],
-    CCACHE_PATH=$withval,)
-
-if test -n "$CCACHE_PATH"; then
-  CC="$CCACHE_PATH $CC"
-  CXX="$CCACHE_PATH $CXX"
+    CCACHE=$withval, CCACHE="no")
+
+if test "$CCACHE" != "no"; then
+    if test -z "$CCACHE" -o "$CCACHE" = "yes"; then
+        CCACHE=
+    else
+        if test ! -e "$CCACHE"; then
+            AC_MSG_ERROR([$CCACHE not found])
+        fi
+    fi
+    MOZ_PATH_PROGS(CCACHE, $CCACHE ccache)
+    if test -z "$CCACHE" -o "$CCACHE" = ":"; then
+        AC_MSG_ERROR([ccache not found])
+    elif test -x "$CCACHE"; then
+        CC="$CCACHE $CC"
+        CXX="$CCACHE $CXX"
+    else
+        AC_MSG_ERROR([$CCACHE is not executable])
+    fi
 fi
 
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(static-checking,
 [  --with-static-checking=path/to/gcc_dehydra.so
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -79,17 +79,17 @@ enum {
 
 namespace mozilla {
 namespace dom {
 
 class Element : public nsIContent
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
-  Element(nsINodeInfo* aNodeInfo) : nsIContent(aNodeInfo) {}
+  Element(already_AddRefed<nsINodeInfo> aNodeInfo) : nsIContent(aNodeInfo) {}
 #endif // MOZILLA_INTERNAL_API
 };
 
 } // namespace dom
 } // namespace mozilla
 
 inline mozilla::dom::Element* nsINode::AsElement() {
   NS_ASSERTION(IsElement(), "Not an element?");
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -103,16 +103,17 @@ XPIDLSRCS	= \
 		nsIDOMFileInternal.idl \
 		nsIDOMFileList.idl \
 		nsIDOMFileException.idl \
 		nsIDOMFileError.idl \
 		nsIDOMFormData.idl \
 		nsIDOMParser.idl \
 		nsIDOMSerializer.idl \
 		nsISelection2.idl \
+		nsISelection3.idl \
 		nsISelectionController.idl  \
 		nsISelectionDisplay.idl  \
 		nsISelectionListener.idl  \
 		nsISelectionPrivate.idl  \
 		nsIScriptLoaderObserver.idl  \
 		nsISyncLoadDOMService.idl  \
 		nsIDroppedLinkHandler.idl \
 		nsIScriptEventHandler.idl \
--- a/content/base/public/nsContentCreatorFunctions.h
+++ b/content/base/public/nsContentCreatorFunctions.h
@@ -61,20 +61,20 @@ class nsGenericHTMLElement;
  */
 #define NS_NOT_FROM_PARSER 0
 #define NS_FROM_PARSER_NETWORK 1
 #define NS_FROM_PARSER_DOCUMENT_WRITE (1 << 1)
 #define NS_FROM_PARSER_FRAGMENT (1 << 2)
 
 nsresult
 NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
-              nsINodeInfo* aNodeInfo, PRUint32 aFromParser);
+              already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser);
 
 nsresult
-NS_NewXMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
+NS_NewXMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo);
 
 /**
  * aNodeInfoManager must not be null.
  */
 nsresult
 NS_NewTextNode(nsIContent **aResult, nsNodeInfoManager *aNodeInfoManager);
 
 /**
@@ -103,41 +103,44 @@ NS_NewXMLStylesheetProcessingInstruction
 /**
  * aNodeInfoManager must not be null.
  */
 nsresult
 NS_NewXMLCDATASection(nsIContent** aInstancePtrResult,
                       nsNodeInfoManager *aNodeInfoManager);
 
 nsresult
-NS_NewHTMLElement(nsIContent** aResult, nsINodeInfo *aNodeInfo,
+NS_NewHTMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
                   PRUint32 aFromParser);
 
 // First argument should be nsHTMLTag, but that adds dependency to parser
 // for a bunch of files.
 already_AddRefed<nsGenericHTMLElement>
-CreateHTMLElement(PRUint32 aNodeType, nsINodeInfo *aNodeInfo,
+CreateHTMLElement(PRUint32 aNodeType, already_AddRefed<nsINodeInfo> aNodeInfo,
                   PRUint32 aFromParser);
 
 #ifdef MOZ_MATHML
 nsresult
-NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
+NS_NewMathMLElement(nsIContent** aResult,
+                     already_AddRefed<nsINodeInfo> aNodeInfo);
 #endif
 
 #ifdef MOZ_XUL
 nsresult
-NS_NewXULElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
+NS_NewXULElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo);
 #endif
 
 #ifdef MOZ_SVG
 nsresult
-NS_NewSVGElement(nsIContent** aResult, nsINodeInfo* aNodeInfo,
+NS_NewSVGElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
                  PRUint32 aFromParser);
 #endif
 
 nsresult
-NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
+NS_NewGenConImageContent(nsIContent** aResult,
+                         already_AddRefed<nsINodeInfo> aNodeInfo,
                          imgIRequest* aImageRequest);
 
 nsresult
-NS_NewXMLEventsElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
+NS_NewXMLEventsElement(nsIContent** aResult,
+                       already_AddRefed<nsINodeInfo> aNodeInfo);
 
 #endif // nsContentCreatorFunctions_h__
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1568,27 +1568,43 @@ public:
    */
   static PRBool CanAccessNativeAnon();
 
   static nsresult WrapNative(JSContext *cx, JSObject *scope,
                              nsISupports *native, const nsIID* aIID, jsval *vp,
                              // If non-null aHolder will keep the jsval alive
                              // while there's a ref to it
                              nsIXPConnectJSObjectHolder** aHolder = nsnull,
-                             PRBool aAllowWrapping = PR_FALSE);
+                             PRBool aAllowWrapping = PR_FALSE)
+  {
+    return WrapNative(cx, scope, native, nsnull, aIID, vp, aHolder,
+                      aAllowWrapping);
+  }
 
   // Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
   static nsresult WrapNative(JSContext *cx, JSObject *scope,
-                             nsISupports *native,  jsval *vp,
+                             nsISupports *native, jsval *vp,
                              // If non-null aHolder will keep the jsval alive
                              // while there's a ref to it
                              nsIXPConnectJSObjectHolder** aHolder = nsnull,
                              PRBool aAllowWrapping = PR_FALSE)
   {
-    return WrapNative(cx, scope, native, nsnull, vp, aHolder, aAllowWrapping);
+    return WrapNative(cx, scope, native, nsnull, nsnull, vp, aHolder,
+                      aAllowWrapping);
+  }
+  static nsresult WrapNative(JSContext *cx, JSObject *scope,
+                             nsISupports *native, nsWrapperCache *cache,
+                             jsval *vp,
+                             // If non-null aHolder will keep the jsval alive
+                             // while there's a ref to it
+                             nsIXPConnectJSObjectHolder** aHolder = nsnull,
+                             PRBool aAllowWrapping = PR_FALSE)
+  {
+    return WrapNative(cx, scope, native, cache, nsnull, vp, aHolder,
+                      aAllowWrapping);
   }
 
   static void StripNullChars(const nsAString& aInStr, nsAString& aOutStr);
 
   /**
    * Creates a structured clone of the given jsval according to the algorithm
    * at:
    *     http://www.whatwg.org/specs/web-apps/current-work/multipage/
@@ -1669,16 +1685,22 @@ private:
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
   static void DropScriptObject(PRUint32 aLangID, void *aObject, void *aClosure);
 
   static PRBool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
+  static nsresult WrapNative(JSContext *cx, JSObject *scope,
+                             nsISupports *native, nsWrapperCache *cache,
+                             const nsIID* aIID, jsval *vp,
+                             nsIXPConnectJSObjectHolder** aHolder,
+                             PRBool aAllowWrapping);
+
   static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
 
   static nsIXPConnect *sXPConnect;
 
   static nsIScriptSecurityManager *sSecurityManager;
 
   static nsIThreadJSContextStack *sThreadJSContextStack;
 
--- a/content/base/public/nsIAttribute.h
+++ b/content/base/public/nsIAttribute.h
@@ -71,17 +71,17 @@ public:
   /**
    * Called when our ownerElement is moved into a new document.
    * Updates the nodeinfo of this node.
    */
   virtual nsresult SetOwnerDocument(nsIDocument* aDocument) = 0;
 
 protected:
 #ifdef MOZILLA_INTERNAL_API
-  nsIAttribute(nsDOMAttributeMap *aAttrMap, nsINodeInfo *aNodeInfo)
+  nsIAttribute(nsDOMAttributeMap *aAttrMap, already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsINode(aNodeInfo), mAttrMap(aAttrMap)
   {
   }
 #endif //MOZILLA_INTERNAL_API
 
   nsDOMAttributeMap *mAttrMap; // WEAK
 };
 
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -66,34 +66,34 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID       \
-{ 0x1450010b, 0xcdca, 0x451c, \
-  { 0xba, 0xdc, 0x07, 0x90, 0x89, 0x7b, 0xce, 0xb8 } }
+{ 0xdd254504, 0xe273, 0x4923, \
+  { 0x9e, 0xc1, 0xd8, 0x42, 0x1a, 0x66, 0x35, 0xf1 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
 #ifdef MOZILLA_INTERNAL_API
   // If you're using the external API, the only thing you can know about
   // nsIContent is that it exists with an IID
 
-  nsIContent(nsINodeInfo *aNodeInfo)
+  nsIContent(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsINode(aNodeInfo),
       mPrimaryFrame(nsnull)
   {
-    NS_ASSERTION(aNodeInfo,
+    NS_ASSERTION(mNodeInfo,
                  "No nsINodeInfo passed to nsIContent, PREPARE TO CRASH!!!");
   }
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENT_IID)
 
   /**
    * Bind this content node to a tree.  If this method throws, the caller must
@@ -923,16 +923,29 @@ public:
                               nsAString& aNamespaceURI) const;
 
   nsIAtom* LookupPrefix(const nsAString& aNamespaceURI);
 
   PRBool IsEqual(nsIContent *aOther);
 
   virtual PRBool IsEqualNode(nsINode* aOther);
 
+  /**
+   * If this content has independent selection, e.g., if this is input field
+   * or textarea, this return TRUE.  Otherwise, false.
+   */
+  PRBool HasIndependentSelection();
+
+  /**
+   * If the content is a part of HTML editor, this returns editing
+   * host content.  When the content is in designMode, this returns its body
+   * element.  Also, when the content isn't editable, this returns null.
+   */
+  nsIContent* GetEditingHost();
+
 protected:
   /**
    * Hook for implementing GetID.  This is guaranteed to only be
    * called if the NODE_HAS_ID flag is set.
    */
   virtual nsIAtom* DoGetID() const = 0;
 
 private:
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -113,18 +113,18 @@ class Loader;
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 
 #define NS_IDOCUMENT_IID      \
-{ 0x19df0b2c, 0xf89a, 0x4c83, \
-  { 0x82, 0x29, 0x3a, 0xe0, 0xb6, 0x42, 0x71, 0x9c } }
+{ 0xda512fdc, 0x2d83, 0x44b0, \
+  { 0xb0, 0x99, 0x00, 0xc6, 0xbb, 0x72, 0x39, 0xed } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              (1 << 0)
@@ -825,17 +825,17 @@ public:
   virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement) = 0;
 
   /**
    * Create an element with the specified name, prefix and namespace ID.
    * If aDocumentDefaultType is true we create an element of the default type
    * for that document (currently XHTML in HTML documents and XUL in XUL
    * documents), otherwise we use the type specified by the namespace ID.
    */
-  virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
+  virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
                               PRBool aDocumentDefaultType,
                               nsIContent** aResult) = 0;
 
   /**
    * Get the security info (i.e. SSL state etc) that the document got
    * from the channel/document that created the content of the
    * document.
--- a/content/base/public/nsIMutationObserver.h
+++ b/content/base/public/nsIMutationObserver.h
@@ -40,18 +40,18 @@
 #include "nsISupports.h"
 
 class nsIAtom;
 class nsIContent;
 class nsIDocument;
 class nsINode;
 
 #define NS_IMUTATION_OBSERVER_IID \
-{0x365d600b, 0x868a, 0x452a, \
-  {0x8d, 0xe8, 0xf4, 0x6f, 0xad, 0x8f, 0xee, 0x53 } }
+{ 0x85eea794, 0xed8e, 0x4e1b, \
+  { 0xa1, 0x28, 0xd0, 0x93, 0x00, 0xae, 0x51, 0xaa } }
 
 /**
  * Information details about a characterdata change.  Basically, we
  * view all changes as replacements of a length of text at some offset
  * with some other text (of possibly some other length).
  */
 struct CharacterDataChangeInfo
 {
@@ -112,32 +112,44 @@ public:
    *
    * This notification is not sent when a piece of content is
    * added/removed from the document (the other notifications are used
    * for that).
    *
    * @param aDocument The owner-document of aContent. Can be null.
    * @param aContent  The piece of content that changed. Is never null.
    * @param aInfo     The structure with information details about the change.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void CharacterDataWillChange(nsIDocument *aDocument,
                                        nsIContent* aContent,
                                        CharacterDataChangeInfo* aInfo) = 0;
 
   /**
    * Notification that the node value of a data node (text, cdata, pi, comment)
    * has changed.
    *
    * This notification is not sent when a piece of content is
    * added/removed from the document (the other notifications are used
    * for that).
    *
    * @param aDocument The owner-document of aContent. Can be null.
    * @param aContent  The piece of content that changed. Is never null.
    * @param aInfo     The structure with information details about the change.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void CharacterDataChanged(nsIDocument *aDocument,
                                     nsIContent* aContent,
                                     CharacterDataChangeInfo* aInfo) = 0;
 
   /**
    * Notification that an attribute of an element will change.  This
    * can happen before the BeginUpdate for the change and may not
@@ -147,16 +159,22 @@ public:
    *
    * @param aDocument    The owner-document of aContent. Can be null.
    * @param aContent     The element whose attribute will change
    * @param aNameSpaceID The namespace id of the changing attribute
    * @param aAttribute   The name of the changing attribute
    * @param aModType     Whether or not the attribute will be added, changed, or
    *                     removed. The constants are defined in
    *                     nsIDOMMutationEvent.h.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void AttributeWillChange(nsIDocument* aDocument,
                                    nsIContent*  aContent,
                                    PRInt32      aNameSpaceID,
                                    nsIAtom*     aAttribute,
                                    PRInt32      aModType) = 0;
 
   /**
@@ -164,16 +182,22 @@ public:
    *
    * @param aDocument    The owner-document of aContent. Can be null.
    * @param aContent     The element whose attribute changed
    * @param aNameSpaceID The namespace id of the changed attribute
    * @param aAttribute   The name of the changed attribute
    * @param aModType     Whether or not the attribute was added, changed, or
    *                     removed. The constants are defined in
    *                     nsIDOMMutationEvent.h.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void AttributeChanged(nsIDocument* aDocument,
                                 nsIContent*  aContent,
                                 PRInt32      aNameSpaceID,
                                 nsIAtom*     aAttribute,
                                 PRInt32      aModType) = 0;
 
   /**
@@ -181,16 +205,22 @@ public:
    * child list of another node in the tree.
    *
    * @param aDocument  The owner-document of aContent. Can be null.
    * @param aContainer The container that had new children appended. Is never
    *                   null.
    * @param aFirstNewContent the node at aIndexInContainer in aContainer.
    * @param aNewIndexInContainer the index in the container of the first
    *                   new child
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void ContentAppended(nsIDocument *aDocument,
                                nsIContent* aContainer,
                                nsIContent* aFirstNewContent,
                                PRInt32     aNewIndexInContainer) = 0;
 
   /**
    * Notification that a content node has been inserted as child to another
@@ -199,16 +229,22 @@ public:
    * @param aDocument  The owner-document of aContent, or, when aContainer
    *                   is null, the container that had the child inserted.
    *                   Can be null.
    * @param aContainer The container that had new a child inserted. Can be
    *                   null to indicate that the child was inserted into
    *                   aDocument
    * @param aChild     The newly inserted child.
    * @param aIndexInContainer The index in the container of the new child.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void ContentInserted(nsIDocument *aDocument,
                                nsIContent* aContainer,
                                nsIContent* aChild,
                                PRInt32 aIndexInContainer) = 0;
 
   /**
    * Notification that a content node has been removed from the child list of
@@ -218,47 +254,64 @@ public:
    *                   is null, the container that had the child removed.
    *                   Can be null.
    * @param aContainer The container that had new a child removed. Can be
    *                   null to indicate that the child was removed from
    *                   aDocument.
    * @param aChild     The child that was removed.
    * @param aIndexInContainer The index in the container which the child used
    *                          to have.
+   * @param aPreviousSibling The previous sibling to the child that was removed.
+   *                         Can be null if there was no previous sibling.
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void ContentRemoved(nsIDocument *aDocument,
                               nsIContent* aContainer,
                               nsIContent* aChild,
-                              PRInt32 aIndexInContainer) = 0;
+                              PRInt32 aIndexInContainer,
+                              nsIContent* aPreviousSibling) = 0;
 
  /**
    * The node is in the process of being destroyed. Calling QI on the node is
    * not supported, however it is possible to get children and flags through
    * nsINode as well as calling IsNodeOfType(eCONTENT) and casting to
    * nsIContent to get attributes.
    *
    * NOTE: This notification is only called on observers registered directly
    * on the node. This is because when the node is destroyed it can not have
    * any ancestors. If you want to know when a descendant node is being
    * removed from the observed node, use the ContentRemoved notification.
    * 
    * @param aNode The node being destroyed.
+   *
+   * @note Callers of this method might not hold a strong reference to
+   *       the observer.  The observer is responsible for making sure it
+   *       stays alive for the duration of the call as needed.
    */
   virtual void NodeWillBeDestroyed(const nsINode *aNode) = 0;
 
   /**
    * Notification that the node's parent chain has changed. This
    * happens when either the node or one of its ancestors is inserted
    * or removed as a child of another node.
    *
    * Note that when a node is inserted this notification is sent to
    * all descendants of that node, since all such nodes have their
    * parent chain changed.
    *
    * @param aContent  The piece of content that had its parent changed.
+   *
+   * @note Callers of this method might not hold a strong reference to
+   *       the observer.  The observer is responsible for making sure it
+   *       stays alive for the duration of the call as needed.
    */
 
   virtual void ParentChainChanged(nsIContent *aContent) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID)
 
 #define NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE                  \
@@ -296,17 +349,18 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutatio
                                  nsIContent* aContainer,                     \
                                  nsIContent* aChild,                         \
                                  PRInt32 aIndexInContainer);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED                           \
     virtual void ContentRemoved(nsIDocument* aDocument,                      \
                                 nsIContent* aContainer,                      \
                                 nsIContent* aChild,                          \
-                                PRInt32 aIndexInContainer);
+                                PRInt32 aIndexInContainer,                   \
+                                nsIContent* aPreviousSibling);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED                      \
     virtual void NodeWillBeDestroyed(const nsINode* aNode);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED                       \
     virtual void ParentChainChanged(nsIContent *aContent);
 
 #define NS_DECL_NSIMUTATIONOBSERVER                                          \
@@ -368,17 +422,18 @@ void                                    
                         nsIContent* aChild,                               \
                         PRInt32 aIndexInContainer)                        \
 {                                                                         \
 }                                                                         \
 void                                                                      \
 _class::ContentRemoved(nsIDocument* aDocument,                            \
                        nsIContent* aContainer,                            \
                        nsIContent* aChild,                                \
-                       PRInt32 aIndexInContainer)                         \
+                       PRInt32 aIndexInContainer,                         \
+                       nsIContent* aPreviousSibling)                      \
 {                                                                         \
 }                                                                         \
 void                                                                      \
 _class::ParentChainChanged(nsIContent *aContent)                          \
 {                                                                         \
 }
 
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -64,16 +64,17 @@ class nsIPrincipal;
 class nsIMutationObserver;
 class nsChildContentList;
 class nsNodeWeakReference;
 class nsNodeSupportsWeakRefTearoff;
 class nsIEditor;
 class nsIVariant;
 class nsIDOMUserDataHandler;
 class nsAttrAndChildArray;
+class nsXPCClassInfo;
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 enum {
@@ -288,18 +289,18 @@ private:
 #define DOM_USER_DATA         1
 #define DOM_USER_DATA_HANDLER 2
 #ifdef MOZ_SMIL
 #define SMIL_MAPPED_ATTR_ANIMVAL 3
 #endif // MOZ_SMIL
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0x58695b2f, 0x39bd, 0x434d, \
-  { 0xa2, 0x0b, 0xde, 0xd3, 0xa8, 0xa0, 0xb6, 0x95 } } 
+{ 0x2a8dc794, 0x9178, 0x400e, \
+  { 0x81, 0xff, 0x55, 0x30, 0x30, 0xb6, 0x74, 0x3b } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public nsPIDOMEventTarget,
                 public nsWrapperCache
@@ -308,25 +309,26 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
 
   friend class nsNodeUtils;
   friend class nsNodeWeakReference;
   friend class nsNodeSupportsWeakRefTearoff;
   friend class nsAttrAndChildArray;
 
 #ifdef MOZILLA_INTERNAL_API
-  nsINode(nsINodeInfo* aNodeInfo)
-    : mNodeInfo(aNodeInfo),
-      mParentPtrBits(0),
-      mFlagsOrSlots(NODE_DOESNT_HAVE_SLOTS),
-      mNextSibling(nsnull),
-      mPreviousSibling(nsnull),
-      mFirstChild(nsnull)
+  nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : mNodeInfo(aNodeInfo),
+    mParentPtrBits(0),
+    mFlagsOrSlots(NODE_DOESNT_HAVE_SLOTS),
+    mNextSibling(nsnull),
+    mPreviousSibling(nsnull),
+    mFirstChild(nsnull)
   {
   }
+
 #endif
 
   virtual ~nsINode();
 
   /**
    * Bit-flags to pass (or'ed together) to IsNodeOfType()
    */
   enum {
@@ -1140,16 +1142,18 @@ public:
       if (parent == aRoot) {
         return nsnull;
       }
       cur = parent;
     }
     NS_NOTREACHED("How did we get here?");
   }
 
+  // Optimized way to get classinfo. May return null.
+  virtual nsXPCClassInfo* GetClassInfo() = 0;
 protected:
 
   // Override this function to create a custom slots class.
   virtual nsINode::nsSlots* CreateSlots();
 
   PRBool HasSlots() const
   {
     return !(mFlagsOrSlots & NODE_DOESNT_HAVE_SLOTS);
--- a/content/base/public/nsINodeInfo.h
+++ b/content/base/public/nsINodeInfo.h
@@ -305,24 +305,36 @@ protected:
    * typically used as a member of nsNodeInfo, the hash table doesn't
    * need to delete the keys. When the value (nsNodeInfo) is deleted
    * the key is automatically deleted.
    */
 
   class nsNodeInfoInner
   {
   public:
+    nsNodeInfoInner()
+      : mName(nsnull), mPrefix(nsnull), mNamespaceID(kNameSpaceID_Unknown),
+        mNameString(nsnull)
+    {
+    }
     nsNodeInfoInner(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
-      : mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID)
+      : mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
+        mNameString(nsnull)
+    {
+    }
+    nsNodeInfoInner(const nsAString& aTmpName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
+      : mName(nsnull), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
+        mNameString(&aTmpName)
     {
     }
 
     nsIAtom*            mName;
     nsIAtom*            mPrefix;
     PRInt32             mNamespaceID;
+    const nsAString*    mNameString;
   };
 
   // nsNodeInfoManager needs to pass mInner to the hash table.
   friend class nsNodeInfoManager;
 
   nsNodeInfoInner mInner;
 
   nsCOMPtr<nsIAtom> mIDAttributeAtom;
--- a/content/base/public/nsISelection.idl
+++ b/content/base/public/nsISelection.idl
@@ -41,20 +41,20 @@
 
 interface nsIDOMNode;
 interface nsIDOMRange;
 
 /**
  * Interface for manipulating and querying the current selected range
  * of nodes within the document.
  *
- * @version 1.1
+ * @version 1.0
  */
 
-[scriptable, uuid(24bb8c1c-407c-4a97-b652-af767d847716)]
+[scriptable, uuid(B2C7ED59-8634-4352-9E37-5484C8B6E4E1)]
 interface nsISelection : nsISupports
 {
     /**
      * Returns the node in which the selection begins.
      */
     readonly attribute nsIDOMNode anchorNode;
 
     /**
@@ -150,37 +150,16 @@ interface nsISelection : nsISupports
     void removeAllRanges();
 
     /**
      * Deletes this selection from document the nodes belong to.
      */
     void deleteFromDocument();
 
     /**
-     * Modifies the selection.  Note that the parameters are case-insensitive.
-     *
-     * @param alter can be one of { "move", "extend" }
-     *   - "move" collapses the selection to the end of the selection and
-     *      applies the movement direction/granularity to the collapsed
-     *      selection.
-     *   - "extend" leaves the start of the selection unchanged, and applies
-     *      movement direction/granularity to the end of the selection.
-     * @param direction can be one of { "forward", "backward", "left", "right" }
-     * @param granularity can be one of { "character", "word",
-     *                                    "line", "lineboundary" }
-     *
-     * @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
-     * "sentenceboundary", "paragraph", "paragraphboundary", or
-     * "documentboundary".  Returns NS_ERROR_INVALID_ARG if alter, direction,
-     * or granularity has an unrecognized value.
-     */
-    void modify(in DOMString alter, in DOMString direction,
-                in DOMString granularity);
-
-    /**
      * Modifies the cursor Bidi level after a change in keyboard direction
      * @param langRTL is PR_TRUE if the new language is right-to-left or
      *                PR_FALSE if the new language is left-to-right.
      */
     void selectionLanguageChange(in boolean langRTL);
 
     /**
      * Returns the whole selection into a plain text string.
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsISelection3.idl
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** 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 Selection code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Justin Lebar <justin.lebar@gmail.com>
+ *
+ * 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 ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(94ac0cb4-95b4-11df-8e13-0026b9792740)]
+interface nsISelection3 : nsISupports
+{
+  /**
+   * Modifies the selection.  Note that the parameters are case-insensitive.
+   *
+   * @param alter can be one of { "move", "extend" }
+   *   - "move" collapses the selection to the end of the selection and
+   *      applies the movement direction/granularity to the collapsed
+   *      selection.
+   *   - "extend" leaves the start of the selection unchanged, and applies
+   *      movement direction/granularity to the end of the selection.
+   * @param direction can be one of { "forward", "backward", "left", "right" }
+   * @param granularity can be one of { "character", "word",
+   *                                    "line", "lineboundary" }
+   *
+   * @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
+   * "sentenceboundary", "paragraph", "paragraphboundary", or
+   * "documentboundary".  Returns NS_ERROR_INVALID_ARG if alter, direction,
+   * or granularity has an unrecognized value.
+   */
+  void modify(in DOMString alter, in DOMString direction,
+              in DOMString granularity);
+
+};
--- a/content/base/src/nsCommentNode.cpp
+++ b/content/base/src/nsCommentNode.cpp
@@ -43,17 +43,17 @@
 #include "nsGenericDOMDataNode.h"
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 
 class nsCommentNode : public nsGenericDOMDataNode,
                       public nsIDOMComment
 {
 public:
-  nsCommentNode(nsINodeInfo *aNodeInfo);
+  nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsCommentNode();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_IMPL_NSIDOMNODE_USING_GENERIC_DOM_DATA
 
@@ -61,16 +61,17 @@ public:
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
 
   // nsIDOMComment
   // Empty interface
 
   // nsIContent
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
 
+  virtual nsXPCClassInfo* GetClassInfo();
 #ifdef DEBUG
   virtual void List(FILE* out, PRInt32 aIndent) const;
   virtual void DumpContent(FILE* out = stdout, PRInt32 aIndent = 0,
                            PRBool aDumpAll = PR_TRUE) const
   {
     return;
   }
 #endif
@@ -82,36 +83,36 @@ NS_NewCommentNode(nsIContent** aInstance
 {
   NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
 
   *aInstancePtrResult = nsnull;
 
   nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetCommentNodeInfo();
   NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
 
-  nsCommentNode *instance = new nsCommentNode(ni);
+  nsCommentNode *instance = new nsCommentNode(ni.forget());
   if (!instance) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aInstancePtrResult = instance);
 
   return NS_OK;
 }
 
-nsCommentNode::nsCommentNode(nsINodeInfo *aNodeInfo)
+nsCommentNode::nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericDOMDataNode(aNodeInfo)
 {
 }
 
 nsCommentNode::~nsCommentNode()
 {
 }
 
-DOMCI_DATA(Comment, nsCommentNode)
+DOMCI_NODE_DATA(Comment, nsCommentNode)
 
 // QueryInterface implementation for nsCommentNode
 NS_INTERFACE_TABLE_HEAD(nsCommentNode)
   NS_NODE_INTERFACE_TABLE3(nsCommentNode, nsIDOMNode, nsIDOMCharacterData,
                            nsIDOMComment)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Comment)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericDOMDataNode)
 
@@ -150,17 +151,18 @@ nsCommentNode::GetNodeType(PRUint16* aNo
 {
   *aNodeType = (PRUint16)nsIDOMNode::COMMENT_NODE;
   return NS_OK;
 }
 
 nsGenericDOMDataNode*
 nsCommentNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
 {
-  nsCommentNode *it = new nsCommentNode(aNodeInfo);
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+  nsCommentNode *it = new nsCommentNode(ni.forget());
   if (it && aCloneText) {
     it->mText = mText;
   }
 
   return it;
 }
 
 #ifdef DEBUG
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -581,28 +581,32 @@ nsContentList::NamedItem(const nsAString
 }
 
 nsIContent*
 nsContentList::GetNodeAt(PRUint32 aIndex)
 {
   return Item(aIndex, PR_TRUE);
 }
 
-nsISupports*
+nsIContent*
 nsContentList::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
 {
   *aResult = NS_OK;
   return Item(aIndex, PR_TRUE);
 }
 
 nsISupports*
-nsContentList::GetNamedItem(const nsAString& aName, nsresult* aResult)
+nsContentList::GetNamedItem(const nsAString& aName, nsWrapperCache **aCache,
+                            nsresult* aResult)
 {
   *aResult = NS_OK;
-  return NamedItem(aName, PR_TRUE);
+
+  nsIContent *item;
+  *aCache = item = NamedItem(aName, PR_TRUE);
+  return item;
 }
 
 void
 nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                 PRInt32 aModType)
 {
   NS_PRECONDITION(aContent, "Must have a content node to work with");
@@ -745,17 +749,18 @@ nsContentList::ContentInserted(nsIDocume
 
   ASSERT_IN_SYNC;
 }
  
 void
 nsContentList::ContentRemoved(nsIDocument *aDocument,
                               nsIContent* aContainer,
                               nsIContent* aChild,
-                              PRInt32 aIndexInContainer)
+                              PRInt32 aIndexInContainer,
+                              nsIContent* aPreviousSibling)
 {
   // Note that aContainer can be null here if we are removing from
   // the document itself; any attempted optimizations to this method
   // should deal with that.
   if (mState != LIST_DIRTY &&
       MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
       nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
       MatchSelf(aChild)) {
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -264,18 +264,20 @@ public:
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsBaseContentList overrides
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual PRInt32 IndexOf(nsIContent* aContent);
 
   // nsIHTMLCollection
-  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
-  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  virtual nsISupports* GetNamedItem(const nsAString& aName,
+                                    nsWrapperCache** aCache,
+                                    nsresult* aResult);
 
   // nsContentList public methods
   NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }
   NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
 
   nsContentListKey* GetKey() {
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1595,22 +1595,20 @@ nsContentSink::DropParserAndPerfHint(voi
     // Make sure we don't unblock unload too many times
     return;
   }
   
   // Ref. Bug 49115
   // Do this hack to make sure that the parser
   // doesn't get destroyed, accidently, before
   // the circularity, between sink & parser, is
-  // actually borken.
-  nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
-
+  // actually broken.
   // Drop our reference to the parser to get rid of a circular
   // reference.
-  mParser = nsnull;
+  nsCOMPtr<nsIParser> kungFuDeathGrip(mParser.forget());
 
   if (mDynamicLowerValue) {
     // Reset the performance hint which was set to FALSE
     // when mDynamicLowerValue was set.
     FavorPerformanceHint(PR_TRUE, 0);
   }
 
   if (mCanInterruptParser) {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3788,25 +3788,26 @@ nsContentUtils::CreateContextualFragment
     if (contextAsContent && !contextAsContent->IsElement()) {
       contextAsContent = contextAsContent->GetParent();
       if (contextAsContent && !contextAsContent->IsElement()) {
         // can this even happen?
         contextAsContent = nsnull;
       }
     }
     
+    nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
     if (contextAsContent) {
       parser->ParseFragment(aFragment, 
-                            frag, 
+                            fragment, 
                             contextAsContent->Tag(), 
                             contextAsContent->GetNameSpaceID(), 
                             (document->GetCompatibilityMode() == eCompatibility_NavQuirks));    
     } else {
       parser->ParseFragment(aFragment, 
-                            frag, 
+                            fragment,
                             nsGkAtoms::body, 
                             kNameSpaceID_XHTML, 
                             (document->GetCompatibilityMode() == eCompatibility_NavQuirks));
     }
   
     frag.swap(*aReturn);
     document->SetFragmentParser(parser);
     return NS_OK;
@@ -5347,17 +5348,17 @@ nsContentUtils::DispatchXULCommand(nsICo
   NS_ENSURE_STATE(target);
   PRBool dummy;
   return target->DispatchEvent(event, &dummy);
 }
 
 // static
 nsresult
 nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
-                           const nsIID* aIID, jsval *vp,
+                           nsWrapperCache *cache, const nsIID* aIID, jsval *vp,
                            nsIXPConnectJSObjectHolder **aHolder,
                            PRBool aAllowWrapping)
 {
   if (!native) {
     NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
 
     *vp = JSVAL_NULL;
 
@@ -5384,17 +5385,17 @@ nsContentUtils::WrapNative(JSContext *cx
   JSContext *topJSContext;
   nsresult rv = sThreadJSContextStack->Peek(&topJSContext);
   if (NS_SUCCEEDED(rv)) {
     PRBool push = topJSContext != cx;
     if (push) {
       rv = sThreadJSContextStack->Push(cx);
     }
     if (NS_SUCCEEDED(rv)) {
-      rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, aIID,
+      rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
                                          aAllowWrapping, vp, aHolder);
       if (push) {
         sThreadJSContextStack->Pop(nsnull);
       }
     }
   }
 
   if (isMainThread) {
@@ -5952,16 +5953,17 @@ AllocClassMatchingInfo(nsINode* aRootNod
 
   if (attrValue.Type() == nsAttrValue::eAtomArray) {
     info->mClasses.AppendObjects(*(attrValue.GetAtomArrayValue()));
   } else if (attrValue.Type() == nsAttrValue::eAtom) {
     info->mClasses.AppendObject(attrValue.GetAtomValue());
   }
 
   info->mCaseTreatment =
+    aRootNode->GetOwnerDoc() &&
     aRootNode->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
     eIgnoreCase : eCaseMatters;
   return info;
 }
 
 // static
 
 nsresult
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -59,17 +59,17 @@
 #include "nsTextNode.h"
 #include "mozAutoDocUpdate.h"
 #include "nsMutationEvent.h"
 
 //----------------------------------------------------------------------
 PRBool nsDOMAttribute::sInitialized;
 
 nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
-                               nsINodeInfo       *aNodeInfo,
+                               already_AddRefed<nsINodeInfo> aNodeInfo,
                                const nsAString   &aValue)
   : nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue), mChild(nsnull)
 {
   NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
 
 
   // We don't add a reference to our content. It will tell us
   // to drop our reference when it goes away.
@@ -119,17 +119,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     static_cast<nsTextNode*>(tmp->mChild)->UnbindFromAttribute();
     NS_RELEASE(tmp->mChild);
     tmp->mFirstChild = nsnull;
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-DOMCI_DATA(Attr, nsDOMAttribute)
+DOMCI_NODE_DATA(Attr, nsDOMAttribute)
 
 // QueryInterface implementation for nsDOMAttribute
 NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODE_INTERFACE_TABLE6(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsIDOMNode,
                            nsIDOM3Attr, nsPIDOMEventTarget, nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttribute)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
@@ -410,17 +410,18 @@ nsDOMAttribute::AppendChild(nsIDOMNode* 
 }
 
 nsresult
 nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   nsAutoString value;
   const_cast<nsDOMAttribute*>(this)->GetValue(value);
 
-  *aResult = new nsDOMAttribute(nsnull, aNodeInfo, value);
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+  *aResult = new nsDOMAttribute(nsnull, ni.forget(), value);
   if (!*aResult) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aResult);
 
   return NS_OK;
 }
@@ -759,16 +760,18 @@ nsDOMAttribute::AttributeChanged(nsIDocu
     return;
   }
 
   nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
   if (nameAtom != aAttribute) {
     return;
   }
 
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+  
   // Just blow away our mChild and recreate it if needed
   if (mChild) {
     static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
     NS_RELEASE(mChild);
     mFirstChild = nsnull;
   }
   EnsureChildState();
 }
--- a/content/base/src/nsDOMAttribute.h
+++ b/content/base/src/nsDOMAttribute.h
@@ -58,17 +58,18 @@
 // Attribute helper class used to wrap up an attribute with a dom
 // object that implements nsIDOMAttr, nsIDOM3Attr, nsIDOMNode, nsIDOM3Node
 class nsDOMAttribute : public nsIAttribute,
                        public nsIDOMAttr,
                        public nsIDOM3Attr,
                        public nsStubMutationObserver
 {
 public:
-  nsDOMAttribute(nsDOMAttributeMap* aAttrMap, nsINodeInfo *aNodeInfo,
+  nsDOMAttribute(nsDOMAttributeMap* aAttrMap,
+                 already_AddRefed<nsINodeInfo> aNodeInfo,
                  const nsAString& aValue);
   virtual ~nsDOMAttribute();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMNode interface
   NS_DECL_NSIDOMNODE
 
@@ -117,16 +118,17 @@ public:
   static void Initialize();
   static void Shutdown();
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDOMAttribute,
                                                          nsIAttribute)
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual mozilla::dom::Element* GetNameSpaceElement()
   {
     return GetContentInternal()->AsElement();
   }
 
   static PRBool sInitialized;
 
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -174,17 +174,19 @@ nsDOMAttributeMap::RemoveAttribute(nsINo
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
   nsRefPtr<nsDOMAttribute> node;
   if (!mAttributeCache.Get(attr, getter_AddRefs(node))) {
     nsAutoString value;
     // As we are removing the attribute we need to set the current value in
     // the attribute node.
     mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
-    nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(nsnull, aNodeInfo, value);
+    nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+    nsCOMPtr<nsIDOMNode> newAttr =
+      new nsDOMAttribute(nsnull, ni.forget(), value);
     if (!newAttr) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     newAttr.swap(*aReturn);
   }
   else {
     // Break link to map
     node->SetMap(nsnull);
@@ -202,18 +204,19 @@ nsDOMAttribute*
 nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo)
 {
   NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nsnull!");
 
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
   nsDOMAttribute* node = mAttributeCache.GetWeak(attr);
   if (!node) {
+    nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     nsRefPtr<nsDOMAttribute> newAttr =
-      new nsDOMAttribute(this, aNodeInfo, EmptyString());
+      new nsDOMAttribute(this, ni.forget(), EmptyString());
     if (newAttr && mAttributeCache.Put(attr, newAttr)) {
       node = newAttr;
     }
   }
 
   return node;
 }
 
--- a/content/base/src/nsDOMDocumentType.cpp
+++ b/content/base/src/nsDOMDocumentType.cpp
@@ -84,28 +84,28 @@ NS_NewDOMDocumentType(nsIDOMDocumentType
     nimgr->SetDocumentPrincipal(aPrincipal);
   }
 
   nsCOMPtr<nsINodeInfo> ni;
   ni = nimgr->GetNodeInfo(nsGkAtoms::documentTypeNodeName, nsnull,
                           kNameSpaceID_None);
   NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
 
-  *aDocType = new nsDOMDocumentType(ni, aName, aEntities, aNotations,
+  *aDocType = new nsDOMDocumentType(ni.forget(), aName, aEntities, aNotations,
                                     aPublicId, aSystemId, aInternalSubset);
   if (!*aDocType) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aDocType);
 
   return NS_OK;
 }
 
-nsDOMDocumentType::nsDOMDocumentType(nsINodeInfo *aNodeInfo,
+nsDOMDocumentType::nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
                                      nsIAtom *aName,
                                      nsIDOMNamedNodeMap *aEntities,
                                      nsIDOMNamedNodeMap *aNotations,
                                      const nsAString& aPublicId,
                                      const nsAString& aSystemId,
                                      const nsAString& aInternalSubset) :
   nsGenericDOMDataNode(aNodeInfo),
   mName(aName),
@@ -116,17 +116,17 @@ nsDOMDocumentType::nsDOMDocumentType(nsI
   mInternalSubset(aInternalSubset)
 {
 }
 
 nsDOMDocumentType::~nsDOMDocumentType()
 {
 }
 
-DOMCI_DATA(DocumentType, nsDOMDocumentType)
+DOMCI_NODE_DATA(DocumentType, nsDOMDocumentType)
 
 // QueryInterface implementation for nsDOMDocumentType
 NS_INTERFACE_TABLE_HEAD(nsDOMDocumentType)
   NS_NODE_INTERFACE_TABLE2(nsDOMDocumentType, nsIDOMNode, nsIDOMDocumentType)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMDocumentType)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DocumentType)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericDOMDataNode)
 
@@ -231,17 +231,18 @@ nsDOMDocumentType::GetNodeType(PRUint16*
   *aNodeType = nsIDOMNode::DOCUMENT_TYPE_NODE;
 
   return NS_OK;
 }
 
 nsGenericDOMDataNode*
 nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
 {
-  return new nsDOMDocumentType(aNodeInfo, mName, mEntities, mNotations,
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+  return new nsDOMDocumentType(ni.forget(), mName, mEntities, mNotations,
                                mPublicId, mSystemId, mInternalSubset);
 }
 
 nsresult
 nsDOMDocumentType::BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               PRBool aCompileEventHandlers)
 {
--- a/content/base/src/nsDOMDocumentType.h
+++ b/content/base/src/nsDOMDocumentType.h
@@ -52,17 +52,17 @@
 // CharacterData object, even though DocumentType is not character
 // data. This is done simply for convenience and should be changed if
 // this restricts what should be done for character data.
 
 class nsDOMDocumentType : public nsGenericDOMDataNode,
                           public nsIDOMDocumentType
 {
 public:
-  nsDOMDocumentType(nsINodeInfo* aNodeInfo,
+  nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
                     nsIAtom *aName,
                     nsIDOMNamedNodeMap *aEntities,
                     nsIDOMNamedNodeMap *aNotations,
                     const nsAString& aPublicId,
                     const nsAString& aSystemId,
                     const nsAString& aInternalSubset);
 
   virtual ~nsDOMDocumentType();
@@ -78,17 +78,17 @@ public:
 
   // nsIContent overrides
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
   virtual const nsTextFragment* GetText();
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               PRBool aCompileEventHandlers);
 
-
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   nsCOMPtr<nsIAtom> mName;
   nsCOMPtr<nsIDOMNamedNodeMap> mEntities;
   nsCOMPtr<nsIDOMNamedNodeMap> mNotations;
   nsString mPublicId;
   nsString mSystemId;
   nsString mInternalSubset;
 };
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1902,21 +1902,23 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
   DestroyElementMaps();
 
   PRUint32 count = mChildren.ChildCount();
   { // Scope for update
     MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, PR_TRUE);    
     for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
       nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
 
+      nsIContent* previousSibling = content->GetPreviousSibling();
+
       if (nsINode::GetFirstChild() == content) {
         mFirstChild = content->GetNextSibling();
       }
       mChildren.RemoveChildAt(i);
-      nsNodeUtils::ContentRemoved(this, content, i);
+      nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
       content->UnbindFromTree();
     }
   }
   mCachedRootElement = nsnull;
 
   // Reset our stylesheets
   ResetStylesheetsToURI(aURI);
   
@@ -2157,22 +2159,92 @@ nsDocument::StartDocumentLoad(const char
     FindCharInReadable(';', semicolon, end);
     SetContentTypeInternal(Substring(start, semicolon));
   }
 
   RetrieveRelevantHeaders(aChannel);
 
   mChannel = aChannel;
   
-  nsresult rv = InitCSP();
+  nsresult rv = CheckFrameOptions();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = InitCSP();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+// Check if X-Frame-Options permits this document to be loaded as a subdocument.
+nsresult nsDocument::CheckFrameOptions()
+{
+  nsAutoString xfoHeaderValue;
+  this->GetHeaderData(nsGkAtoms::headerXFO, xfoHeaderValue);
+
+  // return early if header does not have one of the two values with meaning
+  if (!xfoHeaderValue.LowerCaseEqualsLiteral("deny") &&
+      !xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin"))
+    return NS_OK;
+
+  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+
+  if (docShell) {
+    PRBool framingAllowed = true;
+
+    // We need to check the location of this window and the location of the top
+    // window, if we're not the top.  X-F-O: SAMEORIGIN requires that the
+    // document must be same-origin with top window.  X-F-O: DENY requires that
+    // the document must never be framed.
+    nsCOMPtr<nsIDOMWindow> thisWindow = do_GetInterface(docShell);
+    nsCOMPtr<nsIDOMWindow> topWindow;
+    thisWindow->GetTop(getter_AddRefs(topWindow));
+
+    // if the document is in the top window, it's not in a frame.
+    if (thisWindow == topWindow)
+      return NS_OK;
+
+    // If the value of the header is DENY, then the document
+    // should never be permitted to load as a subdocument.
+    if (xfoHeaderValue.LowerCaseEqualsLiteral("deny")) {
+      framingAllowed = false;
+    }
+
+    else if (xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin")) {
+      // If the X-Frame-Options value is SAMEORIGIN, then the top frame in the
+      // parent chain must be from the same origin as this document.
+      nsCOMPtr<nsIURI> uri = static_cast<nsIDocument*>(this)->GetDocumentURI();
+      nsCOMPtr<nsIDOMDocument> topDOMDoc;
+      topWindow->GetDocument(getter_AddRefs(topDOMDoc));
+      nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDOMDoc);
+      if (topDoc) {
+        nsCOMPtr<nsIURI> topUri = topDoc->GetDocumentURI();
+        nsresult rv = nsContentUtils::GetSecurityManager()->
+          CheckSameOriginURI(uri, topUri, PR_TRUE);
+
+        if (NS_FAILED(rv)) {
+          framingAllowed = false;
+        }
+      }
+    }
+
+    if (!framingAllowed) {
+      // cancel the load and display about:blank
+      mChannel->Cancel(NS_BINDING_ABORTED);
+      nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
+      if (webNav) {
+        webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
+                        0, nsnull, nsnull, nsnull);
+      }
+      return NS_ERROR_CONTENT_BLOCKED;
+    }
+  }
+
+  return NS_OK;
+}
+
 nsresult
 nsDocument::InitCSP()
 {
   if (CSPService::sCSPEnabled) {
     nsAutoString cspHeaderValue;
     nsAutoString cspROHeaderValue;
 
     this->GetHeaderData(nsGkAtoms::headerCSP, cspHeaderValue);
@@ -4015,33 +4087,53 @@ nsDocument::GetDocumentElement(nsIDOMEle
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateElement(const nsAString& aTagName,
                           nsIDOMElement** aReturn)
 {
   *aReturn = nsnull;
+  nsCOMPtr<nsIContent> content;
+  nsresult rv = CreateElement(aTagName, getter_AddRefs(content));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return CallQueryInterface(content, aReturn);
+}
+
+PRBool IsLowercaseASCII(const nsAString& aValue)
+{
+  PRInt32 len = aValue.Length();
+  for (PRInt32 i = 0; i < len; ++i) {
+    PRUnichar c = aValue[i];
+    if (!(0x0061 <= (c) && ((c) <= 0x007a))) {
+      return PR_FALSE;
+    }
+  }
+  return PR_TRUE;
+}
+
+nsresult
+nsDocument::CreateElement(const nsAString& aTagName,
+                          nsIContent** aReturn)
+{
+  *aReturn = nsnull;
 
   nsresult rv = nsContentUtils::CheckQName(aTagName, PR_FALSE);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  NS_ASSERTION(!IsHTML(),
-               "nsDocument::CreateElement() called on document that is not "
-               "case sensitive. Fix caller, or fix "
-               "nsDocument::CreateElement()!");
-
-  nsCOMPtr<nsIAtom> name = do_GetAtom(aTagName);
-
-  nsCOMPtr<nsIContent> content;
-  rv = CreateElem(name, nsnull, GetDefaultNamespaceID(), PR_TRUE,
-                  getter_AddRefs(content));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return CallQueryInterface(content, aReturn);
+  PRBool needsLowercase = IsHTML() && !IsLowercaseASCII(aTagName);
+  nsAutoString lcTagName;
+  if (needsLowercase) {
+    ToLowerCase(aTagName, lcTagName);
+  }
+
+  rv = CreateElem(needsLowercase ? lcTagName : aTagName, nsnull,
+                  IsHTML() ? kNameSpaceID_XHTML : GetDefaultNamespaceID(),
+                  PR_TRUE, aReturn);
+  return rv;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
                             const nsAString& aQualifiedName,
                             nsIDOMElement** aReturn)
 {
   *aReturn = nsnull;
@@ -4049,38 +4141,41 @@ nsDocument::CreateElementNS(const nsAStr
   nsCOMPtr<nsINodeInfo> nodeInfo;
   nsresult rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                                      aQualifiedName,
                                                      mNodeInfoManager,
                                                      getter_AddRefs(nodeInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content;
-  NS_NewElement(getter_AddRefs(content), nodeInfo->NamespaceID(), nodeInfo,
-                PR_FALSE);
+  PRInt32 ns = nodeInfo->NamespaceID();
+  NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), PR_FALSE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return CallQueryInterface(content, aReturn);
 }
 
 NS_IMETHODIMP
 nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn)
 {
   *aReturn = nsnull;
-
-  nsCOMPtr<nsIContent> text;
-  nsresult rv = NS_NewTextNode(getter_AddRefs(text), mNodeInfoManager);
-
+  nsCOMPtr<nsIContent> content;
+  nsresult rv = CreateTextNode(aData, getter_AddRefs(content));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return CallQueryInterface(content, aReturn);
+}
+
+nsresult
+nsDocument::CreateTextNode(const nsAString& aData, nsIContent** aReturn)
+{
+  nsresult rv = NS_NewTextNode(aReturn, mNodeInfoManager);
   if (NS_SUCCEEDED(rv)) {
     // Don't notify; this node is still being created.
-    text->SetText(aData, PR_FALSE);
-
-    rv = CallQueryInterface(text, aReturn);
-  }
-
+    (*aReturn)->SetText(aData, PR_FALSE);
+  }
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateDocumentFragment(nsIDOMDocumentFragment** aReturn)
 {
   return NS_NewDocumentFragment(aReturn, mNodeInfoManager);
 }
@@ -4170,17 +4265,17 @@ nsDocument::CreateAttribute(const nsAStr
   nsAutoString value;
   nsDOMAttribute* attribute;
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
   rv = mNodeInfoManager->GetNodeInfo(aName, nsnull, kNameSpaceID_None,
                                      getter_AddRefs(nodeInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  attribute = new nsDOMAttribute(nsnull, nodeInfo, value);
+  attribute = new nsDOMAttribute(nsnull, nodeInfo.forget(), value);
   NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY);
 
   return CallQueryInterface(attribute, aReturn);
 }
 
 NS_IMETHODIMP
 nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI,
                               const nsAString & aQualifiedName,
@@ -4192,17 +4287,18 @@ nsDocument::CreateAttributeNS(const nsAS
   nsCOMPtr<nsINodeInfo> nodeInfo;
   nsresult rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                                      aQualifiedName,
                                                      mNodeInfoManager,
                                                      getter_AddRefs(nodeInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString value;
-  nsDOMAttribute* attribute = new nsDOMAttribute(nsnull, nodeInfo, value);
+  nsDOMAttribute* attribute =
+    new nsDOMAttribute(nsnull, nodeInfo.forget(), value);
   NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY);
 
   return CallQueryInterface(attribute, aResult);
 }
 
 NS_IMETHODIMP
 nsDocument::CreateEntityReference(const nsAString& aName,
                                   nsIDOMEntityReference** aReturn)
@@ -4905,17 +5001,17 @@ nsDocument::SetTitle(const nsAString& aT
       return NS_OK;
 
     {
       nsCOMPtr<nsINodeInfo> titleInfo;
       titleInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nsnull,
                                                 kNameSpaceID_XHTML);
       if (!titleInfo)
         return NS_OK;
-      title = NS_NewHTMLTitleElement(titleInfo);
+      title = NS_NewHTMLTitleElement(titleInfo.forget());
       if (!title)
         return NS_OK;
     }
 
     head->AppendChildTo(title, PR_TRUE);
   }
 
   return nsContentUtils::SetNodeTextContent(title, aTitle, PR_FALSE);
@@ -5463,23 +5559,19 @@ NS_IMETHODIMP
 nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
 {
   return nsNodeUtils::CloneNodeImpl(this, aDeep, aReturn);
 }
 
 NS_IMETHODIMP
 nsDocument::Normalize()
 {
-  PRInt32 count = mChildren.ChildCount();
-  for (PRInt32 i = 0; i < count; ++i) {
+  for (PRInt32 i = 0; i < mChildren.ChildCount(); ++i) {
     nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mChildren.ChildAt(i)));
-
-    if (node) {
-      node->Normalize();
-    }
+    node->Normalize();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::IsSupported(const nsAString& aFeature, const nsAString& aVersion,
                         PRBool* aReturn)
@@ -6437,16 +6529,17 @@ nsDocument::RetrieveRelevantHeaders(nsIC
       "default-style",
       "content-style-type",
       "content-language",
       "content-disposition",
       "refresh",
       "x-dns-prefetch-control",
       "x-content-security-policy",
       "x-content-security-policy-report-only",
+      "x-frame-options",
       // add more http headers if you need
       // XXXbz don't add content-location support without reading bug
       // 238654 and its dependencies/dups first.
       0
     };
     
     nsCAutoString headerVal;
     const char *const *name = headers;
@@ -6505,46 +6598,47 @@ nsDocument::RetrieveRelevantHeaders(nsIC
                     prtime.tm_month + 1, prtime.tm_mday, prtime.tm_year,
                     prtime.tm_hour     ,  prtime.tm_min,  prtime.tm_sec)) {
       CopyASCIItoUTF16(nsDependentCString(formatedTime), mLastModified);
     }
   }
 }
 
 nsresult
-nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
+nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
                        PRBool aDocumentDefaultType, nsIContent **aResult)
 {
 #ifdef DEBUG
   nsAutoString qName;
   if (aPrefix) {
     aPrefix->ToString(qName);
     qName.Append(':');
   }
-  qName.Append(nsAtomString(aName));
+  qName.Append(aName);
 
   // Note: "a:b:c" is a valid name in non-namespaces XML, and
   // nsDocument::CreateElement can call us with such a name and no prefix,
   // which would cause an error if we just used PR_TRUE here.
   PRBool nsAware = aPrefix != nsnull || aNamespaceID != GetDefaultNamespaceID();
   NS_ASSERTION(NS_SUCCEEDED(nsContentUtils::CheckQName(qName, nsAware)),
                "Don't pass invalid prefixes to nsDocument::CreateElem, "
                "check caller.");
 #endif
 
   *aResult = nsnull;
   
   PRInt32 elementType = aDocumentDefaultType ? mDefaultElementType :
     aNamespaceID;
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
-  nodeInfo = mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID);
+  mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID,
+                                getter_AddRefs(nodeInfo));
   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
-  return NS_NewElement(aResult, elementType, nodeInfo, PR_FALSE);
+  return NS_NewElement(aResult, elementType, nodeInfo.forget(), PR_FALSE);
 }
 
 PRBool
 nsDocument::IsSafeToFlush() const
 {
   nsCOMPtr<nsIPresShell> shell = GetShell();
   if (!shell)
     return PR_TRUE;
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -829,21 +829,26 @@ public:
 
   // nsIApplicationCacheContainer
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
   virtual nsresult Init();
   
   virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
 
-  virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
+  virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
                               PRBool aDocumentDefaultType,
                               nsIContent **aResult);
 
+  nsresult CreateElement(const nsAString& aTagName,
+                         nsIContent** aReturn);
+
+  nsresult CreateTextNode(const nsAString& aData, nsIContent** aReturn);
+
   virtual NS_HIDDEN_(nsresult) Sanitize();
 
   virtual NS_HIDDEN_(void) EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
                                                  void *aData);
 
   virtual NS_HIDDEN_(PRBool) CanSavePresentation(nsIRequest *aNewRequest);
   virtual NS_HIDDEN_(void) Destroy();
   virtual NS_HIDDEN_(void) RemovedFromDocShell();
@@ -1014,19 +1019,19 @@ protected:
   void DispatchPageTransition(nsPIDOMEventTarget* aDispatchTarget,
                               const nsAString& aType,
                               PRBool aPersisted);
 
   virtual nsPIDOMWindow *GetWindowInternal();
   virtual nsPIDOMWindow *GetInnerWindowInternal();
   virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const;
 
-#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_)                  \
-  NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mObservers, nsIDocumentObserver, \
-                                     func_, params_);
+#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_)                        \
+  NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
+                                           func_, params_);
   
 #ifdef DEBUG
   void VerifyRootContentState();
 #endif
 
   nsDocument(const char* aContentType);
   virtual ~nsDocument();
 
@@ -1138,16 +1143,17 @@ protected:
   PRInt32 mGotDocumentState;
 
 private:
   friend class nsUnblockOnloadEvent;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
+  nsresult CheckFrameOptions();
   nsresult InitCSP();
 
   /**
    * See if aDocument is a child of this.  If so, return the frame element in
    * this document that holds currentDoc (or an ancestor).
    */
   already_AddRefed<nsIDOMElement>
     CheckAncestryAndGetFrame(nsIDocument* aDocument) const;
--- a/content/base/src/nsDocumentFragment.cpp
+++ b/content/base/src/nsDocumentFragment.cpp
@@ -54,17 +54,17 @@
 #include "nsGkAtoms.h"
 #include "nsDOMString.h"
 #include "nsIDOMUserDataHandler.h"
 
 class nsDocumentFragment : public nsGenericElement,
                            public nsIDOMDocumentFragment
 {
 public:
-  nsDocumentFragment(nsINodeInfo *aNodeInfo);
+  nsDocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsDocumentFragment();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // interface nsIDOMDocumentFragment
   NS_IMETHOD    GetNodeName(nsAString& aNodeName)
   { return nsGenericElement::GetNodeName(aNodeName); }
@@ -149,16 +149,18 @@ public:
   }
   virtual const nsAttrName* GetAttrNameAt(PRUint32 aIndex) const
   {
     return nsnull;
   }
 
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
 
+  virtual nsXPCClassInfo* GetClassInfo();
+
   virtual nsIAtom* DoGetID() const;
   virtual nsIAtom *GetIDAttributeName() const;
 
 protected:
   nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 };
 
 nsresult
@@ -167,27 +169,27 @@ NS_NewDocumentFragment(nsIDOMDocumentFra
 {
   NS_ENSURE_ARG(aNodeInfoManager);
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
   nodeInfo = aNodeInfoManager->GetNodeInfo(nsGkAtoms::documentFragmentNodeName,
                                            nsnull, kNameSpaceID_None);
   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
-  nsDocumentFragment *it = new nsDocumentFragment(nodeInfo);
+  nsDocumentFragment *it = new nsDocumentFragment(nodeInfo.forget());
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aInstancePtrResult = it);
 
   return NS_OK;
 }
 
-nsDocumentFragment::nsDocumentFragment(nsINodeInfo *aNodeInfo)
+nsDocumentFragment::nsDocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericElement(aNodeInfo)
 {
   UnsetFlags(NODE_IS_ELEMENT);
 }
 
 nsDocumentFragment::~nsDocumentFragment()
 {
 }
@@ -205,17 +207,17 @@ nsDocumentFragment::DoGetID() const
 }
 
 nsIAtom*
 nsDocumentFragment::GetIDAttributeName() const
 {
   return nsnull;
 }
 
-DOMCI_DATA(DocumentFragment, nsDocumentFragment)
+DOMCI_NODE_DATA(DocumentFragment, nsDocumentFragment)
 
 // QueryInterface implementation for nsDocumentFragment
 NS_INTERFACE_TABLE_HEAD(nsDocumentFragment)
   NS_NODE_INTERFACE_TABLE2(nsDocumentFragment, nsIDOMNode,
                            nsIDOMDocumentFragment)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DocumentFragment)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericElement)
 
--- a/content/base/src/nsGenConImageContent.cpp
+++ b/content/base/src/nsGenConImageContent.cpp
@@ -47,17 +47,17 @@
 #include "nsImageLoadingContent.h"
 #include "imgIRequest.h"
 #include "nsIEventStateManager.h"
 
 class nsGenConImageContent : public nsXMLElement,
                              public nsImageLoadingContent
 {
 public:
-  nsGenConImageContent(nsINodeInfo* aNodeInfo)
+  nsGenConImageContent(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsXMLElement(aNodeInfo)
   {
   }
 
   nsresult Init(imgIRequest* aImageRequest)
   {
     // No need to notify, since we have no frame.
     return UseAsPrimaryRequest(aImageRequest, PR_FALSE);
@@ -72,17 +72,17 @@ private:
 public:
   NS_DECL_ISUPPORTS_INHERITED
 };
 
 NS_IMPL_ISUPPORTS_INHERITED3(nsGenConImageContent, nsXMLElement,
                              nsIImageLoadingContent, imgIContainerObserver, imgIDecoderObserver)
 
 nsresult
-NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
+NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
                          imgIRequest* aImageRequest)
 {
   NS_PRECONDITION(aImageRequest, "Must have request!");
   nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo);
   if (!it)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(*aResult = it);
   nsresult rv = it->Init(aImageRequest);
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -62,17 +62,17 @@
 #include "nsNodeUtils.h"
 #include "nsBindingManager.h"
 #include "nsCCUncollectableMarker.h"
 #include "mozAutoDocUpdate.h"
 
 #include "pldhash.h"
 #include "prprf.h"
 
-nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo *aNodeInfo)
+nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsIContent(aNodeInfo)
 {
 }
 
 nsGenericDOMDataNode::~nsGenericDOMDataNode()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -81,17 +81,17 @@ class nsIDOMText;
 class nsINodeInfo;
 class nsURI;
 
 class nsGenericDOMDataNode : public nsIContent
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  nsGenericDOMDataNode(nsINodeInfo *aNodeInfo);
+  nsGenericDOMDataNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericDOMDataNode();
 
   // Implementation for nsIDOMNode
   nsresult GetNodeValue(nsAString& aNodeValue);
   nsresult SetNodeValue(const nsAString& aNodeValue);
   nsresult GetAttributes(nsIDOMNamedNodeMap** aAttributes)
   {
     NS_ENSURE_ARG_POINTER(aAttributes);
@@ -361,17 +361,18 @@ private:
   void SetBidiStatus();
 
   already_AddRefed<nsIAtom> GetCurrentValueAtom();
 };
 
 class nsGenericTextNode : public nsGenericDOMDataNode
 {
 public:
-  nsGenericTextNode(nsINodeInfo *aNodeInfo) : nsGenericDOMDataNode(aNodeInfo)
+  nsGenericTextNode(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : nsGenericDOMDataNode(aNodeInfo)
   {
   }
 
   PRBool IsElementContentWhitespace()
   {
     return TextIsOnlyWhitespace();
   }
   nsresult GetWholeText(nsAString& aWholeText);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -361,18 +361,17 @@ nsINode::GetSelectionRootContent(nsIPres
     return static_cast<nsIDocument*>(this)->GetRootElement();
   if (!IsNodeOfType(eCONTENT))
     return nsnull;
 
   if (GetCurrentDoc() != aPresShell->GetDocument()) {
     return nsnull;
   }
 
-  nsIFrame* frame = static_cast<nsIContent*>(this)->GetPrimaryFrame();
-  if (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
+  if (static_cast<nsIContent*>(this)->HasIndependentSelection()) {
     // This node should be a descendant of input/textarea editor.
     nsIContent* content = GetTextEditorRootContent();
     if (content)
       return content;
   }
 
   nsPresContext* presContext = aPresShell->GetPresContext();
   if (presContext) {
@@ -383,25 +382,19 @@ nsINode::GetSelectionRootContent(nsIPres
       if (!doc || doc->HasFlag(NODE_IS_EDITABLE) ||
           !HasFlag(NODE_IS_EDITABLE)) {
         nsIContent* editorRoot = GetEditorRootContent(editor);
         NS_ENSURE_TRUE(editorRoot, nsnull);
         return nsContentUtils::IsInSameAnonymousTree(this, editorRoot) ?
                  editorRoot :
                  GetRootForContentSubtree(static_cast<nsIContent*>(this));
       }
-      // If the current document is not editable, but current content is
-      // editable, we should assume that the child of the nearest non-editable
-      // ancestor is selection root.
-      nsIContent* content = static_cast<nsIContent*>(this);
-      for (nsIContent* parent = GetParent();
-           parent && parent->HasFlag(NODE_IS_EDITABLE);
-           parent = content->GetParent())
-        content = parent;
-      return content;
+      // If the document isn't editable but this is editable, this is in
+      // contenteditable.  Use the editing host element for selection root.
+      return static_cast<nsIContent*>(this)->GetEditingHost();
     }
   }
 
   nsCOMPtr<nsFrameSelection> fs = aPresShell->FrameSelection();
   nsIContent* content = fs->GetLimiter();
   if (!content) {
     content = fs->GetAncestorLimiter();
     if (!content) {
@@ -825,24 +818,23 @@ nsIContent::GetFlattenedTreeParent() con
 }
 
 PRUint32
 nsIContent::GetDesiredIMEState()
 {
   if (!IsEditableInternal()) {
     return IME_STATUS_DISABLE;
   }
-  nsIContent *editableAncestor = nsnull;
-  for (nsIContent* parent = GetParent();
-       parent && parent->HasFlag(NODE_IS_EDITABLE);
-       parent = parent->GetParent()) {
-    editableAncestor = parent;
-  }
+  // NOTE: The content for independent editors (e.g., input[type=text],
+  // textarea) must override this method, so, we don't need to worry about
+  // that here.
+  nsIContent *editableAncestor = GetEditingHost();
+
   // This is in another editable content, use the result of it.
-  if (editableAncestor) {
+  if (editableAncestor && editableAncestor != this) {
     return editableAncestor->GetDesiredIMEState();
   }
   nsIDocument* doc = GetCurrentDoc();
   if (!doc) {
     return IME_STATUS_DISABLE;
   }
   nsIPresShell* ps = doc->GetShell();
   if (!ps) {
@@ -860,16 +852,45 @@ nsIContent::GetDesiredIMEState()
   // Use "enable" for the default value because IME is disabled unexpectedly,
   // it makes serious a11y problem.
   PRUint32 state = IME_STATUS_ENABLE;
   nsresult rv = imeEditor->GetPreferredIMEState(&state);
   NS_ENSURE_SUCCESS(rv, IME_STATUS_ENABLE);
   return state;
 }
 
+PRBool
+nsIContent::HasIndependentSelection()
+{
+  nsIFrame* frame = GetPrimaryFrame();
+  return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
+}
+
+nsIContent*
+nsIContent::GetEditingHost()
+{
+  // If this isn't editable, return NULL.
+  NS_ENSURE_TRUE(HasFlag(NODE_IS_EDITABLE), nsnull);
+
+  nsIDocument* doc = GetCurrentDoc();
+  NS_ENSURE_TRUE(doc, nsnull);
+  // If this is in designMode, we should return <body>
+  if (doc->HasFlag(NODE_IS_EDITABLE)) {
+    return doc->GetBodyElement();
+  }
+
+  nsIContent* content = this;
+  for (nsIContent* parent = GetParent();
+       parent && parent->HasFlag(NODE_IS_EDITABLE);
+       parent = content->GetParent()) {
+    content = parent;
+  }
+  return content;
+}
+
 nsresult
 nsIContent::LookupNamespaceURI(const nsAString& aNamespacePrefix,
                                nsAString& aNamespaceURI) const
 {
   if (aNamespacePrefix.EqualsLiteral("xml")) {
     // Special-case for xml prefix
     aNamespaceURI.AssignLiteral("http://www.w3.org/XML/1998/namespace");
     return NS_OK;
@@ -2062,17 +2083,17 @@ nsGenericElement::nsDOMSlots::~nsDOMSlot
     mAttributeMap->DropReference();
   }
 
   if (mClassList) {
     mClassList->DropReference();
   }
 }
 
-nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo)
+nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : Element(aNodeInfo)
 {
   // Set the default scriptID to JS - but skip SetScriptTypeID as it
   // does extra work we know isn't necessary here...
   SetFlags(NODE_IS_ELEMENT |
            (nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET));
 }
 
@@ -3671,24 +3692,26 @@ nsINode::doRemoveChildAt(PRUint32 aIndex
   // was processing.
   if (guard.Mutated(0)) {
     aIndex = IndexOf(aKid);
     if (static_cast<PRInt32>(aIndex) < 0) {
       return NS_OK;
     }
   }
 
+  nsIContent* previousSibling = aKid->GetPreviousSibling();
+
   if (GetFirstChild() == aKid) {
     mFirstChild = aKid->GetNextSibling();
   }
 
   aChildArray.RemoveChildAt(aIndex);
 
   if (aNotify) {
-    nsNodeUtils::ContentRemoved(this, aKid, aIndex);
+    nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
   }
 
   aKid->UnbindFromTree();
 
   return NS_OK;
 }
 
 /* static */
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -320,17 +320,17 @@ class nsNSElementTearoff;
 
 /**
  * A generic base class for DOM elements, implementing many nsIContent,
  * nsIDOMNode and nsIDOMElement methods.
  */
 class nsGenericElement : public mozilla::dom::Element
 {
 public:
-  nsGenericElement(nsINodeInfo *aNodeInfo);
+  nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericElement();
 
   friend class nsNSElementTearoff;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   /**
    * Called during QueryInterface to give the binding manager a chance to
@@ -1079,18 +1079,18 @@ private:
  * Macros to implement Clone(). _elementName is the class for which to implement
  * Clone.
  */
 #define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
 nsresult                                                                    \
 _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const        \
 {                                                                           \
   *aResult = nsnull;                                                        \
-                                                                            \
-  _elementName *it = new _elementName(aNodeInfo);                           \
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;                                     \
+  _elementName *it = new _elementName(ni.forget());                         \
   if (!it) {                                                                \
     return NS_ERROR_OUT_OF_MEMORY;                                          \
   }                                                                         \
                                                                             \
   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
   nsresult rv = CopyInnerTo(it);                                            \
   if (NS_SUCCEEDED(rv)) {                                                   \
     kungFuDeathGrip.swap(*aResult);                                         \
@@ -1099,32 +1099,40 @@ nsresult                                
   return rv;                                                                \
 }
 
 #define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName)                       \
 nsresult                                                                    \
 _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const        \
 {                                                                           \
   *aResult = nsnull;                                                        \
-                                                                            \
-  _elementName *it = new _elementName(aNodeInfo);                           \
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;                                     \
+  _elementName *it = new _elementName(ni.forget());                         \
   if (!it) {                                                                \
     return NS_ERROR_OUT_OF_MEMORY;                                          \
   }                                                                         \
                                                                             \
   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
   nsresult rv = it->Init();                                                 \
   rv |= CopyInnerTo(it);                                                    \
   if (NS_SUCCEEDED(rv)) {                                                   \
     kungFuDeathGrip.swap(*aResult);                                         \
   }                                                                         \
                                                                             \
   return rv;                                                                \
 }
 
+#define DOMCI_NODE_DATA(_interface, _class)                             \
+  DOMCI_DATA(_interface, _class)                                        \
+  nsXPCClassInfo* _class::GetClassInfo()                                \
+  {                                                                     \
+    return static_cast<nsXPCClassInfo*>(                                \
+      NS_GetDOMClassInfoInstance(eDOMClassInfo_##_interface##_id));     \
+  }
+
 /**
  * Yet another tearoff class for nsGenericElement
  * to implement additional interfaces
  */
 class nsNSElementTearoff : public nsIDOMNSElement
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1020,16 +1020,17 @@ GK_ATOM(width, "width")
 GK_ATOM(window, "window")
 GK_ATOM(headerWindowTarget, "window-target")
 GK_ATOM(withParam, "with-param")
 GK_ATOM(wizard, "wizard")
 GK_ATOM(wrap, "wrap")
 GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
 GK_ATOM(headerCSP, "x-content-security-policy")
 GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
+GK_ATOM(headerXFO, "x-frame-options")
 GK_ATOM(xml, "xml")
 GK_ATOM(xmlns, "xmlns")
 GK_ATOM(xmp, "xmp")
 GK_ATOM(xulcontentsgenerated, "xulcontentsgenerated")
 GK_ATOM(yes, "yes")
 GK_ATOM(z_index, "z-index")
 GK_ATOM(zeroDigit, "zero-digit")
 
--- a/content/base/src/nsMappedAttributeElement.h
+++ b/content/base/src/nsMappedAttributeElement.h
@@ -55,17 +55,17 @@ typedef void (*nsMapRuleToAttributesFunc
 
 typedef nsStyledElement nsMappedAttributeElementBase;
 
 class nsMappedAttributeElement : public nsMappedAttributeElementBase
 {
 
 protected:
 
-  nsMappedAttributeElement(nsINodeInfo *aNodeInfo)
+  nsMappedAttributeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsMappedAttributeElementBase(aNodeInfo)
   {}
 
 public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
 
--- a/content/base/src/nsNameSpaceManager.cpp
+++ b/content/base/src/nsNameSpaceManager.cpp
@@ -222,17 +222,17 @@ NameSpaceManagerImpl::GetNameSpaceID(con
     return nameSpaceID;
   }
 
   return kNameSpaceID_Unknown;
 }
 
 nsresult
 NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
-              nsINodeInfo* aNodeInfo, PRUint32 aFromParser)
+              already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser)
 {
   if (aElementType == kNameSpaceID_XHTML) {
     return NS_NewHTMLElement(aResult, aNodeInfo, aFromParser);
   }
 #ifdef MOZ_XUL
   if (aElementType == kNameSpaceID_XUL) {
     return NS_NewXULElement(aResult, aNodeInfo);
   }
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -48,16 +48,17 @@
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsBindingManager.h"
+#include "nsHashKeys.h"
 
 #ifdef MOZ_LOGGING
 // so we can get logging even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 
 #ifdef PR_LOGGING
@@ -67,34 +68,48 @@ static PRLogModuleInfo* gNodeInfoManager
 PLHashNumber
 nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
 {
   NS_ASSERTION(key, "Null key passed to nsNodeInfo::GetHashValue!");
 
   const nsINodeInfo::nsNodeInfoInner *node =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key);
 
-  // Is this an acceptable hash value?
-  return (PLHashNumber(NS_PTR_TO_INT32(node->mName)) & 0xffff) >> 8;
+  if (node->mName) {
+    return HashString(nsAtomString(node->mName));
+  }
+  return HashString(*(node->mNameString));
 }
 
 
 PRIntn
 nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
 {
   NS_ASSERTION(key1 && key2, "Null key passed to NodeInfoInnerKeyCompare!");
 
   const nsINodeInfo::nsNodeInfoInner *node1 =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key1);
   const nsINodeInfo::nsNodeInfoInner *node2 =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key2);
 
-  return (node1->mName == node2->mName &&
-          node1->mPrefix == node2->mPrefix &&
-          node1->mNamespaceID == node2->mNamespaceID);
+  if (node1->mPrefix != node2->mPrefix ||
+      node1->mNamespaceID != node2->mNamespaceID) {
+    return 0;
+  }
+
+  if (node1->mName) {
+    if (node2->mName) {
+      return (node1->mName == node2->mName);
+    }
+    return (node1->mName->Equals(*(node2->mNameString)));
+  }
+  if (node2->mName) {
+    return (node2->mName->Equals(*(node1->mNameString)));
+  }
+  return (node1->mNameString->Equals(*(node2->mNameString)));
 }
 
 
 nsNodeInfoManager::nsNodeInfoManager()
   : mDocument(nsnull),
     mPrincipal(nsnull),
     mTextNodeInfo(nsnull),
     mCommentNodeInfo(nsnull),
@@ -224,19 +239,45 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
   return nodeInfo;
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, nsINodeInfo** aNodeInfo)
 {
-  nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
-  *aNodeInfo = nsNodeInfoManager::GetNodeInfo(name, aPrefix, aNamespaceID).get();
-  return *aNodeInfo ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  NS_ASSERTION(!aName.IsEmpty(),
+               "Don't pass an empty string to GetNodeInfo, fix caller.");
+
+  nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID);
+
+  void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
+
+  if (node) {
+    nsINodeInfo* nodeInfo = static_cast<nsINodeInfo *>(node);
+
+    NS_ADDREF(*aNodeInfo = nodeInfo);
+
+    return NS_OK;
+  }
+
+  nsRefPtr<nsNodeInfo> newNodeInfo = nsNodeInfo::Create();
+  NS_ENSURE_TRUE(newNodeInfo, nsnull);
+  
+  nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
+  nsresult rv = newNodeInfo->Init(nameAtom, aPrefix, aNamespaceID, this);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PLHashEntry *he;
+  he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
+  NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
+
+  newNodeInfo.forget(aNodeInfo);
+
+  return NS_OK;
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
                                const nsAString& aNamespaceURI,
                                nsINodeInfo** aNodeInfo)
 {
--- a/content/base/src/nsNodeIterator.cpp
+++ b/content/base/src/nsNodeIterator.cpp
@@ -60,141 +60,112 @@ nsNodeIterator::NodePointer::NodePointer
                                          PRBool aBeforeNode) :
     mNode(aNode),
     mBeforeNode(aBeforeNode)
 {
 }
 
 PRBool nsNodeIterator::NodePointer::MoveToNext(nsINode *aRoot)
 {
-    NS_ASSERTION(mNode, "Iterating an uninitialized NodePointer");
+    if (!mNode)
+      return PR_FALSE;
 
     if (mBeforeNode) {
         mBeforeNode = PR_FALSE;
         return PR_TRUE;
     }
 
-    return MoveForward(aRoot, mNode, -1);
+    nsINode* child = mNode->GetFirstChild();
+    if (child) {
+        mNode = child;
+        return PR_TRUE;
+    }
+
+    return MoveForward(aRoot, mNode);
 }
 
 PRBool nsNodeIterator::NodePointer::MoveToPrevious(nsINode *aRoot)
 {
-    NS_ASSERTION(mNode, "Iterating an uninitialized NodePointer");
+    if (!mNode)
+      return PR_FALSE;
 
     if (!mBeforeNode) {
         mBeforeNode = PR_TRUE;
         return PR_TRUE;
     }
 
     if (mNode == aRoot)
         return PR_FALSE;
 
-    NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveToPrevious");
-    NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveToPrevious");
-    MoveBackward(mNodeParent, mIndexInParent);
+    MoveBackward(mNode->GetNodeParent(), mNode->GetPreviousSibling());
 
     return PR_TRUE;
 }
 
-void nsNodeIterator::NodePointer::AdjustAfterInsertion(nsINode *aRoot,
-                                                       nsINode *aContainer,
-                                                       PRInt32 aIndexInContainer)
-{
-    // If mNode is null or the root there is nothing to do. This also prevents
-    // valgrind from complaining about consuming uninitialized memory for
-    // mNodeParent and mIndexInParent
-    if (!mNode || mNode == aRoot)
-        return;
-
-    // check if earlier sibling was added
-    if (aContainer == mNodeParent && aIndexInContainer <= mIndexInParent)
-        mIndexInParent++;
-}
-
 void nsNodeIterator::NodePointer::AdjustAfterRemoval(nsINode *aRoot,
                                                      nsINode *aContainer,
                                                      nsIContent *aChild,
-                                                     PRInt32 aIndexInContainer)
+                                                     nsIContent *aPreviousSibling)
 {
-    // If mNode is null or the root there is nothing to do. This also prevents
-    // valgrind from complaining about consuming uninitialized memory for
-    // mNodeParent and mIndexInParent
+    // If mNode is null or the root there is nothing to do.
     if (!mNode || mNode == aRoot)
         return;
 
-    // Check if earlier sibling was removed.
-    if (aContainer == mNodeParent && aIndexInContainer < mIndexInParent) {
-        --mIndexInParent;
-        return;
-    }
-
     // check if ancestor was removed
     if (!nsContentUtils::ContentIsDescendantOf(mNode, aChild))
         return;
 
     if (mBeforeNode) {
 
-        if (MoveForward(aRoot, aContainer, aIndexInContainer-1))
+        // Try the next sibling
+        nsINode *nextSibling = aPreviousSibling ? aPreviousSibling->GetNextSibling()
+                                                : aContainer->GetFirstChild();
+
+        if (nextSibling) {
+            mNode = nextSibling;
+            return;
+        }
+
+        // Next try siblings of ancestors
+        if (MoveForward(aRoot, aContainer))
             return;
 
         // No suitable node was found so try going backwards
         mBeforeNode = PR_FALSE;
     }
 
-    MoveBackward(aContainer, aIndexInContainer);
+    MoveBackward(aContainer, aPreviousSibling);
 }
 
-PRBool nsNodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum)
+PRBool nsNodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aNode)
 {
     while (1) {
-        nsINode *node = aParent->GetChildAt(aChildNum+1);
-        if (node) {
-            mNode = node;
-            mIndexInParent = aChildNum+1;
-            mNodeParent = aParent;
+        if (aNode == aRoot)
+            break;
+
+        nsINode *sibling = aNode->GetNextSibling();
+        if (sibling) {
+            mNode = sibling;
             return PR_TRUE;
         }
-
-        if (aParent == aRoot)
-            break;
-
-        node = aParent;
-
-        if (node == mNode) {
-            NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveForward");
-            NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveForward");
-
-            aParent = mNodeParent;
-            aChildNum = mIndexInParent;
-        } else {
-            aParent = node->GetNodeParent();
-            aChildNum = aParent->IndexOf(node);
-        }
+        aNode = aNode->GetNodeParent();
     }
 
     return PR_FALSE;
 }
 
-void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, PRInt32 aChildNum)
+void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, nsINode *aNode)
 {
-    nsINode *sibling = aParent->GetChildAt(aChildNum-1);
-    mNode = aParent;
-    if (sibling) {
+    if (aNode) {
         do {
-            mIndexInParent = aChildNum-1;
-            mNodeParent = mNode;
-            mNode = sibling;
-
-            aChildNum = mNode->GetChildCount();
-            sibling = mNode->GetChildAt(aChildNum-1);
-        } while (sibling);
+            mNode = aNode;
+            aNode = aNode->GetLastChild();
+        } while (aNode);
     } else {
-        mNodeParent = mNode->GetNodeParent();
-        if (mNodeParent)
-            mIndexInParent = mNodeParent->IndexOf(mNode);
+        mNode = aParent;
     }
 }
 
 /*
  * Factories, constructors and destructors
  */
 
 nsNodeIterator::nsNodeIterator(nsINode *aRoot,
@@ -262,18 +233,17 @@ NS_IMETHODIMP nsNodeIterator::GetWhatToS
     return NS_OK;
 }
 
 /* readonly attribute nsIDOMNodeFilter filter; */
 NS_IMETHODIMP nsNodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
 {
     NS_ENSURE_ARG_POINTER(aFilter);
 
-    nsCOMPtr<nsIDOMNodeFilter> filter = mFilter;
-    filter.swap((*aFilter = nsnull));
+    NS_IF_ADDREF(*aFilter = mFilter);
 
     return NS_OK;
 }
 
 /* readonly attribute boolean expandEntityReferences; */
 NS_IMETHODIMP nsNodeIterator::GetExpandEntityReferences(PRBool *aExpandEntityReferences)
 {
     *aExpandEntityReferences = mExpandEntityReferences;
@@ -359,30 +329,19 @@ NS_IMETHODIMP nsNodeIterator::GetPointer
     *aBeforeNode = mPointer.mBeforeNode;
     return NS_OK;
 }
 
 /*
  * nsIMutationObserver interface
  */
 
-void nsNodeIterator::ContentInserted(nsIDocument *aDocument,
-                                     nsIContent *aContainer,
-                                     nsIContent *aChild,
-                                     PRInt32 aIndexInContainer)
+void nsNodeIterator::ContentRemoved(nsIDocument *aDocument,
+                                    nsIContent *aContainer,
+                                    nsIContent *aChild,
+                                    PRInt32 aIndexInContainer,
+                                    nsIContent *aPreviousSibling)
 {
     nsINode *container = NODE_FROM(aContainer, aDocument);
 
-    mPointer.AdjustAfterInsertion(mRoot, container, aIndexInContainer);
-    mWorkingPointer.AdjustAfterInsertion(mRoot, container, aIndexInContainer);
+    mPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
+    mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
 }
-
-
-void nsNodeIterator::ContentRemoved(nsIDocument *aDocument,
-                                    nsIContent *aContainer,
-                                    nsIContent *aChild,
-                                    PRInt32 aIndexInContainer)
-{
-    nsINode *container = NODE_FROM(aContainer, aDocument);
-
-    mPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
-    mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
-}
--- a/content/base/src/nsNodeIterator.h
+++ b/content/base/src/nsNodeIterator.h
@@ -62,46 +62,38 @@ public:
     NS_DECL_NSIDOMNODEITERATOR
 
     nsNodeIterator(nsINode *aRoot,
                    PRUint32 aWhatToShow,
                    nsIDOMNodeFilter *aFilter,
                    PRBool aExpandEntityReferences);
     virtual ~nsNodeIterator();
 
-    NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNodeIterator, nsIDOMNodeIterator)
 
 private:
     struct NodePointer {
         NodePointer() : mNode(nsnull) {};
         NodePointer(nsINode *aNode, PRBool aBeforeNode);
 
         typedef PRBool (NodePointer::*MoveToMethodType)(nsINode*);
         PRBool MoveToNext(nsINode *aRoot);
         PRBool MoveToPrevious(nsINode *aRoot);
 
-        PRBool MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum);
-        void MoveBackward(nsINode *aParent, PRInt32 aChildNum);
+        PRBool MoveForward(nsINode *aRoot, nsINode *aNode);
+        void MoveBackward(nsINode *aParent, nsINode *aNode);
 
-        void AdjustAfterInsertion(nsINode *aRoot, nsINode *aContainer, PRInt32 aIndexInContainer);
-        void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, PRInt32 aIndexInContainer);
+        void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, nsIContent *aPreviousSibling);
 
         void Clear() { mNode = nsnull; }
 
         nsINode *mNode;
-        // pointer to the parent of mNode. Can be dangling if mNode is null or
-        // points to the root
-        nsINode *mNodeParent;
         PRBool mBeforeNode;
-        // mNode's index in mNodeParent. Uninitialized if mNodeParent is null
-        // or dangling (per above comment).
-        PRInt32 mIndexInParent;
     };
 
     inline nsresult
     NextOrPrevNode(NodePointer::MoveToMethodType aMove,
                    nsIDOMNode **_retval);
 
     PRBool mDetached;
     NodePointer mPointer;
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -81,17 +81,16 @@ using namespace mozilla::dom;
       NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(                         \
         slots->mMutationObservers, nsIMutationObserver,           \
         func_, params_);                                          \
     }                                                             \
     node = node->GetNodeParent();                                 \
   } while (node);                                                 \
   PR_END_MACRO
 
-
 void
 nsNodeUtils::CharacterDataWillChange(nsIContent* aContent,
                                      CharacterDataChangeInfo* aInfo)
 {
   nsIDocument* doc = aContent->GetOwnerDoc();
   IMPL_MUTATION_NOTIFICATION(CharacterDataWillChange, aContent,
                              (doc, aContent, aInfo));
 }
@@ -163,17 +162,18 @@ nsNodeUtils::ContentInserted(nsINode* aC
 
   IMPL_MUTATION_NOTIFICATION(ContentInserted, aContainer,
                              (document, container, aChild, aIndexInContainer));
 }
 
 void
 nsNodeUtils::ContentRemoved(nsINode* aContainer,
                             nsIContent* aChild,
-                            PRInt32 aIndexInContainer)
+                            PRInt32 aIndexInContainer,
+                            nsIContent* aPreviousSibling)
 {
   NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
                   aContainer->IsNodeOfType(nsINode::eDOCUMENT),
                   "container must be an nsIContent or an nsIDocument");
   nsIContent* container;
   nsIDocument* doc = aContainer->GetOwnerDoc();
   nsIDocument* document;
   if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
@@ -181,17 +181,18 @@ nsNodeUtils::ContentRemoved(nsINode* aCo
     document = doc;
   }
   else {
     container = nsnull;
     document = static_cast<nsIDocument*>(aContainer);
   }
 
   IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
-                             (document, container, aChild, aIndexInContainer));
+                             (document, container, aChild, aIndexInContainer,
+                              aPreviousSibling));
 }
 
 void
 nsNodeUtils::ParentChainChanged(nsIContent *aContent)
 {
   // No need to notify observers on the parents since their parent
   // chain must have been changed too and so their observers were
   // notified at that time.
--- a/content/base/src/nsNodeUtils.h
+++ b/content/base/src/nsNodeUtils.h
@@ -121,17 +121,18 @@ public:
    * Send ContentRemoved notifications to nsIMutationObservers
    * @param aContainer        Node from which child was removed
    * @param aChild            Removed child
    * @param aIndexInContainer Index of removed child
    * @see nsIMutationObserver::ContentRemoved
    */
   static void ContentRemoved(nsINode* aContainer,
                              nsIContent* aChild,
-                             PRInt32 aIndexInContainer);
+                             PRInt32 aIndexInContainer,
+                             nsIContent* aPreviousSibling);
   /**
    * Send ParentChainChanged notifications to nsIMutationObservers
    * @param aContent  The piece of content that had its parent changed.
    * @see nsIMutationObserver::ParentChainChanged
    */
   static void ParentChainChanged(nsIContent *aContent);
 
   /**
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -539,17 +539,21 @@ nsObjectLoadingContent::OnStartRequest(n
       // because otherwise the default plug-in's catch-all behavior would
       // confuse things.
       (IsSupportedPlugin(mContentType) && 
        GetTypeOfContent(mContentType) == eType_Plugin)) {
     // Set the type we'll use for dispatch on the channel.  Otherwise we could
     // end up trying to dispatch to a nsFrameLoader, which will complain that
     // it couldn't find a way to handle application/octet-stream
 
-    chan->SetContentType(mContentType);
+    nsCAutoString typeHint, dummy;
+    NS_ParseContentType(mContentType, typeHint, dummy);
+    if (!typeHint.IsEmpty()) {
+      chan->SetContentType(typeHint);
+    }
   } else {
     mContentType = channelType;
   }
 
   nsCOMPtr<nsIURI> uri;
   chan->GetURI(getter_AddRefs(uri));
 
   if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM)) {
@@ -1432,17 +1436,21 @@ nsObjectLoadingContent::LoadObject(nsIUR
   // Referrer
   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
   if (httpChan) {
     httpChan->SetReferrer(doc->GetDocumentURI());
   }
 
   // MIME Type hint
   if (!aTypeHint.IsEmpty()) {
-    chan->SetContentType(aTypeHint);
+    nsCAutoString typeHint, dummy;
+    NS_ParseContentType(aTypeHint, typeHint, dummy);
+    if (!typeHint.IsEmpty()) {
+      chan->SetContentType(typeHint);
+    }
   }
 
   // Set up the channel's principal and such, like nsDocShell::DoURILoad does
   PRBool inheritPrincipal;
   rv = NS_URIChainHasFlags(aURI,
                            nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
                            &inheritPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -310,17 +310,18 @@ nsRange::ContentInserted(nsIDocument* aD
     ++mEndOffset;
   }
 }
 
 void
 nsRange::ContentRemoved(nsIDocument* aDocument,
                         nsIContent* aContainer,
                         nsIContent* aChild,
-                        PRInt32 aIndexInContainer)
+                        PRInt32 aIndexInContainer,
+                        nsIContent* aPreviousSibling)
 {
   NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
 
   nsINode* container = NODE_FROM(aContainer, aDocument);
 
   // Adjust position if a sibling was removed...
   if (container == mStartParent) {
     if (aIndexInContainer < mStartOffset) {
@@ -348,16 +349,18 @@ nsRange::ContentRemoved(nsIDocument* aDo
 void
 nsRange::ParentChainChanged(nsIContent *aContent)
 {
   NS_ASSERTION(mRoot == aContent, "Wrong ParentChainChanged notification?");
   nsINode* newRoot = IsValidBoundary(mStartParent);
   NS_ASSERTION(newRoot, "No valid boundary or root found!");
   NS_ASSERTION(newRoot == IsValidBoundary(mEndParent),
                "Start parent and end parent give different root!");
+  // This is safe without holding a strong ref to self as long as the change
+  // of mRoot is the last thing in DoSetRange.
   DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, newRoot);
 }
 
 /********************************************************
  * Utilities for comparing points: API from nsIDOMNSRange
  ********************************************************/
 NS_IMETHODIMP
 nsRange::IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, PRBool* aResult)
@@ -468,16 +471,18 @@ nsRange::DoSetRange(nsINode* aStartN, PR
     }
   }
  
   mStartParent = aStartN;
   mStartOffset = aStartOffset;
   mEndParent = aEndN;
   mEndOffset = aEndOffset;
   mIsPositioned = !!mStartParent;
+  // This needs to be the last thing this function does.  See comment
+  // in ParentChainChanged.
   mRoot = aRoot;
 }
 
 static PRInt32
 IndexOf(nsIDOMNode* aChildNode)
 {
   // convert node to nsIContent, so that we can find the child index
 
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -92,30 +92,22 @@ public:
   NS_DECL_NSIDOMNSRANGE
   
   // nsIRange interface
   virtual nsINode* GetCommonAncestor() const;
   virtual void Reset();
   virtual nsresult SetStart(nsINode* aParent, PRInt32 aOffset);
   virtual nsresult SetEnd(nsINode* aParent, PRInt32 aOffset);
   virtual nsresult CloneRange(nsIRange** aNewRange) const;
-  
+
   // nsIMutationObserver methods
-  virtual void CharacterDataChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent,
-                                    CharacterDataChangeInfo* aChangeInfo);
-  virtual void ContentInserted(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aChild,
-                               PRInt32 aIndexInContainer);
-  virtual void ContentRemoved(nsIDocument* aDocument,
-                              nsIContent* aContainer,
-                              nsIContent* aChild,
-                              PRInt32 aIndexInContainer);
-  virtual void ParentChainChanged(nsIContent *aContent);
+  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+  NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
 
 private:
   // no copy's or assigns
   nsRange(const nsRange&);
   nsRange& operator=(const nsRange&);
 
   nsINode* IsValidBoundary(nsINode* aNode);
  
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -53,17 +53,17 @@ class nsICSSStyleRule;
 
 typedef nsGenericElement nsStyledElementBase;
 
 class nsStyledElement : public nsStyledElementBase
 {
 
 protected:
 
-  inline nsStyledElement(nsINodeInfo *aNodeInfo)
+  inline nsStyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsStyledElementBase(aNodeInfo)
   {}
 
 public:
 
   // nsIContent interface methods
   virtual nsIAtom* GetClassAttributeName() const;
   virtual nsIAtom* GetIDAttributeName() const;
--- a/content/base/src/nsTextNode.cpp
+++ b/content/base/src/nsTextNode.cpp
@@ -54,17 +54,17 @@
  * class used to implement attr() generated content
  */
 class nsAttributeTextNode : public nsTextNode,
                             public nsStubMutationObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   
-  nsAttributeTextNode(nsINodeInfo *aNodeInfo,
+  nsAttributeTextNode(already_AddRefed<nsINodeInfo> aNodeInfo,
                       PRInt32 aNameSpaceID,
                       nsIAtom* aAttrName) :
     nsTextNode(aNodeInfo),
     mGrandparent(nsnull),
     mNameSpaceID(aNameSpaceID),
     mAttrName(aAttrName)
   {
     NS_ASSERTION(mNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
@@ -82,17 +82,18 @@ public:
                               PRBool aNullParent = PR_TRUE);
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
   virtual nsGenericDOMDataNode *CloneDataNode(nsINodeInfo *aNodeInfo,
                                               PRBool aCloneText) const
   {
-    nsAttributeTextNode *it = new nsAttributeTextNode(aNodeInfo,
+    nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+    nsAttributeTextNode *it = new nsAttributeTextNode(ni.forget(),
                                                       mNameSpaceID,
                                                       mAttrName);
     if (it && aCloneText) {
       it->mText = mText;
     }
 
     return it;
   }
@@ -124,39 +125,39 @@ NS_NewTextNode(nsIContent** aInstancePtr
 
   *aInstancePtrResult = nsnull;
 
   nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetTextNodeInfo();
   if (!ni) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  nsIContent *instance = new nsTextNode(ni);
+  nsTextNode *instance = new nsTextNode(ni.forget());
   if (!instance) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aInstancePtrResult = instance);
 
   return NS_OK;
 }
 
-nsTextNode::nsTextNode(nsINodeInfo *aNodeInfo)
+nsTextNode::nsTextNode(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericTextNode(aNodeInfo)
 {
 }
 
 nsTextNode::~nsTextNode()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(nsTextNode, nsGenericDOMDataNode)
 NS_IMPL_RELEASE_INHERITED(nsTextNode, nsGenericDOMDataNode)
 
-DOMCI_DATA(Text, nsTextNode)
+DOMCI_NODE_DATA(Text, nsTextNode)
 
 // QueryInterface implementation for nsTextNode
 NS_INTERFACE_TABLE_HEAD(nsTextNode)
   NS_NODE_INTERFACE_TABLE3(nsTextNode, nsIDOMNode, nsIDOMText,
                            nsIDOMCharacterData)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Text, new nsText3Tearoff(this))
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextNode)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Text)
@@ -192,17 +193,18 @@ PRBool
 nsTextNode::IsNodeOfType(PRUint32 aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eTEXT | eDATA_NODE));
 }
 
 nsGenericDOMDataNode*
 nsTextNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
 {
-  nsTextNode *it = new nsTextNode(aNodeInfo);
+  nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+  nsTextNode *it = new nsTextNode(ni.forget());
   if (it && aCloneText) {
     it->mText = mText;
   }
 
   return it;
 }
 
 nsresult
@@ -276,17 +278,18 @@ NS_NewAttributeContent(nsNodeInfoManager
   
   *aResult = nsnull;
 
   nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetTextNodeInfo();
   if (!ni) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  nsAttributeTextNode* textNode = new nsAttributeTextNode(ni, aNameSpaceID,
+  nsAttributeTextNode* textNode = new nsAttributeTextNode(ni.forget(),
+                                                          aNameSpaceID,
                                                           aAttrName);
   if (!textNode) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aResult = textNode);
 
   return NS_OK;
@@ -336,25 +339,22 @@ void
 nsAttributeTextNode::AttributeChanged(nsIDocument* aDocument,
                                       nsIContent* aContent,
                                       PRInt32 aNameSpaceID,
                                       nsIAtom* aAttribute,
                                       PRInt32 aModType)
 {
   if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
       aContent == mGrandparent) {
-    // Since UpdateText notifies, do it asynchronously.  Note that if we get
-    // unbound while the event is up that's ok -- we'll just have no
-    // grandparent when it fires, and will do nothing.    
-    // XXXbz ideally we'd either process this on layout flushes or do it right
-    // after nsIMutationObserver notifications are over or something, instead
-    // of doing it fully async.
+    // Since UpdateText notifies, do it when it's safe to run script.  Note
+    // that if we get unbound while the event is up that's ok -- we'll just
+    // have no grandparent when it fires, and will do nothing.
     void (nsAttributeTextNode::*update)() = &nsAttributeTextNode::UpdateText;
     nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, update);
-    NS_DispatchToCurrentThread(ev);
+    nsContentUtils::AddScriptRunner(ev);
   }
 }
 
 void
 nsAttributeTextNode::NodeWillBeDestroyed(const nsINode* aNode)
 {
   NS_ASSERTION(aNode == static_cast<nsINode*>(mGrandparent), "Wrong node!");
   mGrandparent = nsnull;
--- a/content/base/src/nsTextNode.h
+++ b/content/base/src/nsTextNode.h
@@ -52,17 +52,17 @@
 
 /**
  * Class used to implement DOM text nodes
  */
 class nsTextNode : public nsGenericTextNode,
                    public nsIDOMText
 {
 public:
-  nsTextNode(nsINodeInfo *aNodeInfo);
+  nsTextNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsTextNode();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_IMPL_NSIDOMNODE_USING_GENERIC_DOM_DATA
 
@@ -73,13 +73,15 @@ public:
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)
 
   // nsIContent
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
 
   nsresult BindToAttribute(nsIAttribute* aAttr);
   nsresult UnbindFromAttribute();
 
+  virtual nsXPCClassInfo* GetClassInfo();
+
 #ifdef DEBUG
   virtual void List(FILE* out, PRInt32 aIndent) const;
   virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;
 #endif
 };
--- a/content/base/src/nsTreeWalker.cpp
+++ b/content/base/src/nsTreeWalker.cpp
@@ -1,11 +1,11 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+/* ***** 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,
@@ -17,16 +17,17 @@
  *
  * The Initial Developer of the Original Code is
  * Jonas Sicking.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jonas Sicking <sicking@bigfoot.com> (Original Author)
+ *   Craig Topper  <craig.topper@gmail.com>
  *
  * 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
@@ -42,32 +43,28 @@
  */
 
 #include "nsTreeWalker.h"
 
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsDOMError.h"
 
-#include "nsIContent.h"
-#include "nsIDocument.h"
-
 #include "nsContentUtils.h"
 
 /*
  * Factories, constructors and destructors
  */
 
 nsTreeWalker::nsTreeWalker(nsINode *aRoot,
                            PRUint32 aWhatToShow,
                            nsIDOMNodeFilter *aFilter,
                            PRBool aExpandEntityReferences) :
     nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
-    mCurrentNode(aRoot),
-    mPossibleIndexesPos(-1)
+    mCurrentNode(aRoot)
 {
 }
 
 nsTreeWalker::~nsTreeWalker()
 {
     /* destructor code */
 }
 
@@ -114,18 +111,17 @@ NS_IMETHODIMP nsTreeWalker::GetWhatToSho
     return NS_OK;
 }
 
 /* readonly attribute nsIDOMNodeFilter filter; */
 NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter)
 {
     NS_ENSURE_ARG_POINTER(aFilter);
 
-    nsCOMPtr<nsIDOMNodeFilter> filter = mFilter;
-    filter.swap((*aFilter = nsnull));
+    NS_IF_ADDREF(*aFilter = mFilter);
 
     return NS_OK;
 }
 
 /* readonly attribute boolean expandEntityReferences; */
 NS_IMETHODIMP
 nsTreeWalker::GetExpandEntityReferences(PRBool *aExpandEntityReferences)
 {
@@ -147,423 +143,302 @@ NS_IMETHODIMP nsTreeWalker::GetCurrentNo
 NS_IMETHODIMP nsTreeWalker::SetCurrentNode(nsIDOMNode * aCurrentNode)
 {
     NS_ENSURE_TRUE(aCurrentNode, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 
     nsresult rv = nsContentUtils::CheckSameOrigin(mRoot, aCurrentNode);
     NS_ENSURE_SUCCESS(rv, rv);
 
     mCurrentNode = do_QueryInterface(aCurrentNode);
-    mPossibleIndexes.Clear();
-    mPossibleIndexesPos = -1;
 
     return NS_OK;
 }
 
 /*
  * nsIDOMTreeWalker functions
  */
 
 /* nsIDOMNode parentNode (); */
 NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval)
 {
     *_retval = nsnull;
-    
+
     nsresult rv;
 
-    PRInt32 indexPos = mPossibleIndexesPos;
     nsCOMPtr<nsINode> node = mCurrentNode;
-    
+
     while (node && node != mRoot) {
         node = node->GetNodeParent();
-        
-        indexPos--;
 
         if (node) {
             PRInt16 filtered;
             rv = TestNode(node, &filtered);
             NS_ENSURE_SUCCESS(rv, rv);
             if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
                 mCurrentNode = node;
-                mPossibleIndexesPos = indexPos >= 0 ? indexPos : -1;
-
                 return CallQueryInterface(node, _retval);
             }
         }
     }
 
     return NS_OK;
 }
 
 /* nsIDOMNode firstChild (); */
 NS_IMETHODIMP nsTreeWalker::FirstChild(nsIDOMNode **_retval)
 {
-    *_retval = nsnull;
-
-    nsCOMPtr<nsINode> result;
-    nsresult rv =  FirstChildOf(mCurrentNode,
-                                PR_FALSE,
-                                mPossibleIndexesPos + 1,
-                                getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+    return FirstChildInternal(PR_FALSE, _retval);
 }
 
 /* nsIDOMNode lastChild (); */
 NS_IMETHODIMP nsTreeWalker::LastChild(nsIDOMNode **_retval)
 {
-    *_retval = nsnull;
-
-    nsCOMPtr<nsINode> result;
-    nsresult rv =  FirstChildOf(mCurrentNode,
-                                PR_TRUE,
-                                mPossibleIndexesPos + 1,
-                                getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+    return FirstChildInternal(PR_TRUE, _retval);
 }
 
 /* nsIDOMNode previousSibling (); */
 NS_IMETHODIMP nsTreeWalker::PreviousSibling(nsIDOMNode **_retval)
 {
-    *_retval = nsnull;
-
-    nsCOMPtr<nsINode> result;
-    nsresult rv = NextSiblingOf(mCurrentNode,
-                                PR_TRUE,
-                                mPossibleIndexesPos,
-                                getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+    return NextSiblingInternal(PR_TRUE, _retval);
 }
 
 /* nsIDOMNode nextSibling (); */
 NS_IMETHODIMP nsTreeWalker::NextSibling(nsIDOMNode **_retval)
 {
-    *_retval = nsnull;
-
-    nsCOMPtr<nsINode> result;
-    nsresult rv = NextSiblingOf(mCurrentNode,
-                                PR_FALSE,
-                                mPossibleIndexesPos,
-                                getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+    return NextSiblingInternal(PR_FALSE, _retval);
 }
 
 /* nsIDOMNode previousNode (); */
 NS_IMETHODIMP nsTreeWalker::PreviousNode(nsIDOMNode **_retval)
 {
+    nsresult rv;
+    PRInt16 filtered;
+
     *_retval = nsnull;
 
-    nsCOMPtr<nsINode> result;
-    nsresult rv = NextInDocumentOrderOf(mCurrentNode,
-                                        PR_TRUE,
-                                        mPossibleIndexesPos,
-                                        getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsINode> node = mCurrentNode;
+
+    while (node != mRoot) {
+        while (nsINode *previousSibling = node->GetPreviousSibling()) {
+            node = previousSibling;
+
+            rv = TestNode(node, &filtered);
+            NS_ENSURE_SUCCESS(rv, rv);
+
+            nsINode *lastChild;
+            while (filtered != nsIDOMNodeFilter::FILTER_REJECT &&
+                   (lastChild = node->GetLastChild())) {
+                node = lastChild;
+                rv = TestNode(node, &filtered);
+                NS_ENSURE_SUCCESS(rv, rv);
+            }
 
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+            if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
+                mCurrentNode = node;
+                return CallQueryInterface(node, _retval);
+            }
+        }
+
+        if (node == mRoot)
+            break;
+
+        node = node->GetNodeParent();
+        if (!node)
+            break;
+
+        rv = TestNode(node, &filtered);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
+            mCurrentNode = node;
+            return CallQueryInterface(node, _retval);
+        }
+    }
+
+    return NS_OK;
 }
 
 /* nsIDOMNode nextNode (); */
 NS_IMETHODIMP nsTreeWalker::NextNode(nsIDOMNode **_retval)
 {
+    nsresult rv;
+    PRInt16 filtered = nsIDOMNodeFilter::FILTER_ACCEPT; // pre-init for inner loop
+
     *_retval = nsnull;
 
-    nsCOMPtr<nsINode> result;
-    nsresult rv = NextInDocumentOrderOf(mCurrentNode,
-                                        PR_FALSE,
-                                        mPossibleIndexesPos,
-                                        getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsINode> node = mCurrentNode;
+
+    while (1) {
+
+        nsINode *firstChild;
+        while (filtered != nsIDOMNodeFilter::FILTER_REJECT &&
+               (firstChild = node->GetFirstChild())) {
+            node = firstChild;
+
+            rv = TestNode(node, &filtered);
+            NS_ENSURE_SUCCESS(rv, rv);
+
+            if (filtered ==  nsIDOMNodeFilter::FILTER_ACCEPT) {
+                // Node found
+                mCurrentNode = node;
+                return CallQueryInterface(node, _retval);
+            }
+        }
+
+        nsINode *sibling = nsnull;
+        nsINode *temp = node;
+        do {
+            if (temp == mRoot)
+                break;
 
-    return result ? CallQueryInterface(result, _retval) : NS_OK;
+            sibling = temp->GetNextSibling();
+            if (sibling)
+                break;
+
+            temp = temp->GetNodeParent();
+        } while (temp);
+
+        if (!sibling)
+            break;
+
+        node = sibling;
+
+        // Found a sibling. Either ours or ancestor's
+        rv = TestNode(node, &filtered);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        if (filtered ==  nsIDOMNodeFilter::FILTER_ACCEPT) {
+            // Node found
+            mCurrentNode = node;
+            return CallQueryInterface(node, _retval);
+        }
+    }
+
+    return NS_OK;
 }
 
-
 /*
  * nsTreeWalker helper functions
  */
 
 /*
- * Finds the first child of aNode and returns it. If a child is
- * found, mCurrentNode is set to that child.
- * @param aNode     Node to search for children.
- * @param aReversed Reverses search to find the last child instead
- *                  of first.
- * @param aIndexPos Position of aNode in mPossibleIndexes.
+ * Implements FirstChild and LastChild which only vary in which direction
+ * they search.
+ * @param aReversed Controls whether we search forwards or backwards
  * @param _retval   Returned node. Null if no child is found
  * @returns         Errorcode
  */
-nsresult
-nsTreeWalker::FirstChildOf(nsINode* aNode,
-                           PRBool aReversed,
-                           PRInt32 aIndexPos,
-                           nsINode** _retval)
-{
-    *_retval = nsnull;
-    PRInt32 start = aReversed ? (PRInt32)aNode->GetChildCount() : -1;
-
-    return ChildOf(aNode, start, aReversed, aIndexPos, _retval);
-}
-
-/*
- * Finds the following sibling of aNode and returns it. If a sibling
- * is found, mCurrentNode is set to that node.
- * @param aNode     Node to start search at.
- * @param aReversed Reverses search to find the previous sibling
- *                  instead of next.
- * @param aIndexPos Position of aNode in mPossibleIndexes.
- * @param _retval   Returned node. Null if no sibling is found
- * @returns         Errorcode
- */
-nsresult
-nsTreeWalker::NextSiblingOf(nsINode* aNode,
-                            PRBool aReversed,
-                            PRInt32 aIndexPos,
-                            nsINode** _retval)
+nsresult nsTreeWalker::FirstChildInternal(PRBool aReversed, nsIDOMNode **_retval)
 {
     nsresult rv;
-    nsCOMPtr<nsINode> node = aNode;
     PRInt16 filtered;
-    PRInt32 childNum;
+
+    *_retval = nsnull;
+
+    nsCOMPtr<nsINode> node = aReversed ? mCurrentNode->GetLastChild()
+                                       : mCurrentNode->GetFirstChild();
+
+    while (node) {
+        rv = TestNode(node, &filtered);
+        NS_ENSURE_SUCCESS(rv, rv);
 
-    if (node == mRoot) {
-        *_retval = nsnull;
-        return NS_OK;
+        switch (filtered) {
+            case nsIDOMNodeFilter::FILTER_ACCEPT:
+                // Node found
+                mCurrentNode = node;
+                return CallQueryInterface(node, _retval);
+            case nsIDOMNodeFilter::FILTER_SKIP: {
+                    nsINode *child = aReversed ? node->GetLastChild()
+                                               : node->GetFirstChild();
+                    if (child) {
+                        node = child;
+                        continue;
+                    }
+                    break;
+                }
+            case nsIDOMNodeFilter::FILTER_REJECT:
+                // Keep searching
+                break;
+        }
+
+        do {
+            nsINode *sibling = aReversed ? node->GetPreviousSibling()
+                                         : node->GetNextSibling();
+            if (sibling) {
+                node = sibling;
+                break;
+            }
+            nsINode *parent = node->GetNodeParent();
+
+            if (!parent || parent == mRoot || parent == mCurrentNode) {
+                return NS_OK;
+            }
+
+        } while (node);
     }
 
-    while (1) {
-        nsCOMPtr<nsINode> parent = node->GetNodeParent();
-
-        if (!parent)
-            break;
-
-        childNum = IndexOf(parent, node, aIndexPos);
-        NS_ENSURE_TRUE(childNum >= 0, NS_ERROR_UNEXPECTED);
-
-        // Search siblings
-        rv = ChildOf(parent, childNum, aReversed, aIndexPos, _retval);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        if (*_retval)
-            return NS_OK;
-
-        // Is parent the root?
-        if (parent == mRoot)
-            break;
-
-        // Is parent transparent in filtered view?
-        rv = TestNode(parent, &filtered);
-        NS_ENSURE_SUCCESS(rv, rv);
-        if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT)
-            break;
-
-        node = parent;
-        aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1;
-    }
-
-    *_retval = nsnull;
     return NS_OK;
 }
 
 /*
- * Finds the next node in document order of aNode and returns it.
- * If a node is found, mCurrentNode is set to that node.
- * @param aNode     Node to start search at.
- * @param aReversed Reverses search to find the preceding node
- *                  instead of next.
- * @param aIndexPos Position of aNode in mPossibleIndexes.
- * @param _retval   Returned node. Null if no node is found
- * @returns         Errorcode
- */
-nsresult
-nsTreeWalker::NextInDocumentOrderOf(nsINode* aNode,
-                                    PRBool aReversed,
-                                    PRInt32 aIndexPos,
-                                    nsINode** _retval)
-{
-    nsresult rv;
-
-    if (!aReversed) {
-        rv = FirstChildOf(aNode, aReversed, aIndexPos+1, _retval);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        if (*_retval)
-            return NS_OK;
-    }
-
-    if (aNode == mRoot){
-        *_retval = nsnull;
-        return NS_OK;
-    }
-
-    nsCOMPtr<nsINode> node = aNode;
-    nsCOMPtr<nsINode> currentNodeBackup = mCurrentNode;
-    PRInt16 filtered;
-    PRInt32 childNum;
-
-    while (1) {
-        // Get our index in the parent
-        nsCOMPtr<nsINode> parent = node->GetNodeParent();
-        if (!parent)
-            break;
-
-        childNum = IndexOf(parent, node, aIndexPos);
-        NS_ENSURE_TRUE(childNum >= 0, NS_ERROR_UNEXPECTED);
-
-        // Search siblings
-        nsCOMPtr<nsINode> sibling;
-        rv = ChildOf(parent, childNum, aReversed, aIndexPos,
-                     getter_AddRefs(sibling));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        if (sibling) {
-            if (aReversed) {
-                // in reversed walking we first test if there are
-                // any children. I don't like this piece of code :(
-                nsCOMPtr<nsINode> child = sibling;
-                while (child) {
-                    sibling = child;
-                    rv = FirstChildOf(sibling,
-                                      PR_TRUE,
-                                      aIndexPos,
-                                      getter_AddRefs(child));
-                    if (NS_FAILED(rv)) {
-                        // ChildOf set mCurrentNode and then something
-                        // failed. Restore the old value before returning
-                        mCurrentNode = currentNodeBackup;
-                        mPossibleIndexesPos = -1;
-                        return rv;
-                    }
-                }
-            }
-            *_retval = sibling;
-            NS_ADDREF(*_retval);
-            return NS_OK;
-        }
-
-        aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1;
-
-        if (aReversed) {
-            // Is parent transparent in filtered view?
-            rv = TestNode(parent, &filtered);
-            NS_ENSURE_SUCCESS(rv, rv);
-            if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
-                mCurrentNode = parent;
-                mPossibleIndexesPos = aIndexPos;
-                *_retval = parent;
-                NS_ADDREF(*_retval);
-                return NS_OK;
-            }
-        }
-
-        // Is parent the root?
-        if (parent == mRoot)
-            break;
-
-        node = parent;
-    }
-
-    *_retval = nsnull;
-    return NS_OK;
-}
-
-/*
- * Finds the first child of aNode after child N and returns it. If a
- * child is found, mCurrentNode is set to that child
- * @param aNode     Node to search for children
- * @param childNum  Child number to start search from. The child with
- *                  this number is not searched
- * @param aReversed Reverses search to find the last child instead
- *                  of first
- * @param aIndexPos Position of aNode in mPossibleIndexes
+ * Implements NextSibling and PreviousSibling which only vary in which
+ * direction they search.
+ * @param aReversed Controls whether we search forwards or backwards
  * @param _retval   Returned node. Null if no child is found
  * @returns         Errorcode
  */
-nsresult
-nsTreeWalker::ChildOf(nsINode* aNode,
-                      PRInt32 childNum,
-                      PRBool aReversed,
-                      PRInt32 aIndexPos,
-                      nsINode** _retval)
+nsresult nsTreeWalker::NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retval)
+
 {
+    nsresult rv;
     PRInt16 filtered;
-    nsresult rv;
+
+    *_retval = nsnull;
+
+    nsCOMPtr<nsINode> node = mCurrentNode;
+
+    if (node == mRoot)
+        return NS_OK;
+
+    while (1) {
+        nsCOMPtr<nsINode> sibling = aReversed ? node->GetPreviousSibling()
+                                              : node->GetNextSibling();
+
+        while (sibling) {
+            rv = TestNode(sibling, &filtered);
+            NS_ENSURE_SUCCESS(rv, rv);
 
-    PRInt32 dir = aReversed ? -1 : 1;
-
-    // Step through all children
-    PRInt32 i = childNum;
-    while (1) {
-        i += dir;
-        nsCOMPtr<nsINode> child = aNode->GetChildAt(i);
-        if (!child) {
-            break;
+            switch (filtered) {
+                case nsIDOMNodeFilter::FILTER_ACCEPT:
+                    // Node found
+                    mCurrentNode = sibling;
+                    return CallQueryInterface(sibling, _retval);
+                case nsIDOMNodeFilter::FILTER_SKIP: {
+                        nsINode *firstChild = aReversed ? sibling->GetLastChild()
+                                                        : sibling->GetFirstChild();
+                        if (firstChild) {
+                            sibling = firstChild;
+                            continue;
+                        }
+                    }
+                    break;
+                case nsIDOMNodeFilter::FILTER_REJECT:
+                    // Keep searching
+                    break;
+            }
+            sibling = aReversed ? sibling->GetPreviousSibling()
+                                : sibling->GetNextSibling();
         }
 
-        rv = TestNode(child, &filtered);
-        NS_ENSURE_SUCCESS(rv, rv);
+        node = node->GetNodeParent();
 
-        switch (filtered) {
-            case nsIDOMNodeFilter::FILTER_ACCEPT:
-                // Child found
-                mCurrentNode = child;
-                mPossibleIndexesPos = aIndexPos;
-                *_retval = child;
-                NS_ADDREF(*_retval);
-
-                SetChildIndex(aIndexPos, i);
-
-                return NS_OK;
+        if (!node || node == mRoot)
+            break;
 
-            case nsIDOMNodeFilter::FILTER_SKIP:
-                // Search children
-                rv = FirstChildOf(child, aReversed, aIndexPos+1, _retval);
-                NS_ENSURE_SUCCESS(rv, rv);
-
-                if (*_retval) {
-                    SetChildIndex(aIndexPos, i);
-                    return NS_OK;
-                }
-                break;
-
-            case nsIDOMNodeFilter::FILTER_REJECT:
-                // Keep searching
-                break;
-
-            default:
-                return NS_ERROR_UNEXPECTED;
-        }
+        // Is parent transparent in filtered view?
+        rv = TestNode(node, &filtered);
+        NS_ENSURE_SUCCESS(rv, rv);
+        if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT)
+            break;
     }
 
-    *_retval = nsnull;
     return NS_OK;
 }
-
-/*
- * Gets the child index of a node within its parent. Gets a possible index
- * from mPossibleIndexes to gain speed. If the value in mPossibleIndexes
- * isn't correct it'll get the index the usual way
- * @param aParent   in which to get the index
- * @param aChild    node to get the index of
- * @param aIndexPos position in mPossibleIndexes that contains the possible.
- *                  index
- * @returns         resulting index
- */
-PRInt32 nsTreeWalker::IndexOf(nsINode* aParent,
-                              nsINode* aChild,
-                              PRInt32 aIndexPos)
-{
-    if (aIndexPos >= 0 && aIndexPos < PRInt32(mPossibleIndexes.Length())) {
-        PRInt32 possibleIndex = mPossibleIndexes.ElementAt(aIndexPos);
-        if (aChild == aParent->GetChildAt(possibleIndex)) {
-            return possibleIndex;
-        }
-    }
-
-    return aParent->IndexOf(aChild);
-}
--- a/content/base/src/nsTreeWalker.h
+++ b/content/base/src/nsTreeWalker.h
@@ -1,11 +1,11 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+/* ***** 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,
@@ -17,16 +17,17 @@
  *
  * The Initial Developer of the Original Code is
  * Jonas Sicking.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jonas Sicking <sicking@bigfoot.com> (Original Author)
+ *   Craig Topper  <craig.topper@gmail.com>
  *
  * 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
@@ -65,114 +66,30 @@ public:
                  nsIDOMNodeFilter *aFilter,
                  PRBool aExpandEntityReferences);
     virtual ~nsTreeWalker();
 
     NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeWalker)
 
 private:
     nsCOMPtr<nsINode> mCurrentNode;
-    
-    /*
-     * Array with all child indexes up the tree. This should only be
-     * considered a hint and the value could be wrong.
-     */
-    nsAutoTArray<PRInt32, 8> mPossibleIndexes;
-    
+
     /*
-     * Position of mCurrentNode in mPossibleIndexes
-     */
-    PRInt32 mPossibleIndexesPos;
-    
-    /*
-     * Finds the first child of aNode and returns it. If a child is
-     * found, mCurrentNode is set to that child.
-     * @param aNode     Node to search for children.
-     * @param aReversed Reverses search to find the last child instead
-     *                  of first.
-     * @param aIndexPos Position of aNode in mPossibleIndexes.
+     * Implements FirstChild and LastChild which only vary in which direction
+     * they search.
+     * @param aReversed Controls whether we search forwards or backwards
      * @param _retval   Returned node. Null if no child is found
      * @returns         Errorcode
      */
-    nsresult FirstChildOf(nsINode* aNode,
-                          PRBool aReversed,
-                          PRInt32 aIndexPos,
-                          nsINode** _retval);
+    nsresult FirstChildInternal(PRBool aReversed, nsIDOMNode **_retval);
 
     /*
-     * Finds the following sibling of aNode and returns it. If a sibling
-     * is found, mCurrentNode is set to that node.
-     * @param aNode     Node to start search at.
-     * @param aReversed Reverses search to find the previous sibling
-     *                  instead of next.
-     * @param aIndexPos Position of aNode in mPossibleIndexes.
-     * @param _retval   Returned node. Null if no sibling is found
-     * @returns         Errorcode
-     */
-    nsresult NextSiblingOf(nsINode* aNode,
-                           PRBool aReversed,
-                           PRInt32 aIndexPos,
-                           nsINode** _retval);
-                           
-    /*
-     * Finds the next node in document order of aNode and returns it.
-     * If a node is found, mCurrentNode is set to that node.
-     * @param aNode     Node to start search at.
-     * @param aReversed Reverses search to find the preceding node
-     *                  instead of next.
-     * @param aIndexPos Position of aNode in mPossibleIndexes.
-     * @param _retval   Returned node. Null if no node is found
-     * @returns         Errorcode
-     */
-    nsresult NextInDocumentOrderOf(nsINode* aNode,
-                                   PRBool aReversed,
-                                   PRInt32 aIndexPos,
-                                   nsINode** _retval);
-
-    /*
-     * Finds the first child of aNode after child N and returns it. If a
-     * child is found, mCurrentNode is set to that child
-     * @param aNode     Node to search for children
-     * @param childNum  Child number to start search from. The child with
-     *                  this number is not searched
-     * @param aReversed Reverses search to find the last child instead
-     *                  of first
-     * @param aIndexPos Position of aNode in mPossibleIndexes
+     * Implements NextSibling and PreviousSibling which only vary in which
+     * direction they search.
+     * @param aReversed Controls whether we search forwards or backwards
      * @param _retval   Returned node. Null if no child is found
      * @returns         Errorcode
      */
-    nsresult ChildOf(nsINode* aNode,
-                     PRInt32 childNum,
-                     PRBool aReversed,
-                     PRInt32 aIndexPos,
-                     nsINode** _retval);
-
-    /*
-     * Gets the child index of a node within its parent. Gets a possible index
-     * from mPossibleIndexes to gain speed. If the value in mPossibleIndexes
-     * isn't correct it'll get the index the usual way.
-     * @param aParent   in which to get the index
-     * @param aChild    node to get the index of
-     * @param aIndexPos position in mPossibleIndexes that contains the possible.
-     *                  index
-     * @returns         resulting index
-     */
-    PRInt32 IndexOf(nsINode* aParent,
-                    nsINode* aChild,
-                    PRInt32 aIndexPos);
-
-    /*
-     * Sets the child index at the specified level. It doesn't matter if this
-     * fails since mPossibleIndexes should only be considered a hint
-     * @param aIndexPos   position in mPossibleIndexes to set
-     * @param aChildIndex child index at specified position
-     */
-    void SetChildIndex(PRInt32 aIndexPos, PRInt32 aChildIndex)
-    {
-        if (aIndexPos >= 0 &&
-            mPossibleIndexes.EnsureLengthAtLeast(aIndexPos+1)) {
-            mPossibleIndexes.ElementAt(aIndexPos) = aChildIndex;
-        }
-    }
+    nsresult NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retval);
 };
 
 #endif
 
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -236,22 +236,24 @@ public:
   NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
   NS_IMETHOD OnAuthAvailable();
   NS_IMETHOD OnAuthCancelled(PRBool userCancel);
 
   nsresult Init(nsWebSocket *aOwner);
   nsresult Disconnect();
 
   // These are called always on the main thread (they dispatch themselves).
-  // ATTENTION, this method when called can release both the WebSocket object
-  // (i.e. mOwner) and its connection (i.e. *this*) if there are no strong event
-  // listeners.
+  // ATTENTION, these method when called can release both the WebSocket object
+  // (i.e. mOwner) and its connection (i.e. *this*).
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(Close)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(FailConnection)
 
+  PRBool HasOutgoingMessages()
+  { return mOutgoingMessages.GetSize() != 0; }
+
   PRBool ClosedCleanly() { return mClosedCleanly; }
 
   nsresult PostMessage(const nsString& aMessage);
   PRUint32 GetOutgoingBufferedAmount() { return mOutgoingBufferedAmount; }
 
   // prevent more than one instance from connecting at a time per IP
   static nsTArray<nsRefPtr<nsWebSocketEstablishedConnection> >* sWSsConnecting;
 
@@ -306,32 +308,31 @@ private:
   void RemoveFromLoadGroup();
   nsresult ProcessHeaders();
   nsresult PostData(nsCString  *aBuffer,
                     WSFrameType aWSFrameType);
   nsresult PrintErrorOnConsole(const char       *aBundleURI,
                                const PRUnichar  *aError,
                                const PRUnichar **aFormatStrings,
                                PRUint32          aFormatStringsLen);
-  PRBool SentAlreadyTheCloseFrame()
-  { return mPostedCloseFrame && mOutgoingMessages.GetSize() == 0; }
 
   // auth specific methods
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(ProcessAuthentication)
 
   // these are called always on the main thread (they dispatch themselves)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(AddWSConnecting)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(RemoveWSConnecting)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(HandleSetCookieHeader)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(DoInitialRequest)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(Connected)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(FrameError)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(DispatchNewMessage)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(Retry)
   DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(ResolveNextProxyAndConnect)
+  DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(UpdateMustKeepAlive)
 
   // called to cause the underlying socket to start speaking SSL
   nsresult ProxyStartSSL();
 
   // shared by both threads (the main and the socket ones)
   Mutex   mLockDisconnect;
   Mutex   mLockOutgoingMessages;
   Mutex   mLockReceivedMessages;
@@ -395,16 +396,17 @@ private:
 
   // auth specific data
   nsCString mProxyCredentials;
   nsCString mCredentials;
   nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
   PRPackedBool mAuthenticating;
 
   PRPackedBool mPostedCloseFrame;
+  PRPackedBool mSentCloseFrame;
   PRPackedBool mClosedCleanly;
 
   /**
    * A simple state machine used to manage the flow status of the input/output
    * streams of the connection.
    *
    * CONN_NOT_CONNECTED (initial state)              ->
    *                          CONN_CONNECTING |
@@ -653,16 +655,17 @@ nsWebSocketEstablishedConnection::nsWebS
   mBytesInBuffer(0),
   mLengthToDiscard(0),
   mReadingProxyConnectResponse(PR_FALSE),
   mCurrentProxyConfig(eNotResolvingProxy),
   mProxyFailureReason(NS_OK),
   mFailureStatus(NS_OK),
   mAuthenticating(PR_FALSE),
   mPostedCloseFrame(PR_FALSE),
+  mSentCloseFrame(PR_FALSE),
   mClosedCleanly(PR_FALSE),
   mStatus(CONN_NOT_CONNECTED)
 {
   NS_ASSERTION(NS_IsMainThread(), "Not running on main thread");
   nsLayoutStatics::AddRef();
 }
 
 nsWebSocketEstablishedConnection::~nsWebSocketEstablishedConnection()
@@ -705,16 +708,18 @@ nsWebSocketEstablishedConnection::PostDa
   }
 
   if (sizeBefore == 0) {
     mBytesAlreadySentOfFirstOutString = 0;
     rv = mSocketOutput->AsyncWait(this, 0, 0, gWebSocketThread);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  UpdateMustKeepAlive();
+
   return NS_OK;
 }
 
 nsresult
 nsWebSocketEstablishedConnection::PostMessage(const nsString& aMessage)
 {
   NS_ASSERTION(NS_IsMainThread(), "Not running on main thread");
 
@@ -1209,17 +1214,17 @@ nsWebSocketEstablishedConnection::Handle
         NS_ENSURE_STATE(mLengthToDiscard <= ((PR_UINT32_MAX - bv) / 128));
 
         mLengthToDiscard = mLengthToDiscard * 128 + bv;
 
         if (!IS_HIGH_BIT_OF_BYTE_SET(b)) {
           // check if it is the close frame
           if (mLengthToDiscard == 0 && frameType == START_BYTE_OF_CLOSE_FRAME) {
             mBytesInBuffer = 0;
-            if (SentAlreadyTheCloseFrame()) {
+            if (mSentCloseFrame) {
               mClosedCleanly = PR_TRUE;
               mStatus = CONN_CLOSED;
             } else {
               mStatus = CONN_SENDING_ACK_CLOSE_FRAME;
             }
             return Close();
           }
           FrameError();
@@ -2242,16 +2247,22 @@ IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGI
                                   getter_AddRefs(mProxyResolveCancelable));
   if (NS_FAILED(rv)) {
     ResolveNextProxyAndConnect();
     return;
   }
 }
 IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_END
 
+IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGIN(UpdateMustKeepAlive)
+{
+  mOwner->UpdateMustKeepAlive();
+}
+IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_END
+
 void
 nsWebSocketEstablishedConnection::RemoveFromLoadGroup()
 {
   NS_ASSERTION(NS_IsMainThread(), "Not running on main thread");
   nsCOMPtr<nsILoadGroup> loadGroup;
   GetLoadGroup(getter_AddRefs(loadGroup));
   if (loadGroup) {
     loadGroup->RemoveRequest(this, nsnull, NS_OK);
@@ -2690,17 +2701,16 @@ nsWebSocketEstablishedConnection::OnOutp
 
         nsWSFrame *frameToSend =
           static_cast<nsWSFrame*>(mOutgoingMessages.PeekFront());
         nsCString *strToSend = frameToSend->mData;
         PRUint32 sizeToSend =
           strToSend->Length() - mBytesAlreadySentOfFirstOutString;
         PRBool currentStrHasStartFrameByte =
           (mBytesAlreadySentOfFirstOutString == 0);
-        PRBool strIsMessage = (frameToSend->mType == eUTF8MessageFrame);
 
         if (sizeToSend != 0) {
           PRUint32 written;
           rv = aStream->Write(strToSend->get() + mBytesAlreadySentOfFirstOutString,
                               sizeToSend, &written);
           if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
             break;
           }
@@ -2725,17 +2735,17 @@ nsWebSocketEstablishedConnection::OnOutp
             if (mStatus < CONN_CONNECTED_AND_READY) {
               FailConnection();
             } else {
               Close();
             }
             return NS_BASE_STREAM_CLOSED;
           }
 
-          if (strIsMessage) {
+          if (frameToSend->mType == eUTF8MessageFrame) {
             PRBool currentStrHasEndFrameByte =
               (mBytesAlreadySentOfFirstOutString + written ==
                strToSend->Length());
 
             // START_BYTE_OF_MESSAGE and END_BYTE_OF_MESSAGE bytes don't count
             if (currentStrHasStartFrameByte) {
               if (currentStrHasEndFrameByte) {
                 mOutgoingBufferedAmount -= written - 2;
@@ -2755,27 +2765,30 @@ nsWebSocketEstablishedConnection::OnOutp
         }
 
         sizeToSend = strToSend->Length() - mBytesAlreadySentOfFirstOutString;
         if (sizeToSend != 0) { // if different, we try sending what remain after
           break;
         }
 
         // ok, send the next string
+        if (frameToSend->mType == eCloseFrame) {
+          mSentCloseFrame = PR_TRUE;
+        }
         mOutgoingMessages.PopFront();
         delete frameToSend;
         mBytesAlreadySentOfFirstOutString = 0;
+        UpdateMustKeepAlive();
       }
 
       if (mOutgoingMessages.GetSize() != 0) {
         rv = mSocketOutput->AsyncWait(this, 0, 0, gWebSocketThread);
         ENSURE_SUCCESS_AND_FAIL_IF_FAILED(rv, rv);
       } else {
-        if (mStatus == CONN_SENDING_ACK_CLOSE_FRAME &&
-            SentAlreadyTheCloseFrame()) {
+        if (mStatus == CONN_SENDING_ACK_CLOSE_FRAME && mSentCloseFrame) {
           mClosedCleanly = PR_TRUE;
           mStatus = CONN_CLOSED;
           return Close();
         }
 
         if (mStatus == CONN_SENDING_INITIAL_REQUEST ||
             mStatus == CONN_CONNECTING_TO_HTTP_PROXY) {
           if (mStatus == CONN_SENDING_INITIAL_REQUEST) {
@@ -2828,18 +2841,19 @@ nsWebSocketEstablishedConnection::GetInt
 
   return NS_ERROR_UNEXPECTED;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsWebSocket
 ////////////////////////////////////////////////////////////////////////////////
 
-nsWebSocket::nsWebSocket() : mHasStrongEventListeners(PR_FALSE),
-                             mCheckThereAreStrongEventListeners(PR_TRUE),
+nsWebSocket::nsWebSocket() : mKeepingAlive(PR_FALSE),
+                             mCheckMustKeepAlive(PR_TRUE),
+                             mTriggeredCloseEvent(PR_FALSE),
                              mReadyState(nsIWebSocket::CONNECTING),
                              mOutgoingBufferedAmount(0)
 {
 }
 
 nsWebSocket::~nsWebSocket()
 {
   if (mConnection) {
@@ -3058,16 +3072,18 @@ nsWebSocket::CreateAndDispatchMessageEve
   return DispatchDOMEvent(nsnull, event, nsnull, nsnull);
 }
 
 nsresult
 nsWebSocket::CreateAndDispatchCloseEvent(PRBool aWasClean)
 {
   nsresult rv;
 
+  mTriggeredCloseEvent = PR_TRUE;
+
   rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
   }
 
   // create an event that uses the CloseEvent interface,
   // which does not bubble, is not cancelable, and has no default action
 
@@ -3133,16 +3149,17 @@ nsWebSocket::SetReadyState(PRUint16 aNew
       new nsWSCloseEvent(this, mConnection->ClosedCleanly());
 
     mOutgoingBufferedAmount += mConnection->GetOutgoingBufferedAmount();
     mConnection = nsnull; // this is no longer necessary
 
     rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the close event");
+      mTriggeredCloseEvent = PR_TRUE;
       UpdateMustKeepAlive();
     }
   }
 }
 
 nsresult
 nsWebSocket::ParseURL(const nsString& aURL)
 {
@@ -3246,55 +3263,81 @@ nsWebSocket::SetProtocol(const nsString&
     }
   }
 
   CopyUTF16toUTF8(aProtocol, mProtocol);
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
-// Methods that keep alive the WebSocket object when there are
-// onopen/onmessage event listeners.
+// Methods that keep alive the WebSocket object when:
+//   1. the object has registered event listeners that can be triggered
+//      ("strong event listeners");
+//   2. there are outgoing not sent messages.
 //-----------------------------------------------------------------------------
 
 void
 nsWebSocket::UpdateMustKeepAlive()
 {
-  if (!mCheckThereAreStrongEventListeners) {
+  if (!mCheckMustKeepAlive) {
     return;
   }
 
-  if (mHasStrongEventListeners) {
-    if (!mListenerManager ||
-        ((mReadyState != nsIWebSocket::CONNECTING ||
-          !mListenerManager->HasListenersFor(NS_LITERAL_STRING("open"))) &&
-         (mReadyState == nsIWebSocket::CLOSED ||
-          !mListenerManager->HasListenersFor(NS_LITERAL_STRING("message"))))) {
-      mHasStrongEventListeners = PR_FALSE;
-      static_cast<nsPIDOMEventTarget*>(this)->Release();
+  PRBool shouldKeepAlive = PR_FALSE;
+
+  if (mListenerManager) {
+    switch (mReadyState)
+    {
+      case nsIWebSocket::CONNECTING:
+      {
+        if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("open")) ||
+            mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
+            mListenerManager->HasListenersFor(NS_LITERAL_STRING("close"))) {
+          shouldKeepAlive = PR_TRUE;
+        }
+      }
+      break;
+
+      case nsIWebSocket::OPEN:
+      case nsIWebSocket::CLOSING:
+      {
+        if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
+            mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")) ||
+            mConnection->HasOutgoingMessages()) {
+          shouldKeepAlive = PR_TRUE;
+        }
+      }
+      break;
+
+      case nsIWebSocket::CLOSED:
+      {
+        shouldKeepAlive =
+          (!mTriggeredCloseEvent &&
+           mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")));
+      }
     }
-  } else {
-    if ((mReadyState == nsIWebSocket::CONNECTING && mListenerManager &&
-         mListenerManager->HasListenersFor(NS_LITERAL_STRING("open"))) ||
-        (mReadyState != nsIWebSocket::CLOSED && mListenerManager &&
-         mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")))) {
-      mHasStrongEventListeners = PR_TRUE;
-      static_cast<nsPIDOMEventTarget*>(this)->AddRef();
-    }
+  }
+
+  if (mKeepingAlive && !shouldKeepAlive) {
+    mKeepingAlive = PR_FALSE;
+    static_cast<nsPIDOMEventTarget*>(this)->Release();
+  } else if (!mKeepingAlive && shouldKeepAlive) {
+    mKeepingAlive = PR_TRUE;
+    static_cast<nsPIDOMEventTarget*>(this)->AddRef();
   }
 }
 
 void
 nsWebSocket::DontKeepAliveAnyMore()
 {
-  if (mHasStrongEventListeners) {
-    mCheckThereAreStrongEventListeners = PR_FALSE;
-    mHasStrongEventListeners = PR_FALSE;
+  if (mKeepingAlive) {
+    mKeepingAlive = PR_FALSE;
     static_cast<nsPIDOMEventTarget*>(this)->Release();
   }
+  mCheckMustKeepAlive = PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsWebSocket::AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture)
 {
   nsresult rv = nsDOMEventTargetHelper::AddEventListener(aType,
@@ -3426,18 +3469,18 @@ NS_IMETHODIMP
 nsWebSocket::Close()
 {
   if (mReadyState == nsIWebSocket::CLOSING ||
       mReadyState == nsIWebSocket::CLOSED) {
     return NS_OK;
   }
 
   if (mReadyState == nsIWebSocket::CONNECTING) {
-    // FailConnection() can release the object if there are no strong event
-    // listeners, so we keep a reference before calling it
+    // FailConnection() can release the object, so we keep a reference
+    // before calling it
     nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
 
     mConnection->FailConnection();
     return NS_OK;
   }
 
   // mReadyState == nsIWebSocket::OPEN
   mConnection->Close();
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/nsWebSocket.h
@@ -110,36 +110,37 @@ protected:
 
   nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
   nsresult CreateAndDispatchMessageEvent(nsCString *aData);
   nsresult CreateAndDispatchCloseEvent(PRBool aWasClean);
 
   // called from mConnection accordingly to the situation
   void SetReadyState(PRUint16 aNewReadyState);
 
-  // if there are onopen or onmessage event listeners ("strong event listeners")
-  // then this method keeps the object alive when js doesn't have strong
-  // references to it.
+  // if there are "strong event listeners" (see comment in nsWebSocket.cpp) or
+  // outgoing not sent messages then this method keeps the object alive
+  // when js doesn't have strong references to it.
   void UpdateMustKeepAlive();
-  // Releases, if necessary, the strong event listeners. ATTENTION, when calling
-  // this method the object can be released (and possibly collected).
+  // ATTENTION, when calling this method the object can be released
+  // (and possibly collected).
   void DontKeepAliveAnyMore();
 
   nsRefPtr<nsDOMEventListenerWrapper> mOnOpenListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnMessageListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnCloseListener;
 
   // related to the WebSocket constructor steps
   nsString mOriginalURL;
   PRPackedBool mSecure; // if true it is using SSL and the wss scheme,
                         // otherwise it is using the ws scheme with no SSL
 
-  PRPackedBool mHasStrongEventListeners;
-  PRPackedBool mCheckThereAreStrongEventListeners;
+  PRPackedBool mKeepingAlive;
+  PRPackedBool mCheckMustKeepAlive;
+  PRPackedBool mTriggeredCloseEvent;
 
   nsCString mAsciiHost;  // hostname
   PRUint32  mPort;
   nsCString mResource; // [filepath[?query]]
   nsCString mOrigin;
   nsCOMPtr<nsIURI> mURI;
   nsCString mProtocol;
 
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -398,16 +398,19 @@ include $(topsrcdir)/config/rules.mk
 		test_websocket_hello.html \
 		file_websocket_hello_wsh.py \
 		test_ws_basic_tests.html \
 		file_ws_basic_tests_wsh.py \
 		test_websocket.html \
 		file_websocket_wsh.py \
 		file_websocket_http_resource.txt \
 		test_bug574596.html \
+		test_x-frame-options.html \
+		file_x-frame-options_main.html \
+		file_x-frame-options_page.sjs \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
 _TEST_FILES2 += 	test_copyimage.html \
 		$(NULL)
 endif
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_x-frame-options_main.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+<title>X-Frame-Options tests</title>
+<script type="text/javascript">
+// This frame loading means all subframes have either loaded or errored out.  We
+// can now tell the test harness to check each subframe for the expected result.
+window.addEventListener('load', parent.testFramesLoaded, false);
+</script>
+</head>
+<body>
+
+<iframe id="control1" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=control1"></iframe><br>
+<iframe id="control2" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=control2"></iframe><br>
+<iframe id="deny" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny"></iframe><br>
+<iframe id="sameorigin1" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin1&xfo=sameorigin"></iframe><br>
+<iframe id="sameorigin2" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin2&xfo=sameorigin"></iframe><br>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_x-frame-options_page.sjs
@@ -0,0 +1,25 @@
+// SJS file for X-Frame-Options mochitests
+function handleRequest(request, response)
+{
+  var query = {};
+  request.queryString.split('&').forEach(function (val) {
+    var [name, value] = val.split('=');
+    query[name] = unescape(value);
+  });
+
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "text/html", false);
+
+  // X-Frame-Options header value
+  if (query['xfo'] == "deny") {
+    for (var i = 0 ; i < 0x7fffff ; i++) { }
+    response.setHeader("X-Frame-Options", "DENY", false);
+  }
+  else if (query['xfo'] == "sameorigin") {
+    response.setHeader("X-Frame-Options", "SAMEORIGIN", false);
+  }
+
+  // from the test harness we'll be checking for the presence of this element
+  // to test if the page loaded
+  response.write("<h1 id=\"test\">" + query["testid"] + "</h1>");
+}
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -432,17 +432,17 @@ function test16()
 }
 
 var status_test17 = "not started";
 
 window._test17 = function()
 {
   var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 17");
   local_ws._testNumber = "local17";
-  current_test++;
+  local_ws._testNumber = current_test++;
 
   status_test17 = "started";
 
   local_ws.onopen = function(e)
   {
     status_test17 = "opened";
     e.target.send("client data");
     forcegc();
@@ -505,42 +505,45 @@ function test19()
     doTest(20);
   };
 }
 
 window._test20 = function()
 {
   var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 20");
   local_ws._testNumber = "local20";
-  current_test++;
+  local_ws._testNumber = current_test++;
 
   local_ws.onerror = function()
   {
     ok(false, "onerror called on test " + e.target._testNumber + "!");
   };
 
-  local_ws.onclose = shouldNotReceiveCloseEvent;
+  local_ws.onclose = function(e)
+  {
+    shouldCloseCleanly(e);
+    doTest(21);
+  };
 
   local_ws = null;
   window._test20 = null;
   forcegc();
 }
 
 function test20()
 {
   window._test20();
-  doTest(21);
 }
 
 var timeoutTest21;
 
 window._test21 = function()
 {
   var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 21");
-  current_test++;
+  local_ws._testNumber = current_test++;
 
   local_ws.onopen = function(e)
   {
     e.target.send("client data");
     timeoutTest21 = setTimeout(function()
     {
       ok(false, "Didn't received message on test 21!");
     }, 15000);
@@ -558,27 +561,30 @@ window._test21 = function()
   {
     clearTimeout(timeoutTest21);
     ok(e.data == "server data", "Bad message in test 21");
     forcegc();
     e.target.onmessage = null;
     forcegc();
   };
 
-  local_ws.onclose = shouldNotReceiveCloseEvent;
+  local_ws.onclose = function(e)
+  {
+    shouldCloseCleanly(e);
+    doTest(22);
+  };
 
   local_ws = null;
   window._test21 = null;
   forcegc();
 }
 
 function test21()
 {
   window._test21();
-  doTest(22);
 }
 
 function test22()
 {
   var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 22");
   ws.onopen = shouldNotOpen;
   ws.onclose = function(e)
   {
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_x-frame-options.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for X-Frame-Options response header</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/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 style="width:100%;height:300px;" id="harness"></iframe>
+<script class="testbody" type="text/javascript">
+
+var path = "/tests/content/base/test/";
+// contains { test_frame_id : expected_result }
+var testExpectedResults = { "control1": true,
+                            "control2": true,
+                            "deny": false,
+                            "sameorigin1": true,
+                            "sameorigin2": false
+                          };
+
+var testFramesLoaded = function() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var harness = document.getElementById("harness");
+
+  for (var t in testExpectedResults) {
+    var frame = harness.contentDocument.getElementById(t);
+    // test if frame loaded by checking for a contentDocument we can access
+    test = frame.contentDocument.getElementById("test");
+    is(test != null, testExpectedResults[t], "test "+t);
+  }
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// load the test harness
+document.getElementById("harness").src = "file_x-frame-options_main.html";
+
+</script>
+</pre>
+
+</body>
+</html>
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -104,23 +104,35 @@ Canvas2D_GetStyleHelper(JSContext *cx, J
     if (NS_FAILED(rv))
         return xpc_qsThrowGetterSetterFailed(cx, rv, JSVAL_TO_OBJECT(*vp), id);
 
     switch (resultType) {
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_STRING:
         return xpc_qsStringToJsval(cx, resultString, vp);
 
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_PATTERN:
-        return xpc_qsXPCOMObjectToJsval(lccx, resultInterface, xpc_qsGetWrapperCache(resultInterface),
-                                        &NS_GET_IID(nsIDOMCanvasPattern), &interfaces[k_nsIDOMCanvasPattern], vp);
-
+    {
+        nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
+        qsObjectHelper helper(ToSupports(resultInterface));
+        helper.SetNode(resultInterface);
+        helper.SetCanonical(ToCanonicalSupports(resultInterface));
+        return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
+                                        &NS_GET_IID(nsIDOMCanvasPattern),
+                                        &interfaces[k_nsIDOMCanvasPattern], vp);
+    }
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_GRADIENT:
-        return xpc_qsXPCOMObjectToJsval(lccx, resultInterface, xpc_qsGetWrapperCache(resultInterface),
-                                        &NS_GET_IID(nsIDOMCanvasGradient), &interfaces[k_nsIDOMCanvasGradient], vp);
-
+    {
+        nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
+        qsObjectHelper helper(ToSupports(resultInterface));
+        helper.SetNode(resultInterface);
+        helper.SetCanonical(ToCanonicalSupports(resultInterface));
+        return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
+                                        &NS_GET_IID(nsIDOMCanvasGradient),
+                                        &interfaces[k_nsIDOMCanvasGradient], vp);
+    }
     default:
         return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(*vp), id);
     }
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -1128,131 +1128,131 @@ helper_nsICanvasRenderingContextWebGL_Un
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv,
-    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv,
-    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv,
-    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 // FIXME This should return void, not uint32
 //       (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
 static uint32 FASTCALL
 nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4);
     return 0;
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv,
-    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
 
 #endif /* JS_TRACER */
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -315,19 +315,19 @@ WebGLContext::SetDimensions(PRInt32 widt
     MakeContextCurrent();
 
     // Make sure that we clear this out, otherwise
     // we'll end up displaying random memory
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, gl->GetOffscreenFBO());
     gl->fViewport(0, 0, mWidth, mHeight);
     gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 #ifdef USE_GLES2
-    gl->fClearDepthf(0.0f);
+    gl->fClearDepthf(1.0f);
 #else
-    gl->fClearDepth(0.0f);
+    gl->fClearDepth(1.0f);
 #endif
     gl->fClearStencil(0);
     gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -69,16 +69,17 @@
 
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIFrame.h"
 #include "nsDOMError.h"
 #include "nsIScriptError.h"
 
 #include "nsCSSParser.h"
 #include "nsICSSStyleRule.h"
+#include "mozilla/css/Declaration.h"
 #include "nsComputedDOMStyle.h"
 #include "nsStyleSet.h"
 
 #include "nsPrintfCString.h"
 
 #include "nsReadableUtils.h"
 
 #include "nsColor.h"
@@ -2238,38 +2239,46 @@ nsCanvasRenderingContext2D::Rect(float x
 static nsresult
 CreateFontStyleRule(const nsAString& aFont,
                     nsINode* aNode,
                     nsICSSStyleRule** aResult)
 {
     nsCSSParser parser;
     NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
-    // aFont is to be parsed as the value of a CSS 'font' shorthand,
-    // and then any line-height setting in that shorthand is to be
-    // overridden with "normal".  Because of the way style rules are
-    // stored, it is more efficient to fabricate a text string that
-    // can be processed in one go with ParseStyleAttribute than to
-    // make two calls to ParseDeclaration.
-
-    nsAutoString styleAttr(NS_LITERAL_STRING("font:"));
-    styleAttr.Append(aFont);
-    styleAttr.AppendLiteral(";line-height:normal");
+    nsCOMPtr<nsICSSStyleRule> rule;
+    PRBool changed;
 
     nsIPrincipal* principal = aNode->NodePrincipal();
     nsIDocument* document = aNode->GetOwnerDoc();
+
     nsIURI* docURL = document->GetDocumentURI();
     nsIURI* baseURL = document->GetDocBaseURI();
 
-    nsresult rv = parser.ParseStyleAttribute(styleAttr, docURL, baseURL,
-                                             principal, aResult);
+    nsresult rv = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
+                                             principal, getter_AddRefs(rule));
+    if (NS_FAILED(rv))
+        return rv;
+
+    rv = parser.ParseProperty(eCSSProperty_font, aFont, docURL, baseURL,
+                              principal, rule->GetDeclaration(), &changed,
+                              PR_FALSE);
     if (NS_FAILED(rv))
         return rv;
 
-    (*aResult)->RuleMatched();
+    rv = parser.ParseProperty(eCSSProperty_line_height,
+                              NS_LITERAL_STRING("normal"), docURL, baseURL,
+                              principal, rule->GetDeclaration(), &changed,
+                              PR_FALSE);
+    if (NS_FAILED(rv))
+        return rv;
+
+    rule->RuleMatched();
+
+    rule.forget(aResult);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::SetFont(const nsAString& font)
 {
     nsresult rv;
 
@@ -2294,16 +2303,33 @@ nsCanvasRenderingContext2D::SetFont(cons
 
     nsCOMArray<nsIStyleRule> rules;
 
     nsCOMPtr<nsICSSStyleRule> rule;
     rv = CreateFontStyleRule(font, document, getter_AddRefs(rule));
     if (NS_FAILED(rv))
         return rv;
 
+    css::Declaration *declaration = rule->GetDeclaration();
+    // The easiest way to see whether we got a syntax error or whether
+    // we got 'inherit' or 'initial' is to look at font-size-adjust,
+    // which the shorthand resets to either 'none' or
+    // '-moz-system-font'.
+    // We know the declaration is not !important, so we can use
+    // GetNormalBlock().
+    const nsCSSValue *fsaVal =
+      declaration->GetNormalBlock()->
+        ValueStorageFor(eCSSProperty_font_size_adjust);
+    if (!fsaVal || (fsaVal->GetUnit() != eCSSUnit_None &&
+                    fsaVal->GetUnit() != eCSSUnit_System_Font)) {
+        // We got an all-property value or a syntax error.  The spec says
+        // this value must be ignored.
+        return NS_OK;
+    }
+
     rules.AppendObject(rule);
 
     nsStyleSet* styleSet = presShell->StyleSet();
 
     // have to get a parent style context for inherit-like relative
     // values (2em, bolder, etc.)
     nsRefPtr<nsStyleContext> parentContext;
 
@@ -2362,17 +2388,23 @@ nsCanvasRenderingContext2D::SetFont(cons
                        fontStyle->mFont.featureSettings,
                        fontStyle->mFont.languageOverride);
 
     CurrentState().fontGroup =
         gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name,
                                                     &style,
                                                     presShell->GetPresContext()->GetUserFontSet());
     NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
-    CurrentState().font = font;
+
+    // The font getter is required to be reserialized based on what we
+    // parsed (including having line-height removed).  (Older drafts of
+    // the spec required font sizes be converted to pixels, but that no
+    // longer seems to be required.)
+    declaration->GetValue(eCSSProperty_font, CurrentState().font);
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::GetFont(nsAString& font)
 {
     /* will initilize the value if not set, else does nothing */
     GetCurrentFontStyle();
@@ -3669,16 +3701,19 @@ nsCanvasRenderingContext2D::DrawWindow(n
         renderDocFlags |= nsIPresShell::RENDER_CARET;
     }
     if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_VIEW) {
         renderDocFlags &= ~nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
     }
     if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_USE_WIDGET_LAYERS) {
         renderDocFlags |= nsIPresShell::RENDER_USE_WIDGET_LAYERS;
     }
+    if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
+        renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
+    }
 
     rv = presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes);
 
     // get rid of the pattern surface ref, just in case
     mThebes->SetColor(gfxRGBA(1,1,1,1));
     DirtyAllStyles();
 
     // note that aX and aY are coordinates in the document that
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -61,16 +61,17 @@ include $(topsrcdir)/config/rules.mk
 	image_anim-gr.png \
 	image_rgrg-256x256.png \
 	image_red.png \
 	image_transparent.png \
 	image_green.png \
 	image_green-redirect \
 	image_green-redirect^headers^ \
 	test_drawImageIncomplete.html \
+	test_canvas_font_setter.html \
 	$(NULL)
 
 # xor and lighter aren't well handled by cairo; they mostly work, but we don't want
 # to test that
 #	test_2d.composite.solid.xor.html \
 #	test_2d.composite.solid.lighter.html \
 #	test_2d.composite.transparent.xor.html \
 #	test_2d.composite.transparent.lighter.html \
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_canvas_font_setter.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=
+-->
+<head>
+  <title>Test for Bug </title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/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=">Mozilla Bug </a>
+<canvas id="display" height="200" width="200"></canvas>
+<pre id="test">
+<script type="application/javascript">
+
+var canvas = document.getElementById("display");
+var cx = canvas.getContext("2d");
+
+is(cx.font, "10px sans-serif", "initial font of canvas context");
+
+cx.font = "italic 16px sans-serif";
+is(cx.font, "italic 16px sans-serif", "valid font should round-trip");
+cx.font = "bold 12px serif; background: green";
+is(cx.font, "italic 16px sans-serif", "invalid font should be ignored");
+
+cx.font = "bold 12px/3.0 serif";
+is(cx.font, "bold 12px serif", "line-height should be dropped");
+cx.font = "inherit";
+is(cx.font, "bold 12px serif", "inherit should be ignored");
+cx.font = "boold 18px sans-serif";
+is(cx.font, "bold 12px serif", "syntax error should be ignored");
+cx.font = "menu";
+todo_is(cx.font, "menu", "system fonts should work");
+
+function textmeas() {
+  return cx.measureText("hello").width;
+}
+
+cx.font = "66px serif";
+var w_at_66 = textmeas();
+cx.font = "20px serif";
+var w_at_20 = textmeas();
+ok(w_at_66 > w_at_20, "text should be wider at 66px than at 20px");
+
+canvas.style.fontSize = "33px";
+cx.font = "2em serif";
+is(cx.font, "2em serif", "serialization of em");
+is(textmeas(), w_at_66, "em should be relative to canvas font size");
+canvas.style.fontSize = "16px";
+is(cx.font, "2em serif", "serialization of em");
+is(textmeas(), w_at_66,
+   "em should be relative to canvas font size at time of setting");
+document.body.removeChild(canvas);
+is(cx.font, "2em serif", "serialization of em");
+is(textmeas(), w_at_66,
+   "em should be relative to canvas font size at time of setting");
+canvas.style.fontSize = "33px";
+cx.font = "2em serif";
+is(cx.font, "2em serif", "serialization of em");
+is(textmeas(), w_at_20,
+   "em should be relative to 10px when canvas not in document");
+document.body.appendChild(canvas);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -453,19 +453,20 @@ nsTextStateManager::ContentInserted(nsID
                                      PRInt32 aIndexInContainer)
 {
   NotifyContentAdded(NODE_FROM(aContainer, aDocument),
                      aIndexInContainer, aIndexInContainer + 1);
 }
 
 void
 nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
-                                    nsIContent* aContainer,
-                                    nsIContent* aChild,
-                                    PRInt32 aIndexInContainer)
+                                   nsIContent* aContainer,
+                                   nsIContent* aChild,
+                                   PRInt32 aIndexInContainer,
+                                   nsIContent* aPreviousSibling)
 {
   PRUint32 offset = 0, childOffset = 1;
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     mRootContent, NODE_FROM(aContainer, aDocument),
                     aIndexInContainer, &offset)))
     return;
 
   // get offset at the end of the deleted node
--- a/content/events/src/nsXMLEventsElement.cpp
+++ b/content/events/src/nsXMLEventsElement.cpp
@@ -37,28 +37,28 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDocument.h"
 
 class nsXMLEventsElement : public nsXMLElement {
 public:
-  nsXMLEventsElement(nsINodeInfo *aNodeInfo);
+  nsXMLEventsElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsXMLEventsElement();
   NS_FORWARD_NSIDOMNODE(nsXMLElement::)
 
   virtual nsIAtom *GetIDAttributeName() const;
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, 
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 };
 
-nsXMLEventsElement::nsXMLEventsElement(nsINodeInfo *aNodeInfo)
+nsXMLEventsElement::nsXMLEventsElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsXMLElement(aNodeInfo)
 {
 }
 
 nsXMLEventsElement::~nsXMLEventsElement()
 {
 }
 
@@ -80,17 +80,18 @@ nsXMLEventsElement::SetAttr(PRInt32 aNam
     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
   return nsXMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                    aNotify);
 }
 
 NS_IMPL_ELEMENT_CLONE(nsXMLEventsElement)
 
 nsresult
-NS_NewXMLEventsElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
+NS_NewXMLEventsElement(nsIContent** aInstancePtrResult,
+                       already_AddRefed<nsINodeInfo> aNodeInfo)
 {
   nsXMLEventsElement* it = new nsXMLEventsElement(aNodeInfo);
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   NS_ADDREF(*aInstancePtrResult = it);
   return NS_OK;
 }
--- a/content/events/src/nsXMLEventsManager.cpp
+++ b/content/events/src/nsXMLEventsManager.cpp
@@ -301,67 +301,51 @@ PRBool nsXMLEventsManager::RemoveListene
     mListeners.Remove(aContent);
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   nsIContent *cur;
   for (int i = 0; i < mIncomplete.Count(); ++i) {
     cur = mIncomplete[i];
     //If this succeeds, the object will be removed from mIncomplete
     if (nsXMLEventsListener::InitXMLEventsListener(aDocument, this, cur))
       --i;
   }
 }
 
 void 
-nsXMLEventsManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
-void 
-nsXMLEventsManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
-void 
 nsXMLEventsManager::NodeWillBeDestroyed(const nsINode* aNode)
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
   mIncomplete.Clear();
   mListeners.Enumerate(EnumAndUnregisterListener, this);
   mListeners.Clear();
 }
 
 void 
-nsXMLEventsManager::BeginLoad(nsIDocument* aDocument) {}
-
-void 
 nsXMLEventsManager::EndLoad(nsIDocument* aDocument)
 {
   AddListeners(aDocument);
 }
-NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXMLEventsManager)
-void
-nsXMLEventsManager::CharacterDataWillChange(nsIDocument* aDocument,
-                                            nsIContent* aContent,
-                                            CharacterDataChangeInfo* aInfo) {}
-void 
-nsXMLEventsManager::CharacterDataChanged(nsIDocument* aDocument,
-                                         nsIContent* aContent,
-                                         CharacterDataChangeInfo* aInfo) {}
-void
-nsXMLEventsManager::AttributeWillChange(nsIDocument* aDocument,
-                                        nsIContent* aContent,
-                                        PRInt32 aNameSpaceID,
-                                        nsIAtom* aAttribute,
-                                        PRInt32 aModType) {}
+
 void
 nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
                                      nsIContent* aContent,
                                      PRInt32 aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      PRInt32 aModType)
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   if (aNameSpaceID == kNameSpaceID_XMLEvents &&
       (aAttribute == nsGkAtoms::event ||
        aAttribute == nsGkAtoms::handler ||
        aAttribute == nsGkAtoms::target ||
        aAttribute == nsGkAtoms::observer ||
        aAttribute == nsGkAtoms::phase ||
        aAttribute == nsGkAtoms::propagate)) {
     RemoveListener(aContent);
@@ -407,41 +391,36 @@ nsXMLEventsManager::ContentInserted(nsID
                                     nsIContent* aContainer,
                                     nsIContent* aChild,
                                     PRInt32 aIndexInContainer)
 {
   AddListeners(aDocument);
 }
 
 void
-nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument, 
+nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
                                    nsIContent* aContainer,
                                    nsIContent* aChild,
-                                   PRInt32 aIndexInContainer)
+                                   PRInt32 aIndexInContainer,
+                                   nsIContent* aPreviousSibling)
 {
   if (!aChild || !aChild->IsElement())
     return;
   //Note, we can't use IDs here, the observer may not always have an ID.
   //And to remember: the same observer can be referenced by many 
   //XMLEventsListeners
 
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   //If the content was an XML Events observer or handler
   mListeners.Enumerate(EnumAndSetIncomplete, aChild);
 
   //If the content was an XML Events attributes container
   if (RemoveListener(aChild)) {
     //for aContainer.appendChild(aContainer.removeChild(aChild));
     AddXMLEventsContent(aChild);
   }
 
   PRUint32 count = aChild->GetChildCount();
   for (PRUint32 i = 0; i < count; ++i) {
-    ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i);
+    ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i, aChild->GetPreviousSibling());
   }
 }
-
-void
-nsXMLEventsManager::ParentChainChanged(nsIContent *aContent)
-{
-}
-
-NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXMLEventsManager)
-
--- a/content/events/src/nsXMLEventsManager.h
+++ b/content/events/src/nsXMLEventsManager.h
@@ -41,16 +41,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsCOMArray.h"
 #include "nsIDOMEventListener.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIAtom.h"
+#include "nsStubDocumentObserver.h"
 
 /*
  * The implementation of the XML Events Basic profile
  */
 
 class nsXMLEventsManager;
 class nsXMLEventsListener : public nsIDOMEventListener {
 public:
@@ -84,22 +85,28 @@ private:
   nsString mEvent;
   nsCOMPtr<nsIAtom> mTarget;
   PRPackedBool mPhase;
   PRPackedBool mStopPropagation;
   PRPackedBool mCancelDefault;
   
 };
 
-class nsXMLEventsManager : public nsIDocumentObserver {
+class nsXMLEventsManager : public nsStubDocumentObserver {
 public:
   nsXMLEventsManager();
   ~nsXMLEventsManager();
   NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOCUMENTOBSERVER
+
+  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
+  virtual void EndLoad(nsIDocument* aDocument);
+  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   void AddXMLEventsContent(nsIContent * aContent);
   void RemoveXMLEventsContent(nsIContent * aContent);
   void AddListener(nsIContent * aContent, nsXMLEventsListener * aListener);
   //Returns PR_TRUE if a listener was removed.
   PRBool RemoveListener(nsIContent * aXMLElement);
 private:
   void AddListeners(nsIDocument* aDocument);
--- a/content/html/content/public/nsHTMLAudioElement.h
+++ b/content/html/content/public/nsHTMLAudioElement.h
@@ -45,17 +45,18 @@
 typedef PRUint16 nsMediaNetworkState;
 typedef PRUint16 nsMediaReadyState;
 
 class nsHTMLAudioElement : public nsHTMLMediaElement,
                            public nsIDOMHTMLAudioElement,
                            public nsIJSNativeInitializer
 {
 public:
-  nsHTMLAudioElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser = 0);
+  nsHTMLAudioElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                     PRUint32 aFromParser = 0);
   virtual ~nsHTMLAudioElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsHTMLMediaElement::)
 
@@ -71,11 +72,13 @@ public:
   // nsIDOMHTMLAudioElement
   NS_DECL_NSIDOMHTMLAUDIOELEMENT
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
                         JSObject* aObj, PRUint32 argc, jsval* argv);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 #endif
--- a/content/html/content/public/nsHTMLCanvasElement.h
+++ b/content/html/content/public/nsHTMLCanvasElement.h
@@ -60,17 +60,17 @@
 class nsHTMLCanvasElement : public nsGenericHTMLElement,
                             public nsICanvasElementExternal,
                             public nsIDOMHTMLCanvasElement
 {
   typedef mozilla::layers::CanvasLayer CanvasLayer;
   typedef mozilla::layers::LayerManager LayerManager;
 
 public:
-  nsHTMLCanvasElement(nsINodeInfo *aNodeInfo);
+  nsHTMLCanvasElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLCanvasElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -158,16 +158,17 @@ public:
   already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
                                                LayerManager *aManager);
 
   // Tell the Context that all the current rendering that it's
   // invalidated has been displayed to the screen, so that it should
   // start requesting invalidates again as needed.
   void MarkContextClean();
 
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   nsIntSize GetWidthHeight();
 
   nsresult UpdateContext();
   nsresult ToDataURLImpl(const nsAString& aMimeType,
                          const nsAString& aEncoderOptions,
                          nsAString& aDataURL);
   nsresult GetContextHelper(const nsAString& aContextId,
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -62,17 +62,18 @@ class nsHTMLMediaElement : public nsGene
 
 public:
   enum CanPlayStatus {
     CANPLAY_NO,
     CANPLAY_MAYBE,
     CANPLAY_YES
   };
 
-  nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser = 0);
+  nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                     PRUint32 aFromParser = 0);
   virtual ~nsHTMLMediaElement();
 
   /**
    * This is used when the browser is constructing a video element to play
    * a channel that we've already started loading. The src attribute and
    * <source> children are ignored.
    * @param aChannel the channel to use
    * @param aListener returns a stream listener that should receive
--- a/content/html/content/public/nsHTMLVideoElement.h
+++ b/content/html/content/public/nsHTMLVideoElement.h
@@ -40,17 +40,18 @@
 
 #include "nsIDOMHTMLVideoElement.h"
 #include "nsHTMLMediaElement.h"
 
 class nsHTMLVideoElement : public nsHTMLMediaElement,
                            public nsIDOMHTMLVideoElement
 {
 public:
-  nsHTMLVideoElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser = 0);
+  nsHTMLVideoElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                     PRUint32 aFromParser = 0);
   virtual ~nsHTMLVideoElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsHTMLMediaElement::)
 
@@ -73,11 +74,13 @@ public:
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   // Returns the current video frame width and height.
   // If there is no video frame, returns the given default size.
   nsIntSize GetVideoSize(nsIntSize defaultSize);
+
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 #endif
--- a/content/html/content/public/nsIHTMLCollection.h
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -35,37 +35,41 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsIHTMLCollection_h___
 #define nsIHTMLCollection_h___
 
 #include "nsIDOMHTMLCollection.h"
 
+class nsIContent;
+class nsWrapperCache;
+
 // IID for the nsIHTMLCollection interface
 #define NS_IHTMLCOLLECTION_IID \
-{ 0x5709485b, 0xc057, 0x4ba7, \
- { 0x95, 0xbd, 0x98, 0xb7, 0x94, 0x4f, 0x13, 0xe7 } }
+{ 0xf38b43dc, 0x74d4, 0x4b11, \
+ { 0xa6, 0xc9, 0xf8, 0xf4, 0xb5, 0xd3, 0x84, 0xe3 } }
 
 /**
  * An internal interface that allows QI-less getting of nodes from HTML
  * collections
  */
 class nsIHTMLCollection : public nsIDOMHTMLCollection
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLCOLLECTION_IID)
 
   /**
    * Get the node at the index.  Returns null if the index is out of bounds.
    */
-  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult) = 0;
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult) = 0;
 
   /**
    * Get the node for the name.  Returns null if no node exists for the name.
    */
   virtual nsISupports* GetNamedItem(const nsAString& aName,
+                                    nsWrapperCache** aCache,
                                     nsresult* aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLCollection, NS_IHTMLCOLLECTION_IID)
 
 #endif /* nsIHTMLCollection_h___ */
deleted file mode 100644
--- a/content/html/content/public/nsIRadioControlElement.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C++; 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
- * John B. Keiser
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsIRadioControlElement_h___
-#define nsIRadioControlElement_h___
-
-#include "nsISupports.h"
-#include "nsIRadioGroupContainer.h"
-class nsAString;
-class nsIForm;
-
-// IID for the nsIRadioControl interface
-#define NS_IRADIOCONTROLELEMENT_IID \
-{ 0x647dff84, 0x1dd2, 0x11b2, \
-    { 0x95, 0xcf, 0xe5, 0x01, 0xa8, 0x54, 0xa6, 0x40 } }
-
-/**
- * This interface is used for the text control frame to store its value away
- * into the content.
- */
-class nsIRadioControlElement : public nsISupports {
-public:
-
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRADIOCONTROLELEMENT_IID)
-
-  /**
-   * Set the radio button checked, but don't do any extra checks and don't
-   * trigger "value changed".  This is for experts only.  Do not try this
-   * at home.  Well, OK, try it at home, but not late at night.
-   */
-  NS_IMETHOD RadioSetChecked(PRBool aNotify) = 0;
-
-  /**
-   * Let this radio button know that the radio group's "checked" property has
-   * been changed by JavaScript or by the user
-   *
-   * @param aCheckedChanged whether the checked property has been changed.
-   * @param aOnlyOnThisRadioButton set to TRUE to only set the property only on
-   *        the radio button in question; otherwise it will set the property on
-   *        all other radio buttons in its group just to be sure they are
-   *        consistent.
-   */
-  NS_IMETHOD SetCheckedChangedInternal(PRBool aCheckedChanged) = 0;
-
-  /**
-   * Let an entire radio group know that its "checked" property has been
-   * changed by JS or by the user (calls SetCheckedChangedInternal multiple
-   * times via a visitor)
-   *
-   * @param aCheckedChanged whether the checked property has been changed.
-   */
-  NS_IMETHOD SetCheckedChanged(PRBool aCheckedChanged) = 0;
-
-  /**
-   * Find out whether this radio group's "checked" property has been changed by
-   * JavaScript or by the user
-   *
-   * @param aCheckedChanged out param, whether the checked property has been
-   *        changed.
-   */
-  NS_IMETHOD GetCheckedChanged(PRBool* aCheckedChanged) = 0;
-
-  /**
-   * Let this radio button know that state has been changed such that it has
-   * been added to a group.
-   */
-  NS_IMETHOD AddedToRadioGroup(PRBool aNotify = PR_TRUE) = 0;
-
-  /**
-   * Let this radio button know that it is about to be removed from the radio
-   * group it is currently in (the relevant properties should not have changed
-   * yet).
-   */
-  NS_IMETHOD WillRemoveFromRadioGroup() = 0;
-
-  /**
-   * Get the radio group container for this radio button
-   * @return the radio group container (or null if no container)
-   */
-  virtual already_AddRefed<nsIRadioGroupContainer> GetRadioGroupContainer() = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioControlElement,
-                              NS_IRADIOCONTROLELEMENT_IID)
-
-#endif // nsIRadioControlElement_h___
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -47,16 +47,22 @@ LIBRARY_NAME	= gkconhtmlcon_s
 LIBXUL_LIBRARY	= 1
 
 
 EXPORTS		= \
 		nsImageMapUtils.h \
 		nsClientRect.h \
 		$(NULL)
 
+ifdef MOZ_IPC
+EXPORTS        += \
+                nsHTMLDNSPrefetch.h \
+                $(NULL)
+endif
+
 CPPSRCS		= \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
 		nsGenericHTMLElement.cpp \
 		nsFormSubmission.cpp \
 		nsImageMapUtils.cpp \
 		nsTextEditorState.cpp \
 		nsHTMLElement.cpp \
@@ -116,16 +122,18 @@ CPPSRCS		+= \
 		nsHTMLVideoElement.cpp \
 		$(NULL)
 endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 INCLUDES	+= \
 		-I$(srcdir)/../../../base/src \
 		-I$(srcdir)/../../../events/src \
 		-I$(srcdir)/../../../xbl/src \
 		-I$(srcdir)/../../../../layout/forms \
 		-I$(srcdir)/../../../../layout/style \
 		-I$(srcdir)/../../../../layout/tables \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -946,16 +946,18 @@ nsGenericHTMLElement::BindToTree(nsIDocu
   }
 
   return rv;
 }
 
 void
 nsGenericHTMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
+  RemoveFromNameTable();
+
   if (GetContentEditableValue() == eTrue) {
     nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(GetCurrentDoc());
     if (htmlDocument) {
       htmlDocument->ChangeContentEditableCount(this, -1);
     }
   }
 
   nsStyledElement::UnbindFromTree(aDeep, aNullParent);
@@ -2305,17 +2307,17 @@ nsGenericHTMLElement::GetIsContentEditab
   *aContentEditable = PR_FALSE;
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLFrameElement, TabIndex, tabindex, 0)
 
-nsGenericHTMLFormElement::nsGenericHTMLFormElement(nsINodeInfo *aNodeInfo)
+nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mForm(nsnull)
 {
 }
 
 nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
 {
   // Check that this element doesn't know anything about its form at this point.
@@ -2522,18 +2524,16 @@ nsGenericHTMLFormElement::BindToTree(nsI
 }
 
 void
 nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   // Save state before doing anything
   SaveState();
   
-  RemoveFromNameTable();
-
   if (mForm) {
     // Might need to unset mForm
     if (aNullParent) {
       // No more parent means no more form
       ClearForm(PR_TRUE, PR_TRUE);
     } else {
       // Recheck whether we should still have an mForm.
       if (!FindForm(mForm)) {
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -67,20 +67,20 @@ class nsHTMLFormElement;
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
 public:
-  nsGenericHTMLElement(nsINodeInfo *aNodeInfo)
+  nsGenericHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElementBase(aNodeInfo)
   {
-    NS_ASSERTION(aNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
+    NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
                  "Unexpected namespace");
   }
 
   /** Typesafe, non-refcounting cast from nsIContent.  Cheaper than QI. **/
   static nsGenericHTMLElement* FromContent(nsIContent *aContent)
   {
     if (aContent->IsHTML())
       return static_cast<nsGenericHTMLElement*>(aContent);
@@ -789,17 +789,17 @@ private:
 
 /**
  * A helper class for form elements that can contain children
  */
 class nsGenericHTMLFormElement : public nsGenericHTMLElement,
                                  public nsIFormControl
 {
 public:
-  nsGenericHTMLFormElement(nsINodeInfo *aNodeInfo);
+  nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericHTMLFormElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
   virtual void SaveSubtreeState();
 
   // nsIFormControl
@@ -907,17 +907,17 @@ PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_B
  * A helper class for frame elements
  */
 
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
                                   public nsIDOMNSHTMLFrameElement,
                                   public nsIFrameLoaderOwner
 {
 public:
-  nsGenericHTMLFrameElement(nsINodeInfo *aNodeInfo)
+  nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~nsGenericHTMLFrameElement();
 
   // nsISupports
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
@@ -965,24 +965,26 @@ protected:
 
 //----------------------------------------------------------------------
 
 /**
  * A macro to implement the NS_NewHTMLXXXElement() functions.
  */
 #define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName)                            \
 nsGenericHTMLElement*                                                        \
-NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)\
+NS_NewHTML##_elementName##Element(already_AddRefed<nsINodeInfo> aNodeInfo,   \
+                                  PRUint32 aFromParser)                      \
 {                                                                            \
   return new nsHTML##_elementName##Element(aNodeInfo);                       \
 }
 
 #define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName)               \
 nsGenericHTMLElement*                                                        \
-NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)\
+NS_NewHTML##_elementName##Element(already_AddRefed<nsINodeInfo> aNodeInfo,   \
+                                  PRUint32 aFromParser)                      \
 {                                                                            \
   return new nsHTML##_elementName##Element(aNodeInfo, aFromParser);          \
 }
 
 /**
  * A macro to implement the getter and setter for a given string
  * valued content property. The method uses the generic GetAttr and
  * SetAttr methods.
@@ -1207,25 +1209,24 @@ NS_NewHTML##_elementName##Element(nsINod
     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(_class)                              \
   NS_HTML_CONTENT_INTERFACE_MAP_END
 
 #define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag)                       \
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface,                              \
                                      mNodeInfo->Equals(nsGkAtoms::_tag))
 
 
-#define NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_IF_TAG(_class, _tag)             \
-  if (mNodeInfo->Equals(nsGkAtoms::_tag) &&                                   \
-      (aIID.Equals(NS_GET_IID(nsIClassInfo)) ||                               \
-       aIID.Equals(NS_GET_IID(nsXPCClassInfo)))) {                            \
-    foundInterface = NS_GetDOMClassInfoInstance(eDOMClassInfo_##_class##_id); \
-    if (!foundInterface) {                                                    \
-      *aInstancePtr = nsnull;                                                 \
-      return NS_ERROR_OUT_OF_MEMORY;                                          \
-    }                                                                         \
+#define NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_GETTER(_getter) \
+  if (aIID.Equals(NS_GET_IID(nsIClassInfo)) ||               \
+      aIID.Equals(NS_GET_IID(nsXPCClassInfo))) {             \
+    foundInterface = _getter ();                             \
+    if (!foundInterface) {                                   \
+      *aInstancePtr = nsnull;                                \
+      return NS_ERROR_OUT_OF_MEMORY;                         \
+    }                                                        \
   } else
 
 #define NS_HTML_CONTENT_INTERFACE_TABLE0(_class)                              \
   NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(_class)                               \
   NS_OFFSET_AND_INTERFACE_TABLE_END
 
 #define NS_HTML_CONTENT_INTERFACE_TABLE1(_class, _i1)                         \
   NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(_class)                               \
@@ -1300,33 +1301,33 @@ NS_NewHTML##_elementName##Element(nsINod
     NS_INTERFACE_TABLE_ENTRY(_class, _i8)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i9)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i10)                                    \
   NS_OFFSET_AND_INTERFACE_TABLE_END
 
 
 // Element class factory methods
 
-#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName)              \
-nsGenericHTMLElement*                                             \
-NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo,         \
+#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName)                       \
+nsGenericHTMLElement*                                                      \
+NS_NewHTML##_elementName##Element(already_AddRefed<nsINodeInfo> aNodeInfo, \
                                   PRUint32 aFromParser = 0);
 
-#define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName)    \
-inline nsGenericHTMLElement*                                      \
-NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo,         \
-                                  PRUint32 aFromParser = 0)       \
-{                                                                 \
-  return NS_NewHTMLSharedElement(aNodeInfo, aFromParser);         \
+#define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName)             \
+inline nsGenericHTMLElement*                                               \
+NS_NewHTML##_elementName##Element(already_AddRefed<nsINodeInfo> aNodeInfo, \
+                                  PRUint32 aFromParser = 0)                \
+{                                                                          \
+  return NS_NewHTMLSharedElement(aNodeInfo, aFromParser);                  \
 }
 
 // Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand.
 // (Calling the macro directly (with no args) produces compiler warnings.)
 nsGenericHTMLElement*
-NS_NewHTMLElement(nsINodeInfo *aNodeInfo,
+NS_NewHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                   PRUint32 aFromParser = 0);
 
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject)
 
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Area)
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -63,17 +63,17 @@ nsresult NS_NewPreContentIterator(nsICon
 
 class nsHTMLAnchorElement : public nsGenericHTMLElement,
                             public nsIDOMHTMLAnchorElement,
                             public nsIDOMNSHTMLAnchorElement2,
                             public nsILink,
                             public Link
 {
 public:
-  nsHTMLAnchorElement(nsINodeInfo *aNodeInfo);
+  nsHTMLAnchorElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLAnchorElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -126,36 +126,38 @@ public:
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual PRInt32 IntrinsicState() const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor)
 
-nsHTMLAnchorElement::nsHTMLAnchorElement(nsINodeInfo *aNodeInfo)
+nsHTMLAnchorElement::nsHTMLAnchorElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLAnchorElement::~nsHTMLAnchorElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLAnchorElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLAnchorElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLAnchorElement, nsHTMLAnchorElement)
+DOMCI_NODE_DATA(HTMLAnchorElement, nsHTMLAnchorElement)
 
 // QueryInterface implementation for nsHTMLAnchorElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLAnchorElement)
   NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLAnchorElement,
                                    nsIDOMHTMLAnchorElement,
                                    nsIDOMNSHTMLAnchorElement,
                                    nsIDOMNSHTMLAnchorElement2,
                                    nsILink,
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -53,17 +53,17 @@ using namespace mozilla::dom;
 
 class nsHTMLAreaElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLAreaElement,
                           public nsIDOMNSHTMLAreaElement2,
                           public nsILink,
                           public Link
 {
 public:
-  nsHTMLAreaElement(nsINodeInfo *aNodeInfo);
+  nsHTMLAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLAreaElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -108,37 +108,36 @@ public:
                            PRBool aNotify);
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              PRBool aNotify);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual PRInt32 IntrinsicState() const;
 
-protected:
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Area)
 
 
-nsHTMLAreaElement::nsHTMLAreaElement(nsINodeInfo *aNodeInfo)
+nsHTMLAreaElement::nsHTMLAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLAreaElement::~nsHTMLAreaElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLAreaElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLAreaElement, nsGenericElement) 
 
-
-DOMCI_DATA(HTMLAreaElement, nsHTMLAreaElement)
+DOMCI_NODE_DATA(HTMLAreaElement, nsHTMLAreaElement)
 
 // QueryInterface implementation for nsHTMLAreaElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLAreaElement)
   NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLAreaElement,
                                    nsIDOMHTMLAreaElement,
                                    nsIDOMNSHTMLAreaElement,
                                    nsIDOMNSHTMLAreaElement2,
                                    nsILink,
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -63,17 +63,18 @@
 #include "nsITimer.h"
 
 #include "nsEventDispatcher.h"
 #include "nsIDOMDocumentEvent.h"
 #include "nsIDOMProgressEvent.h"
 #include "nsHTMLMediaError.h"
 
 nsGenericHTMLElement*
-NS_NewHTMLAudioElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+NS_NewHTMLAudioElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                       PRUint32 aFromParser)
 {
   /*
    * nsHTMLAudioElement's will be created without a nsINodeInfo passed in
    * if someone says "var audio = new Audio();" in JavaScript, in a case like
    * that we request the nsINodeInfo from the document's nodeinfo list.
    */
   nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
   if (!nodeInfo) {
@@ -81,35 +82,36 @@ NS_NewHTMLAudioElement(nsINodeInfo *aNod
       do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
     NS_ENSURE_TRUE(doc, nsnull);
 
     nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::audio, nsnull,
                                                    kNameSpaceID_XHTML);
     NS_ENSURE_TRUE(nodeInfo, nsnull);
   }
 
-  return new nsHTMLAudioElement(nodeInfo, aFromParser);
+  return new nsHTMLAudioElement(nodeInfo.forget(), aFromParser);
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLAudioElement, nsHTMLMediaElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLAudioElement, nsHTMLMediaElement)
 
-DOMCI_DATA(HTMLAudioElement, nsHTMLAudioElement)
+DOMCI_NODE_DATA(HTMLAudioElement, nsHTMLAudioElement)
 
 NS_INTERFACE_TABLE_HEAD(nsHTMLAudioElement)
 NS_HTML_CONTENT_INTERFACE_TABLE3(nsHTMLAudioElement, nsIDOMHTMLMediaElement,
                                  nsIDOMHTMLAudioElement, nsIJSNativeInitializer)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLAudioElement,
+NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLAudioElement,
                                                nsHTMLMediaElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLAudioElement)
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLAudioElement)
 
 
-nsHTMLAudioElement::nsHTMLAudioElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+nsHTMLAudioElement::nsHTMLAudioElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                                       PRUint32 aFromParser)
   : nsHTMLMediaElement(aNodeInfo, aFromParser)
 {
 }
 
 nsHTMLAudioElement::~nsHTMLAudioElement()
 {
 }
 
--- a/content/html/content/src/nsHTMLBRElement.cpp
+++ b/content/html/content/src/nsHTMLBRElement.cpp
@@ -41,17 +41,17 @@
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 #include "nsRuleData.h"
 
 class nsHTMLBRElement : public nsGenericHTMLElement,
                         public nsIDOMHTMLBRElement
 {
 public:
-  nsHTMLBRElement(nsINodeInfo *aNodeInfo);
+  nsHTMLBRElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLBRElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -66,36 +66,37 @@ public:
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(BR)
 
 
-nsHTMLBRElement::nsHTMLBRElement(nsINodeInfo *aNodeInfo)
+nsHTMLBRElement::nsHTMLBRElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLBRElement::~nsHTMLBRElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLBRElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLBRElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLBRElement, nsHTMLBRElement)
+DOMCI_NODE_DATA(HTMLBRElement, nsHTMLBRElement)
 
 // QueryInterface implementation for nsHTMLBRElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLBRElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLBRElement, nsIDOMHTMLBRElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLBRElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLBRElement)
 
--- a/content/html/content/src/nsHTMLBodyElement.cpp
+++ b/content/html/content/src/nsHTMLBodyElement.cpp
@@ -78,17 +78,17 @@ public:
 };
 
 //----------------------------------------------------------------------
 
 class nsHTMLBodyElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLBodyElement
 {
 public:
-  nsHTMLBodyElement(nsINodeInfo *aNodeInfo);
+  nsHTMLBodyElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLBodyElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -107,16 +107,17 @@ public:
                                 nsAttrValue& aResult);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 private:
   nsresult GetColorHelper(nsIAtom* aAtom, nsAString& aColor);
 
 protected:
   BodyRule* mContentStyleRule;
 };
 
 //----------------------------------------------------------------------
@@ -271,17 +272,17 @@ BodyRule::List(FILE* out, PRInt32 aInden
 #endif
 
 //----------------------------------------------------------------------
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Body)
 
 
-nsHTMLBodyElement::nsHTMLBodyElement(nsINodeInfo *aNodeInfo)
+nsHTMLBodyElement::nsHTMLBodyElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mContentStyleRule(nsnull)
 {
 }
 
 nsHTMLBodyElement::~nsHTMLBodyElement()
 {
   if (mContentStyleRule) {
@@ -289,17 +290,17 @@ nsHTMLBodyElement::~nsHTMLBodyElement()
     NS_RELEASE(mContentStyleRule);
   }
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLBodyElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLBodyElement, nsGenericElement) 
 
-DOMCI_DATA(HTMLBodyElement, nsHTMLBodyElement)
+DOMCI_NODE_DATA(HTMLBodyElement, nsHTMLBodyElement)
 
 // QueryInterface implementation for nsHTMLBodyElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLBodyElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLBodyElement, nsIDOMHTMLBodyElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLBodyElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLBodyElement)
 
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -76,17 +76,17 @@ static const nsAttrValue::EnumTable kBut
 // Default type is 'submit'.
 static const nsAttrValue::EnumTable* kButtonDefaultType = &kButtonTypeTable[2];
 
 class nsHTMLButtonElement : public nsGenericHTMLFormElement,
                             public nsIDOMHTMLButtonElement,
                             public nsIDOMNSHTMLButtonElement
 {
 public:
-  nsHTMLButtonElement(nsINodeInfo *aNodeInfo);
+  nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLButtonElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
 
@@ -134,17 +134,17 @@ public:
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual void DoneCreatingElement();
-
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual PRBool AcceptAutofocus() const
   {
     return PR_TRUE;
   }
 
   PRUint8 mType;
   PRPackedBool mHandlingClick;
@@ -159,17 +159,17 @@ private:
 
 
 // Construction, destruction
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Button)
 
 
-nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo)
+nsHTMLButtonElement::nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo),
     mType(kButtonDefaultType->value),
     mHandlingClick(PR_FALSE),
     mDisabledChanged(PR_FALSE),
     mInInternalActivate(PR_FALSE)
 {
 }
 
@@ -178,17 +178,17 @@ nsHTMLButtonElement::~nsHTMLButtonElemen
 }
 
 // nsISupports
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLButtonElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLButtonElement, nsGenericElement)
 
 
-DOMCI_DATA(HTMLButtonElement, nsHTMLButtonElement)
+DOMCI_NODE_DATA(HTMLButtonElement, nsHTMLButtonElement)
 
 // QueryInterface implementation for nsHTMLButtonElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
   NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLButtonElement,
                                    nsIDOMHTMLButtonElement,
                                    nsIDOMNSHTMLButtonElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLButtonElement,
                                                nsGenericHTMLFormElement)
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -52,22 +52,23 @@
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 nsGenericHTMLElement*
-NS_NewHTMLCanvasElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+NS_NewHTMLCanvasElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                        PRUint32 aFromParser)
 {
   return new nsHTMLCanvasElement(aNodeInfo);
 }
 
-nsHTMLCanvasElement::nsHTMLCanvasElement(nsINodeInfo *aNodeInfo)
+nsHTMLCanvasElement::nsHTMLCanvasElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo), mWriteOnly(PR_FALSE)
 {
 }
 
 nsHTMLCanvasElement::~nsHTMLCanvasElement()
 {
 }
 
@@ -75,17 +76,17 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLCan
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLCanvasElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentContext)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLCanvasElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLCanvasElement, nsGenericElement)
 
-DOMCI_DATA(HTMLCanvasElement, nsHTMLCanvasElement)
+DOMCI_NODE_DATA(HTMLCanvasElement, nsHTMLCanvasElement)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLCanvasElement)
   NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLCanvasElement,
                                    nsIDOMHTMLCanvasElement,
                                    nsICanvasElementExternal)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLCanvasElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLCanvasElement)
--- a/content/html/content/src/nsHTMLDNSPrefetch.cpp
+++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp
@@ -31,16 +31,22 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#include "mozilla/net/NeckoCommon.h"
+#include "mozilla/net/NeckoChild.h"
+#endif
+
 #include "nsHTMLDNSPrefetch.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 #include "nsNetUtil.h"
 
 #include "nsIDNSListener.h"
 #include "nsIWebProgressListener.h"
@@ -124,16 +130,29 @@ nsHTMLDNSPrefetch::IsAllowed (nsIDocumen
 {
   // There is no need to do prefetch on non UI scenarios such as XMLHttpRequest.
   return aDocument->IsDNSPrefetchAllowed() && aDocument->GetWindow();
 }
 
 nsresult
 nsHTMLDNSPrefetch::Prefetch(Link *aElement, PRUint16 flags)
 {
+#ifdef MOZ_IPC
+  if (mozilla::net::IsNeckoChild()) {
+    // Instead of transporting the Link object to the other process
+    // we are using the hostname based function here, too. Compared to the 
+    // IPC the performance hit should be negligible.
+    nsAutoString hostname;
+    nsresult rv = aElement->GetHostname(hostname);
+    NS_ENSURE_SUCCESS(rv,rv);
+
+    return Prefetch(hostname, flags);
+  }
+#endif
+
   if (!(sInitialized && sPrefetches && sDNSService && sDNSListener))
     return NS_ERROR_NOT_AVAILABLE;
 
   return sPrefetches->Add(flags, aElement);
 }
 
 nsresult
 nsHTMLDNSPrefetch::PrefetchLow(Link *aElement)
@@ -151,16 +170,23 @@ nsresult
 nsHTMLDNSPrefetch::PrefetchHigh(Link *aElement)
 {
   return Prefetch(aElement, 0);
 }
 
 nsresult
 nsHTMLDNSPrefetch::Prefetch(nsAString &hostname, PRUint16 flags)
 {
+#ifdef MOZ_IPC
+  if (mozilla::net::IsNeckoChild()) {
+    mozilla::net::gNeckoChild->SendHTMLDNSPrefetch(nsAutoString(hostname), flags);
+    return NS_OK;
+  }
+#endif
+
   if (!(sInitialized && sDNSService && sPrefetches && sDNSListener))
     return NS_ERROR_NOT_AVAILABLE;
 
   nsCOMPtr<nsICancelable> tmpOutstanding;
   return sDNSService->AsyncResolve(NS_ConvertUTF16toUTF8(hostname), flags | nsIDNSService::RESOLVE_SPECULATE,
                                    sDNSListener, nsnull, getter_AddRefs(tmpOutstanding));
 }
 
--- a/content/html/content/src/nsHTMLDNSPrefetch.h
+++ b/content/html/content/src/nsHTMLDNSPrefetch.h
@@ -51,16 +51,22 @@
 class nsIDocument;
 class nsITimer;
 namespace mozilla {
 namespace dom {
 class Link;
 } // namespace dom
 } // namespace mozilla
 
+namespace mozilla {
+namespace net {
+class NeckoParent;
+} // namespace net
+} // namespace mozilla
+
 class nsHTMLDNSPrefetch 
 {
 public:
   // The required aDocument parameter is the context requesting the prefetch - under
   // certain circumstances (e.g. headers, or security context) associated with
   // the context the prefetch will not be performed. 
   static PRBool   IsAllowed(nsIDocument *aDocument);
  
@@ -131,11 +137,15 @@ public:
     static const int          sMaxDeferredMask = (sMaxDeferred - 1);
     
     struct deferred_entry
     {
       PRUint16                         mFlags;
       nsWeakPtr                        mElement;
     } mEntries[sMaxDeferred];
   };
+
+#ifdef MOZ_IPC
+  friend class mozilla::net::NeckoParent;
+#endif
 };
 
 #endif 
--- a/content/html/content/src/nsHTMLDelElement.cpp
+++ b/content/html/content/src/nsHTMLDelElement.cpp
@@ -40,17 +40,17 @@
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 
 
 class nsHTMLModElement : public nsGenericHTMLElement,
                          public nsIDOMHTMLModElement
 {
 public:
-  nsHTMLModElement(nsINodeInfo *aNodeInfo);
+  nsHTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLModElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -59,44 +59,60 @@ public:
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLModElement
   NS_DECL_NSIDOMHTMLMODELEMENT
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo()
+  {
+    return static_cast<nsXPCClassInfo*>(GetClassInfoInternal());
+  }
+  nsIClassInfo* GetClassInfoInternal();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Mod)
 
-nsHTMLModElement::nsHTMLModElement(nsINodeInfo *aNodeInfo)
+nsHTMLModElement::nsHTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLModElement::~nsHTMLModElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLModElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLModElement, nsGenericElement)
 
 DOMCI_DATA(HTMLDelElement, nsHTMLModElement)
 DOMCI_DATA(HTMLInsElement, nsHTMLModElement)
 
+nsIClassInfo* 
+nsHTMLModElement::GetClassInfoInternal()
+{
+  if (mNodeInfo->Equals(nsGkAtoms::del)) {
+    return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLDelElement_id);
+  }
+  if (mNodeInfo->Equals(nsGkAtoms::ins)) {
+    return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLInsElement_id);
+  }
+  return nsnull;
+}
+
 // QueryInterface implementation for nsHTMLModElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLModElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLModElement, nsIDOMHTMLModElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLModElement,
                                                nsGenericHTMLElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_IF_TAG(HTMLDelElement, del)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_IF_TAG(HTMLInsElement, ins)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_GETTER(GetClassInfoInternal)
 NS_HTML_CONTENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLModElement)
 
 
 NS_IMPL_URI_ATTR(nsHTMLModElement, Cite, cite)
 NS_IMPL_STRING_ATTR(nsHTMLModElement, DateTime, datetime)
--- a/content/html/content/src/nsHTMLDivElement.cpp
+++ b/content/html/content/src/nsHTMLDivElement.cpp
@@ -40,17 +40,17 @@
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 class nsHTMLDivElement : public nsGenericHTMLElement,
                          public nsIDOMHTMLDivElement
 {
 public:
-  nsHTMLDivElement(nsINodeInfo *aNodeInfo);
+  nsHTMLDivElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLDivElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -65,38 +65,38 @@ public:
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Div)
 
 
-nsHTMLDivElement::nsHTMLDivElement(nsINodeInfo *aNodeInfo)
+nsHTMLDivElement::nsHTMLDivElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLDivElement::~nsHTMLDivElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLDivElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLDivElement, nsGenericElement) 
 
-
-
-DOMCI_DATA(HTMLDivElement, nsHTMLDivElement)
+DOMCI_NODE_DATA(HTMLDivElement, nsHTMLDivElement)
 
 // QueryInterface implementation for nsHTMLDivElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLDivElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLDivElement, nsIDOMHTMLDivElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLDivElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLDivElement)
 
@@ -181,8 +181,9 @@ nsHTMLDivElement::GetAttributeMappingFun
   if (mNodeInfo->Equals(nsGkAtoms::div)) {
     return &MapAttributesIntoRule;
   }
   if (mNodeInfo->Equals(nsGkAtoms::marquee)) {
     return &MapMarqueeAttributesIntoRule;
   }  
   return nsGenericHTMLElement::GetAttributeMappingFunction();
 }
+
--- a/content/html/content/src/nsHTMLElement.cpp
+++ b/content/html/content/src/nsHTMLElement.cpp
@@ -38,17 +38,17 @@
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLElement.h"
 
 
 class nsHTMLElement : public nsGenericHTMLElement,
                       public nsIDOMHTMLElement
 {
 public:
-  nsHTMLElement(nsINodeInfo *aNodeInfo);
+  nsHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -56,39 +56,42 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 // Here, we expand 'NS_IMPL_NS_NEW_HTML_ELEMENT()' by hand.
 // (Calling the macro directly (with no args) produces compiler warnings.)
 nsGenericHTMLElement*
-NS_NewHTMLElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+NS_NewHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                  PRUint32 aFromParser)
 {
   return new nsHTMLElement(aNodeInfo);
 }
 
-nsHTMLElement::nsHTMLElement(nsINodeInfo* aNodeInfo)
+nsHTMLElement::nsHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLElement::~nsHTMLElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLElement, nsGenericElement)
 
-DOMCI_DATA(HTMLElement, nsHTMLElement)
+DOMCI_NODE_DATA(HTMLElement, nsHTMLElement)
 
 NS_INTERFACE_TABLE_HEAD(nsHTMLElement)
   NS_HTML_CONTENT_INTERFACE_TABLE0(nsHTMLElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLElement)
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -42,17 +42,17 @@
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 
 
 class nsHTMLFieldSetElement : public nsGenericHTMLFormElement,
                               public nsIDOMHTMLFieldSetElement
 {
 public:
-  nsHTMLFieldSetElement(nsINodeInfo *aNodeInfo);
+  nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFieldSetElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
 
@@ -66,40 +66,40 @@ public:
   NS_DECL_NSIDOMHTMLFIELDSETELEMENT
 
   // nsIFormControl
   NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_FIELDSET; }
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
                                nsIContent* aSubmitElement);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 // construction, destruction
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet)
 
 
-nsHTMLFieldSetElement::nsHTMLFieldSetElement(nsINodeInfo *aNodeInfo)
+nsHTMLFieldSetElement::nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo)
 {
 }
 
 nsHTMLFieldSetElement::~nsHTMLFieldSetElement()
 {
 }
 
 // nsISupports
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFieldSetElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFieldSetElement, nsGenericElement)
 
-
-DOMCI_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
+DOMCI_NODE_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
 
 // QueryInterface implementation for nsHTMLFieldSetElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLFieldSetElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFieldSetElement,
                                    nsIDOMHTMLFieldSetElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFieldSetElement,
                                                nsGenericHTMLFormElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFieldSetElement)
--- a/content/html/content/src/nsHTMLFontElement.cpp
+++ b/content/html/content/src/nsHTMLFontElement.cpp
@@ -46,17 +46,17 @@
 #include "nsCSSStruct.h"
 #include "nsRuleData.h"
 #include "nsIDocument.h"
 
 class nsHTMLFontElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLFontElement
 {
 public:
-  nsHTMLFontElement(nsINodeInfo *aNodeInfo);
+  nsHTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFontElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -71,36 +71,36 @@ public:
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Font)
 
 
-nsHTMLFontElement::nsHTMLFontElement(nsINodeInfo *aNodeInfo)
+nsHTMLFontElement::nsHTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLFontElement::~nsHTMLFontElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFontElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFontElement, nsGenericElement)
 
-
-DOMCI_DATA(HTMLFontElement, nsHTMLFontElement)
+DOMCI_NODE_DATA(HTMLFontElement, nsHTMLFontElement)
 
 // QueryInterface implementation for nsHTMLFontElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLFontElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFontElement, nsIDOMHTMLFontElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFontElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFontElement)
 
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -97,30 +97,33 @@ public:
 
   void DropFormReference();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMHTMLCollection interface
   NS_DECL_NSIDOMHTMLCOLLECTION
 
-  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
   {
     FlushPendingNotifications();
 
     *aResult = NS_OK;
 
-    // XXXbz this should start returning nsINode* or something!
-    return static_cast<nsIFormControl*>(mElements.SafeElementAt(aIndex, nsnull));
+    return mElements.SafeElementAt(aIndex, nsnull);
   }
-  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult)
+  virtual nsISupports* GetNamedItem(const nsAString& aName,
+                                    nsWrapperCache **aCache,
+                                    nsresult* aResult)
   {
     *aResult = NS_OK;
 
-    return NamedItemInternal(aName, PR_TRUE);
+    nsISupports *item = NamedItemInternal(aName, PR_TRUE);
+    *aCache = nsnull;
+    return item;
   }
 
   nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
                              const nsAString& aName);
   nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
                                   const nsAString& aName);
   nsresult IndexOfControl(nsIFormControl* aControl,
                           PRInt32* aIndex);
@@ -205,34 +208,35 @@ ShouldBeInElements(nsIFormControl* aForm
 
   return PR_FALSE;
 }
 
 // nsHTMLFormElement implementation
 
 // construction, destruction
 nsGenericHTMLElement*
-NS_NewHTMLFormElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+NS_NewHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                      PRUint32 aFromParser)
 {
   nsHTMLFormElement* it = new nsHTMLFormElement(aNodeInfo);
   if (!it) {
     return nsnull;
   }
 
   nsresult rv = it->Init();
 
   if (NS_FAILED(rv)) {
     delete it;
     return nsnull;
   }
 
   return it;
 }
 
-nsHTMLFormElement::nsHTMLFormElement(nsINodeInfo *aNodeInfo)
+nsHTMLFormElement::nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mGeneratingSubmit(PR_FALSE),
     mGeneratingReset(PR_FALSE),
     mIsSubmitting(PR_FALSE),
     mDeferSubmission(PR_FALSE),
     mNotifiedObservers(PR_FALSE),
     mNotifiedObserversResult(PR_FALSE),
     mSubmitPopupState(openAbused),
@@ -295,17 +299,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                        nsIDOMHTMLCollection)
   tmp->mSelectedRadioButtons.EnumerateRead(ElementTraverser, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFormElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLFormElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLFormElement, nsHTMLFormElement)
+DOMCI_NODE_DATA(HTMLFormElement, nsHTMLFormElement)
 
 // QueryInterface implementation for nsHTMLFormElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLFormElement)
   NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLFormElement,
                                    nsIDOMHTMLFormElement,
                                    nsIDOMNSHTMLFormElement,
                                    nsIForm,
                                    nsIWebProgressListener,
--- a/content/html/content/src/nsHTMLFormElement.h
+++ b/content/html/content/src/nsHTMLFormElement.h
@@ -88,17 +88,17 @@ private:
 class nsHTMLFormElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLFormElement,
                           public nsIDOMNSHTMLFormElement,
                           public nsIWebProgressListener,
                           public nsIForm,
                           public nsIRadioGroupContainer
 {
 public:
-  nsHTMLFormElement(nsINodeInfo *aNodeInfo);
+  nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFormElement();
 
   nsresult Init();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
@@ -239,16 +239,17 @@ public:
   /**
    * Flag the form to know that a button or image triggered scripted form
    * submission. In that case the form will defer the submission until the
    * script handler returns and the return value is known.
    */
   void OnSubmitClickBegin();
   void OnSubmitClickEnd();
 
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   class RemoveElementRunnable;
   friend class RemoveElementRunnable;
 
   class RemoveElementRunnable : public nsRunnable {
   public:
     RemoveElementRunnable(nsHTMLFormElement* aForm, PRBool aNotify):
       mForm(aForm), mNotify(aNotify)
--- a/content/html/content/src/nsHTMLFrameElement.cpp
+++ b/content/html/content/src/nsHTMLFrameElement.cpp
@@ -41,17 +41,17 @@
 #include "nsIDOMDocument.h"
 #include "nsDOMError.h"
 
 
 class nsHTMLFrameElement : public nsGenericHTMLFrameElement,
                            public nsIDOMHTMLFrameElement
 {
 public:
-  nsHTMLFrameElement(nsINodeInfo *aNodeInfo);
+  nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFrameElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::)
 
@@ -67,37 +67,38 @@ public:
   // nsIContent
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Frame)
 
 
-nsHTMLFrameElement::nsHTMLFrameElement(nsINodeInfo *aNodeInfo)
+nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFrameElement(aNodeInfo)
 {
 }
 
 nsHTMLFrameElement::~nsHTMLFrameElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFrameElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFrameElement, nsGenericElement)
 
 
-DOMCI_DATA(HTMLFrameElement, nsHTMLFrameElement)
+DOMCI_NODE_DATA(HTMLFrameElement, nsHTMLFrameElement)
 
 // QueryInterface implementation for nsHTMLFrameElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLFrameElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFrameElement, nsIDOMHTMLFrameElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFrameElement,
                                                nsGenericHTMLFrameElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameElement)
 
--- a/content/html/content/src/nsHTMLFrameSetElement.cpp
+++ b/content/html/content/src/nsHTMLFrameSetElement.cpp
@@ -43,17 +43,17 @@
 #include "nsIHTMLDocument.h"
 #include "nsIDocument.h"
 
 class nsHTMLFrameSetElement : public nsGenericHTMLElement,
                               public nsIDOMHTMLFrameSetElement,
                               public nsIFrameSetElement
 {
 public:
-  nsHTMLFrameSetElement(nsINodeInfo *aNodeInfo);
+  nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFrameSetElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -84,17 +84,17 @@ public:
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
+  virtual nsXPCClassInfo* GetClassInfo();
 private:
   nsresult ParseRowCol(const nsAString& aValue,
                        PRInt32&         aNumSpecs,
                        nsFramesetSpec** aSpecs);
 
   /**
    * The number of size specs in our "rows" attr
    */
@@ -116,32 +116,32 @@ private:
    * The parsed representation of the "cols" attribute
    */
   nsAutoArrayPtr<nsFramesetSpec>  mColSpecs; // parsed, non-computed dimensions
 };
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(FrameSet)
 
 
-nsHTMLFrameSetElement::nsHTMLFrameSetElement(nsINodeInfo *aNodeInfo)
+nsHTMLFrameSetElement::nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo), mNumRows(0), mNumCols(0),
     mCurrentRowColHint(NS_STYLE_HINT_REFLOW)
 {
 }
 
 nsHTMLFrameSetElement::~nsHTMLFrameSetElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFrameSetElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLFrameSetElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLFrameSetElement, nsHTMLFrameSetElement)
+DOMCI_NODE_DATA(HTMLFrameSetElement, nsHTMLFrameSetElement)
 
 // QueryInterface implementation for nsHTMLFrameSetElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLFrameSetElement)
   NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLFrameSetElement,
                                    nsIDOMHTMLFrameSetElement,
                                    nsIFrameSetElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFrameSetElement,
                                                nsGenericHTMLElement)
@@ -317,20 +317,22 @@ nsHTMLFrameSetElement::ParseRowCol(const
   static const PRUnichar sComma(',');
 
   nsAutoString spec(aValue);
   // remove whitespace (Bug 33699) and quotation marks (bug 224598)
   // also remove leading/trailing commas (bug 31482)
   spec.StripChars(" \n\r\t\"\'");
   spec.Trim(",");
   
-  // Count the commas 
+#define MAX_FRAMESET_SPEC_COUNT 100000
+  // Count the commas. Don't count more than X commas (bug 576447).
+  PR_STATIC_ASSERT(MAX_FRAMESET_SPEC_COUNT * sizeof(nsFramesetSpec) < (1 << 30));
   PRInt32 commaX = spec.FindChar(sComma);
   PRInt32 count = 1;
-  while (commaX != kNotFound) {
+  while (commaX != kNotFound && count < MAX_FRAMESET_SPEC_COUNT) {
     count++;
     commaX = spec.FindChar(sComma, commaX + 1);
   }
 
   nsFramesetSpec* specs = new nsFramesetSpec[count];
   if (!specs) {
     *aSpecs = nsnull;
     aNumSpecs = 0;
--- a/content/html/content/src/nsHTMLHRElement.cpp
+++ b/content/html/content/src/nsHTMLHRElement.cpp
@@ -44,17 +44,17 @@
 #include "nsMappedAttributes.h"
 #include "nsRuleData.h"
 
 class nsHTMLHRElement : public nsGenericHTMLElement,
                         public nsIDOMHTMLHRElement,
                         public nsIDOMNSHTMLHRElement
 {
 public:
-  nsHTMLHRElement(nsINodeInfo *aNodeInfo);
+  nsHTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLHRElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -72,37 +72,38 @@ public:
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(HR)
 
 
-nsHTMLHRElement::nsHTMLHRElement(nsINodeInfo *aNodeInfo)
+nsHTMLHRElement::nsHTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLHRElement::~nsHTMLHRElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLHRElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLHRElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLHRElement, nsHTMLHRElement)
+DOMCI_NODE_DATA(HTMLHRElement, nsHTMLHRElement)
 
 // QueryInterface implementation for nsHTMLHRElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLHRElement)
   NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLHRElement,
                                    nsIDOMHTMLHRElement,
                                    nsIDOMNSHTMLHRElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLHRElement,
                                                nsGenericHTMLElement)
--- a/content/html/content/src/nsHTMLHeadingElement.cpp
+++ b/content/html/content/src/nsHTMLHeadingElement.cpp
@@ -42,17 +42,17 @@
 #include "nsMappedAttributes.h"
 #include "nsRuleData.h"
 #include "mozAutoDocUpdate.h"
 
 class nsHTMLHeadingElement : public nsGenericHTMLElement,
                              public nsIDOMHTMLHeadingElement
 {
 public:
-  nsHTMLHeadingElement(nsINodeInfo *aNodeInfo);
+  nsHTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLHeadingElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -67,37 +67,38 @@ public:
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Heading)
 
 
-nsHTMLHeadingElement::nsHTMLHeadingElement(nsINodeInfo *aNodeInfo)
+nsHTMLHeadingElement::nsHTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLHeadingElement::~nsHTMLHeadingElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLHeadingElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLHeadingElement, nsGenericElement) 
 
 
-DOMCI_DATA(HTMLHeadingElement, nsHTMLHeadingElement)
+DOMCI_NODE_DATA(HTMLHeadingElement, nsHTMLHeadingElement)
 
 // QueryInterface implementation for nsHTMLHeadingElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLHeadingElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLHeadingElement,
                                    nsIDOMHTMLHeadingElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLHeadingElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLHeadingElement)
--- a/content/html/content/src/nsHTMLIFrameElement.cpp
+++ b/content/html/content/src/nsHTMLIFrameElement.cpp
@@ -50,17 +50,17 @@
 
 class nsHTMLIFrameElement : public nsGenericHTMLFrameElement,
                             public nsIDOMHTMLIFrameElement
 #ifdef MOZ_SVG
                             , public nsIDOMGetSVGDocument
 #endif
 {
 public:
-  nsHTMLIFrameElement(nsINodeInfo *aNodeInfo);
+  nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLIFrameElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::)
 
@@ -82,36 +82,37 @@ public:
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(IFrame)
 
 
-nsHTMLIFrameElement::nsHTMLIFrameElement(nsINodeInfo *aNodeInfo)
+nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFrameElement(aNodeInfo)
 {
 }
 
 nsHTMLIFrameElement::~nsHTMLIFrameElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameElement,nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLIFrameElement,nsGenericElement)
 
-DOMCI_DATA(HTMLIFrameElement, nsHTMLIFrameElement)
+DOMCI_NODE_DATA(HTMLIFrameElement, nsHTMLIFrameElement)
 
 // QueryInterface implementation for nsHTMLIFrameElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLIFrameElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(nsHTMLIFrameElement)
     NS_INTERFACE_TABLE_ENTRY(nsHTMLIFrameElement, nsIDOMHTMLIFrameElement)
 #ifdef MOZ_SVG
     NS_INTERFACE_TABLE_ENTRY(nsHTMLIFrameElement, nsIDOMGetSVGDocument)
 #endif
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -80,17 +80,17 @@
 
 class nsHTMLImageElement : public nsGenericHTMLElement,
                            public nsImageLoadingContent,
                            public nsIDOMHTMLImageElement,
                            public nsIDOMNSHTMLImageElement,
                            public nsIJSNativeInitializer
 {
 public:
-  nsHTMLImageElement(nsINodeInfo *aNodeInfo);
+  nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLImageElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
@@ -145,23 +145,25 @@ public:
                               PRBool aCompileEventHandlers);
 
   virtual PRInt32 IntrinsicState() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   nsresult CopyInnerTo(nsGenericElement* aDest) const;
 
   void MaybeLoadImage();
+  virtual nsXPCClassInfo* GetClassInfo();
 protected:
   nsPoint GetXY();
   nsSize GetWidthHeight();
 };
 
 nsGenericHTMLElement*
-NS_NewHTMLImageElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
+NS_NewHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                       PRUint32 aFromParser)
 {
   /*
    * nsHTMLImageElement's will be created without a nsINodeInfo passed in
    * if someone says "var img = new Image();" in JavaScript, in a case like
    * that we request the nsINodeInfo from the document's nodeinfo list.
    */
   nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
   if (!nodeInfo) {
@@ -169,35 +171,35 @@ NS_NewHTMLImageElement(nsINodeInfo *aNod
       do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
     NS_ENSURE_TRUE(doc, nsnull);
 
     nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::img, nsnull,
                                                    kNameSpaceID_XHTML);
     NS_ENSURE_TRUE(nodeInfo, nsnull);
   }
 
-  return new nsHTMLImageElement(nodeInfo);
+  return new nsHTMLImageElement(nodeInfo.forget());
 }
 
-nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo)
+nsHTMLImageElement::nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
 nsHTMLImageElement::~nsHTMLImageElement()
 {
   DestroyImageLoadingContent();
 }
 
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLImageElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLImageElement, nsGenericElement)
 
 
-DOMCI_DATA(HTMLImageElement, nsHTMLImageElement)
+DOMCI_NODE_DATA(HTMLImageElement, nsHTMLImageElement)
 
 // QueryInterface implementation for nsHTMLImageElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLImageElement)
   NS_HTML_CONTENT_INTERFACE_TABLE6(nsHTMLImageElement,
                                    nsIDOMHTMLImageElement,
                                    nsIDOMNSHTMLImageElement,
                                    nsIJSNativeInitializer,
                                    imgIDecoderObserver,
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -122,18 +122,16 @@ static NS_DEFINE_CID(kLookAndFeelCID, NS
 #define NS_OUTER_ACTIVATE_EVENT   (1 << 9)
 #define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
 #define NS_NO_CONTENT_DISPATCH    (1 << 11)
 #define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
 #define NS_CONTROL_TYPE(bits)  ((bits) & ~( \
   NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
   NS_ORIGINAL_INDETERMINATE_VALUE))
 
-static const char kWhitespace[] = "\n\r\t\b";
-
 // whether textfields should be selected once focused:
 //  -1: no, 1: yes, 0: uninitialized
 static PRInt32 gSelectTextFieldOnFocus;
 
 static const nsAttrValue::EnumTable kInputTypeTable[] = {
   { "button", NS_FORM_INPUT_BUTTON },
   { "checkbox", NS_FORM_INPUT_CHECKBOX },
   { "file", NS_FORM_INPUT_FILE },
@@ -219,17 +217,17 @@ static nsresult FireEventForAccessibilit
 #endif
 
 //
 // construction, destruction
 //
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Input)
 
-nsHTMLInputElement::nsHTMLInputElement(nsINodeInfo *aNodeInfo,
+nsHTMLInputElement::nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                        PRUint32 aFromParser)
   : nsGenericHTMLFormElement(aNodeInfo),
     mType(kInputDefaultType->value),