Merge m-c to bs.
authorKyle Huey <khuey@kylehuey.com>
Thu, 31 Mar 2011 07:17:15 -0400
changeset 64448 ad4889b72e448992095fa7acd792aa3e562ff0c4
parent 64447 3a205e920ec02d3fa8184fcd6dccda444ac1ab13 (current diff)
parent 64446 422bbd8245a728ebedbd64433dec253baa6c10d0 (diff)
child 64449 a5dbece71e4abc15d58b2e390235fb0af420a124
push id19345
push userkhuey@kylehuey.com
push dateThu, 31 Mar 2011 11:34:17 +0000
treeherdermozilla-central@b7534c685c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.2a1pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to bs.
config/autoconf.mk.in
configure.in
dom/interfaces/core/nsIDOM3Document.idl
dom/interfaces/load-save/nsIDOMDOMImplementationLS.idl
dom/interfaces/load-save/nsIDOMLSException.idl
dom/interfaces/load-save/nsIDOMLSInput.idl
dom/interfaces/load-save/nsIDOMLSLoadEvent.idl
dom/interfaces/load-save/nsIDOMLSOutput.idl
dom/interfaces/load-save/nsIDOMLSParser.idl
dom/interfaces/load-save/nsIDOMLSParserFilter.idl
dom/interfaces/load-save/nsIDOMLSResourceResolver.idl
dom/interfaces/load-save/nsIDOMLSSerializer.idl
dom/interfaces/load-save/nsIDOMLSSerializerFilter.idl
intl/uconv/tests/unit/test_bug335531.js
intl/uconv/ucvja/jis0212.uf
intl/uconv/ucvko/nsUnicodeToISO2022KR.cpp
intl/uconv/ucvko/nsUnicodeToISO2022KR.h
intl/uconv/ucvlatin/nsUTF32ToUnicode.cpp
intl/uconv/ucvlatin/nsUTF32ToUnicode.h
intl/uconv/ucvlatin/nsUnicodeToUTF32.cpp
intl/uconv/ucvlatin/nsUnicodeToUTF32.h
intl/uconv/ucvlatin/nsUnicodeToVIQR.cpp
intl/uconv/ucvlatin/nsUnicodeToVIQR.h
intl/uconv/ucvlatin/nsUnicodeToVNI.cpp
intl/uconv/ucvlatin/nsUnicodeToVNI.h
intl/uconv/ucvlatin/nsVIQRToUnicode.cpp
intl/uconv/ucvlatin/nsVIQRToUnicode.h
intl/uconv/ucvlatin/nsVNIToUnicode.cpp
intl/uconv/ucvlatin/nsVNIToUnicode.h
jpeg/cdjpeg.c
jpeg/change.log
jpeg/cjpeg.c
jpeg/ckconfig.c
jpeg/coderules.doc
jpeg/djpeg.c
jpeg/example.c
jpeg/filelist.doc
jpeg/install.doc
jpeg/jconfig-mac-cw.h
jpeg/jconfig.doc
jpeg/jconfig.wat
jpeg/jmemansi.c
jpeg/jmemdos.c
jpeg/jmemdosa.asm
jpeg/jmemname.c
jpeg/jos2fig.h
jpeg/jwinfig.h
jpeg/libjpeg.doc
jpeg/makefile.gen
jpeg/netscape_mods.doc
jpeg/structure.doc
jpeg/usage.doc
jpeg/wizard.doc
js/src/jit-test/tests/basic/bug633890.js
js/src/tests/js1_8/extensions/regress-476871-01.js
layout/style/nsCSSStruct.cpp
layout/style/nsCSSStruct.h
toolkit/mozapps/installer/packager.mk
toolkit/themes/pinstripe/global/tree/sort-asc.gif
toolkit/themes/pinstripe/global/tree/sort-dsc.gif
webshell/Makefile.in
webshell/public/Makefile.in
webshell/public/nsIClipboardCommands.idl
webshell/public/nsIContentViewerContainer.idl
webshell/public/nsIDocumentLoaderFactory.idl
webshell/public/nsILinkHandler.h
webshell/public/nsIRefreshURI.idl
webshell/public/nsIWebShellServices.h
--- a/README.txt
+++ b/README.txt
@@ -18,8 +18,10 @@ on http://developer.mozilla.org, you can
 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.]
 
 You can download nightly development builds from the Mozilla FTP server.
 Keep in mind that nightly builds, which are used by Mozilla developers for
 testing, may be buggy. Firefox nightlies, for example, can be found at:
 
     ftp://ftp.mozilla.org/pub/firefox/nightly/latest-trunk/
+            - or -
+    http://nightly.mozilla.org/
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -1267,16 +1267,37 @@ nsAccessibleWrap::FirePlatformEvent(AccE
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
         nsRootAccessible *rootAcc =
           static_cast<nsRootAccessible *>(accessible);
         rootAcc->mActivated = PR_FALSE;
         guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
         g_signal_emit(atkObj, id, 0);
       } break;
 
+    case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
+      {
+        MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MAXIMIZE\n"));
+        guint id = g_signal_lookup ("maximize", MAI_TYPE_ATK_OBJECT);
+        g_signal_emit(atkObj, id, 0);
+      } break;
+
+    case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE:
+      {
+        MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MINIMIZE\n"));
+        guint id = g_signal_lookup ("minimize", MAI_TYPE_ATK_OBJECT);
+        g_signal_emit(atkObj, id, 0);
+      } break;
+
+    case nsIAccessibleEvent::EVENT_WINDOW_RESTORE:
+      {
+        MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_RESTORE\n"));
+        guint id = g_signal_lookup ("restore", MAI_TYPE_ATK_OBJECT);
+        g_signal_emit(atkObj, id, 0);
+      } break;
+
     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
         g_signal_emit_by_name (atkObj, "load_complete");
       } break;
 
     case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
       {
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -213,16 +213,34 @@ mai_util_get_type(void)
         };
 
         type = g_type_register_static(ATK_TYPE_UTIL,
                                       "MaiUtil", &tinfo, GTypeFlags(0));
     }
     return type;
 }
 
+static void
+window_added (AtkObject *atk_obj,
+              guint     index,
+              AtkObject *child)
+{
+  guint id =  g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
+  g_signal_emit (child, id, 0);
+}
+
+static void
+window_removed (AtkObject *atk_obj,
+                guint     index,
+                AtkObject *child)
+{
+  guint id =  g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
+  g_signal_emit (child, id, 0);
+}
+
 /* intialize the the atk interface (function pointers) with MAI implementation.
  * When atk bridge get loaded, these interface can be used.
  */
 static void
 mai_util_class_init(MaiUtilClass *klass)
 {
     AtkUtilClass *atk_class;
     gpointer data;
@@ -243,16 +261,20 @@ mai_util_class_init(MaiUtilClass *klass)
     atk_class->add_key_event_listener = mai_util_add_key_event_listener;
     atk_class->remove_key_event_listener = mai_util_remove_key_event_listener;
     atk_class->get_root = mai_util_get_root;
     atk_class->get_toolkit_name = mai_util_get_toolkit_name;
     atk_class->get_toolkit_version = mai_util_get_toolkit_version;
 
     listener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
                                           _listener_info_destroy);
+    // Keep track of added/removed windows.
+    AtkObject *root = atk_get_root ();
+    g_signal_connect (root, "children-changed::add", (GCallback) window_added, NULL);
+    g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, NULL);
 }
 
 static guint
 mai_util_add_global_event_listener(GSignalEmissionHook listener,
                                    const gchar *event_type)
 {
     guint rc = 0;
     gchar **split_string;
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -299,20 +299,20 @@ NotificationController::WillRefresh(mozi
   events.SwapElements(mEvents);
 
   PRUint32 eventCount = events.Length();
   for (PRUint32 idx = 0; idx < eventCount; idx++) {
     AccEvent* accEvent = events[idx];
     if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
       mDocument->ProcessPendingEvent(accEvent);
 
-      AccMutationEvent* showOrhideEvent = downcast_accEvent(accEvent);
-      if (showOrhideEvent) {
-        if (showOrhideEvent->mTextChangeEvent)
-          mDocument->ProcessPendingEvent(showOrhideEvent->mTextChangeEvent);
+      AccMutationEvent* showOrHideEvent = downcast_accEvent(accEvent);
+      if (showOrHideEvent) {
+        if (showOrHideEvent->mTextChangeEvent)
+          mDocument->ProcessPendingEvent(showOrHideEvent->mTextChangeEvent);
       }
     }
     if (!mDocument)
       return;
   }
 
   // Stop further processing if there are no newly queued insertions,
   // notifications or events.
--- a/accessible/src/base/TextUpdater.cpp
+++ b/accessible/src/base/TextUpdater.cpp
@@ -65,17 +65,20 @@ TextUpdater::Run(nsDocAccessible* aDocum
   }
 }
 
 void
 TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
                       PRUint32 aSkipStart)
 {
   nsAccessible* parent = mTextLeaf->GetParent();
-  NS_ASSERTION(parent, "No parent for text leaf!");
+  if (!parent) {
+    NS_ERROR("No parent for text leaf!");
+    return;
+  }
 
   mHyperText = parent->AsHyperText();
   if (!mHyperText) {
     NS_ERROR("Text leaf parent is not hypertext!");
     return;
   }
 
   // Get the text leaf accessible offset and invalidate cached offsets after it.
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -39,17 +39,16 @@
 #include "nsCoreUtils.h"
 #include "nsAccUtils.h"
 
 #include "nsIAccessibleStates.h"
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccessibilityAtoms.h"
-#include "nsAccTreeWalker.h"
 #include "nsARIAMap.h"
 #include "nsDocAccessible.h"
 #include "nsHyperTextAccessible.h"
 #include "nsHTMLTableAccessible.h"
 #include "nsTextAccessible.h"
 #include "nsXULTreeGridAccessible.h"
 
 #include "nsIDOMXULContainerElement.h"
@@ -329,33 +328,16 @@ nsAccUtils::HasDefinedARIAToken(nsIConte
                             nsAccessibilityAtoms::_empty, eCaseMatters) ||
       aContent->AttrValueIs(kNameSpaceID_None, aAtom,
                             nsAccessibilityAtoms::_undefined, eCaseMatters)) {
         return PR_FALSE;
   }
   return PR_TRUE;
 }
 
-PRBool
-nsAccUtils::HasAccessibleChildren(nsINode *aNode)
-{
-  if (!aNode)
-    return PR_FALSE;
-
-  nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode);
-  if (!presShell)
-    return PR_FALSE;
-
-  nsIContent *content = nsCoreUtils::GetRoleContent(aNode);
-  nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
-  nsAccTreeWalker walker(weakShell, content, PR_FALSE);
-  nsRefPtr<nsAccessible> accessible = walker.GetNextChild();
-  return accessible ? PR_TRUE : PR_FALSE;
-}
-
 nsAccessible *
 nsAccUtils::GetAncestorWithRole(nsAccessible *aDescendant, PRUint32 aRole)
 {
   nsAccessible *document = aDescendant->GetDocAccessible();
   nsAccessible *parent = aDescendant;
   while ((parent = parent->GetParent())) {
     PRUint32 testRole = parent->Role();
     if (testRole == aRole)
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -178,21 +178,16 @@ public:
     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
     nsCOMPtr<nsIPresShell> presShell;
     docShell->GetPresShell(getter_AddRefs(presShell));
     return presShell ?
       GetAccService()->GetDocAccessible(presShell->GetDocument()) : nsnull;
   }
 
   /**
-   * Return true if the given DOM node contains accessible children.
-   */
-  static PRBool HasAccessibleChildren(nsINode *aNode);
-
-  /**
     * Return ancestor in this document with the given role if it exists.
     *
     * @param  aDescendant  [in] descendant to start search with
     * @param  aRole        [in] role to find matching ancestor for
     * @return               the ancestor accessible with the given role, or
     *                       nsnull if no match is found
     */
    static nsAccessible * GetAncestorWithRole(nsAccessible *aDescendant,
@@ -370,26 +365,16 @@ public:
   {
     PRUint32 role = Role(aAcc);
     return role != nsIAccessibleRole::ROLE_TEXT_LEAF &&
            role != nsIAccessibleRole::ROLE_WHITESPACE &&
            role != nsIAccessibleRole::ROLE_STATICTEXT;
   }
 
   /**
-   * Return true if the given accessible hasn't children.
-   */
-  static inline PRBool IsLeaf(nsIAccessible *aAcc)
-  {
-    PRInt32 numChildren = 0;
-    aAcc->GetChildCount(&numChildren);
-    return numChildren == 0;
-  }
-
-  /**
    * Return true if the given accessible can't have children. Used when exposing
    * to platform accessibility APIs, should the children be pruned off?
    */
   static PRBool MustPrune(nsIAccessible *aAccessible);
 
   /**
    * Search hint enum constants. Used by GetHeaderCellsFor() method.
    */
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -95,16 +95,18 @@
 #endif
 
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
 #include "mozilla/FunctionTimer.h"
+#include "mozilla/dom/Element.h"
+#include "nsImageMapUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
 PRBool nsAccessibilityService::gIsShutdown = PR_TRUE;
 
@@ -258,31 +260,22 @@ nsAccessibilityService::CreateHTMLCombob
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
                                                   nsIPresShell* aPresShell)
 {
-  nsCOMPtr<nsIHTMLDocument> htmlDoc =
-    do_QueryInterface(aContent->GetCurrentDoc());
-
-  nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
-  if (htmlDoc) {
-    nsAutoString mapElmName;
-    aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::usemap,
-                      mapElmName);
-
-    if (!mapElmName.IsEmpty()) {
-      if (mapElmName.CharAt(0) == '#')
-        mapElmName.Cut(0,1);
-      mapElm = htmlDoc->GetImageMap(mapElmName);
-    }
-  }
+  nsAutoString mapElmName;
+  aContent->GetAttr(kNameSpaceID_None,
+                    nsAccessibilityAtoms::usemap,
+                    mapElmName);
+  nsCOMPtr<nsIDOMHTMLMapElement> mapElm =
+    nsImageMapUtils::FindImageMap(aContent->GetCurrentDoc(), mapElmName);
 
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
   nsAccessible* accessible = mapElm ?
     new nsHTMLImageMapAccessible(aContent, weakShell, mapElm) :
     new nsHTMLImageAccessibleWrap(aContent, weakShell);
   NS_IF_ADDREF(accessible);
   return accessible;
 }
@@ -533,16 +526,32 @@ nsAccessibilityService::UpdateText(nsIPr
                                    nsIContent* aContent)
 {
   nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
   if (document)
     document->UpdateText(aContent);
 }
 
 void
+nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
+                                         nsIContent* aHTMLListItemContent,
+                                         bool aHasBullet)
+{
+  nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
+  if (document) {
+    nsAccessible* accessible = document->GetAccessible(aHTMLListItemContent);
+    if (accessible) {
+      nsHTMLLIAccessible* listItem = accessible->AsHTMLListItem();
+      if (listItem)
+        listItem->UpdateBullet(aHasBullet);
+    }
+  }
+}
+
+void
 nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
 {
   // Presshell destruction will automatically destroy shells for descendant
   // documents, so no need to worry about those. Just shut down the accessible
   // for this one document. That keeps us from having bad behavior in case of
   // deep bushy subtrees.
   // When document subtree containing iframe is hidden then we don't get
   // pagehide event for the iframe's underlying document and its presshell is
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -115,16 +115,23 @@ public:
                                     nsIContent* aStartChild,
                                     nsIContent* aEndChild);
 
   virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
                               nsIContent* aChild);
 
   virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
 
+  /**
+   * Update list bullet accessible.
+   */
+  virtual void UpdateListBullet(nsIPresShell* aPresShell,
+                                nsIContent* aHTMLListItemContent,
+                                bool aHasBullet);
+
   virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
 
   virtual void PresShellDestroyed(nsIPresShell* aPresShell);
 
   /**
    * Notify that presshell is activated.
    */
   virtual void PresShellActivated(nsIPresShell* aPresShell);
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -760,70 +760,64 @@ nsAccessible::GetFocusedChild(nsIAccessi
       focusedChild = nsnull;
   }
 
   NS_IF_ADDREF(*aFocusedChild = focusedChild);
   return NS_OK;
 }
 
 // nsAccessible::GetChildAtPoint()
-nsresult
-nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, PRBool aDeepestChild,
-                              nsIAccessible **aChild)
+nsAccessible*
+nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                              EWhichChildAtPoint aWhichChild)
 {
   // If we can't find the point in a child, we will return the fallback answer:
   // we return |this| if the point is within it, otherwise nsnull.
   PRInt32 x = 0, y = 0, width = 0, height = 0;
   nsresult rv = GetBounds(&x, &y, &width, &height);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIAccessible> fallbackAnswer;
+  NS_ENSURE_SUCCESS(rv, nsnull);
+
+  nsAccessible* fallbackAnswer = nsnull;
   if (aX >= x && aX < x + width && aY >= y && aY < y + height)
     fallbackAnswer = this;
 
-  if (nsAccUtils::MustPrune(this)) {  // Do not dig any further
-    NS_IF_ADDREF(*aChild = fallbackAnswer);
-    return NS_OK;
-  }
+  if (nsAccUtils::MustPrune(this))  // Do not dig any further
+    return fallbackAnswer;
 
   // Search an accessible at the given point starting from accessible document
   // because containing block (see CSS2) for out of flow element (for example,
   // absolutely positioned element) may be different from its DOM parent and
   // therefore accessible for containing block may be different from accessible
   // for DOM parent but GetFrameForPoint() should be called for containing block
   // to get an out of flow element.
   nsDocAccessible *accDocument = GetDocAccessible();
-  NS_ENSURE_TRUE(accDocument, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(accDocument, nsnull);
 
   nsIFrame *frame = accDocument->GetFrame();
-  NS_ENSURE_STATE(frame);
+  NS_ENSURE_TRUE(frame, nsnull);
 
   nsPresContext *presContext = frame->PresContext();
 
   nsIntRect screenRect = frame->GetScreenRectExternal();
   nsPoint offset(presContext->DevPixelsToAppUnits(aX - screenRect.x),
                  presContext->DevPixelsToAppUnits(aY - screenRect.y));
 
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
   nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
 
   nsIContent* content = nsnull;
-  if (!foundFrame || !(content = foundFrame->GetContent())) {
-    NS_IF_ADDREF(*aChild = fallbackAnswer);
-    return NS_OK;
-  }
+  if (!foundFrame || !(content = foundFrame->GetContent()))
+    return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   nsAccessible* accessible =
    GetAccService()->GetAccessibleOrContainer(content, mWeakShell);
-  if (!accessible) {
-    NS_IF_ADDREF(*aChild = fallbackAnswer);
-    return NS_OK;
-  }
+  if (!accessible)
+    return fallbackAnswer;
 
   if (accessible == this) {
     // Manually walk through accessible children and see if the are within this
     // point. Skip offscreen or invisible accessibles. This takes care of cases
     // where layout won't walk into things for us, such as image map areas and
     // sub documents (XXX: subdocuments should be handled by methods of
     // nsOuterDocAccessibles).
     PRInt32 childCount = GetChildCount();
@@ -831,78 +825,76 @@ nsAccessible::GetChildAtPoint(PRInt32 aX
       nsAccessible *child = GetChildAt(childIdx);
 
       PRInt32 childX, childY, childWidth, childHeight;
       child->GetBounds(&childX, &childY, &childWidth, &childHeight);
       if (aX >= childX && aX < childX + childWidth &&
           aY >= childY && aY < childY + childHeight &&
           (nsAccUtils::State(child) & nsIAccessibleStates::STATE_INVISIBLE) == 0) {
 
-        if (aDeepestChild)
-          return child->GetDeepestChildAtPoint(aX, aY, aChild);
-
-        NS_IF_ADDREF(*aChild = child);
-        return NS_OK;
+        if (aWhichChild == eDeepestChild)
+          return child->GetChildAtPoint(aX, aY, eDeepestChild);
+
+        return child;
       }
     }
 
     // The point is in this accessible but not in a child. We are allowed to
     // return |this| as the answer.
-    NS_IF_ADDREF(*aChild = accessible);
-    return NS_OK;
+    return accessible;
   }
 
   // Since DOM node of obtained accessible may be out of flow then we should
   // ensure obtained accessible is a child of this accessible.
-  nsCOMPtr<nsIAccessible> parent, child(accessible);
-  while (PR_TRUE) {
-    child->GetParent(getter_AddRefs(parent));
+  nsAccessible* child = accessible;
+  while (true) {
+    nsAccessible* parent = child->GetParent();
     if (!parent) {
       // Reached the top of the hierarchy. These bounds were inside an
       // accessible that is not a descendant of this one.
-      NS_IF_ADDREF(*aChild = fallbackAnswer);      
-      return NS_OK;
+      return fallbackAnswer;
     }
 
-    if (parent == this) {
-      NS_ADDREF(*aChild = (aDeepestChild ? accessible : child));
-      return NS_OK;
-    }
-    child.swap(parent);
+    if (parent == this)
+      return aWhichChild == eDeepestChild ? accessible : child;
+
+    child = parent;
   }
 
-  return NS_OK;
+  return nsnull;
 }
 
 // nsIAccessible getChildAtPoint(in long x, in long y)
 NS_IMETHODIMP
 nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                               nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  return GetChildAtPoint(aX, aY, PR_FALSE, aAccessible);
+  NS_IF_ADDREF(*aAccessible = GetChildAtPoint(aX, aY, eDirectChild));
+  return NS_OK;
 }
 
 // nsIAccessible getDeepestChildAtPoint(in long x, in long y)
 NS_IMETHODIMP
 nsAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
                                      nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  return GetChildAtPoint(aX, aY, PR_TRUE, aAccessible);
+  NS_IF_ADDREF(*aAccessible = GetChildAtPoint(aX, aY, eDeepestChild));
+  return NS_OK;
 }
 
 void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
 {
 /*
  * This method is used to determine the bounds of a content node.
  * Because HTML wraps and links are not always rectangular, this
  * method uses the following algorithm:
@@ -2711,17 +2703,17 @@ nsAccessible::GetNameInternal(nsAString&
 void
 nsAccessible::BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent)
 {
   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
 
   if (mParent) {
     if (mParent != aParent) {
       NS_ERROR("Adopting child!");
-      mParent->InvalidateChildren();
+      mParent->RemoveChild(this);
     } else {
       NS_ERROR("Binding to the same parent!");
       return;
     }
   }
 
   mParent = aParent;
   mIndexInParent = aIndexInParent;
@@ -3223,25 +3215,47 @@ nsAccessible::GetSiblingAtOffset(PRInt32
     *aError = NS_ERROR_UNEXPECTED;
 
   return child;
 }
 
 nsAccessible *
 nsAccessible::GetFirstAvailableAccessible(nsINode *aStartNode) const
 {
-  nsAccessible *accessible =
+  nsAccessible* accessible =
     GetAccService()->GetAccessibleInWeakShell(aStartNode, mWeakShell);
   if (accessible)
     return accessible;
 
-  nsIContent *content = nsCoreUtils::GetRoleContent(aStartNode);
-  nsAccTreeWalker walker(mWeakShell, content, PR_FALSE);
-  nsRefPtr<nsAccessible> childAccessible = walker.GetNextChild();
-  return childAccessible;
+  nsCOMPtr<nsIDOMDocumentTraversal> trav =
+    do_QueryInterface(aStartNode->GetOwnerDoc());
+  NS_ENSURE_TRUE(trav, nsnull);
+
+  nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aStartNode);
+  nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(GetNode()));
+  nsCOMPtr<nsIDOMTreeWalker> walker;
+  trav->CreateTreeWalker(rootNode,
+                         nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
+                         nsnull, PR_FALSE, getter_AddRefs(walker));
+  NS_ENSURE_TRUE(walker, nsnull);
+
+  walker->SetCurrentNode(currentNode);
+  while (true) {
+    walker->NextNode(getter_AddRefs(currentNode));
+    if (!currentNode)
+      return nsnull;
+
+    nsCOMPtr<nsINode> node(do_QueryInterface(currentNode));
+    nsAccessible* accessible =
+      GetAccService()->GetAccessibleInWeakShell(node, mWeakShell);
+    if (accessible)
+      return accessible;
+  }
+
+  return nsnull;
 }
 
 PRBool nsAccessible::CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView)
 {
   nsIDocument* document = aDocument;
   nsIView* view = aView;
   // both view chain and widget chain are broken between chrome and content
   while (document != nsnull) {
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -53,16 +53,17 @@
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 
 class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class nsAccessible;
 class nsHyperTextAccessible;
+class nsHTMLLIAccessible;
 struct nsRoleMapEntry;
 class nsTextAccessible;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
 class nsIView;
@@ -184,26 +185,33 @@ public:
 
   /**
    * Returns attributes for accessible without explicitly setted ARIA
    * attributes.
    */
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
   /**
+   * Used by GetChildAtPoint() method to get direct or deepest child at point.
+   */
+  enum EWhichChildAtPoint {
+    eDirectChild,
+    eDeepestChild
+  };
+
+  /**
    * Return direct or deepest child at the given point.
    *
-   * @param  aX             [in] x coordinate relative screen
-   * @param  aY             [in] y coordinate relative screen
-   * @param  aDeepestChild  [in] flag points if deep child should be returned
-   * @param  aChild         [out] found child
+   * @param  aX           [in] x coordinate relative screen
+   * @param  aY           [in] y coordinate relative screen
+   * @param  aWhichChild  [in] flag points if deepest or direct child
+   *                        should be returned
    */
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   /**
    * Return calculated group level based on accessible hierarchy.
    */
   virtual PRInt32 GetLevelInternal();
 
   /**
    * Calculate position in group and group size ('posinset' and 'setsize') based
@@ -359,16 +367,19 @@ public:
   //////////////////////////////////////////////////////////////////////////////
   // Downcasting
 
   inline bool IsApplication() const { return mFlags & eApplicationAccessible; }
 
   inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
   nsHyperTextAccessible* AsHyperText();
 
+  inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
+  nsHTMLLIAccessible* AsHTMLListItem();
+
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   nsRootAccessible* AsRoot();
 
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
   // HyperLinkAccessible
@@ -507,18 +518,19 @@ protected:
 
   /**
    * Flags describing the accessible itself.
    * @note keep these flags in sync with ChildrenFlags
    */
   enum AccessibleTypes {
     eApplicationAccessible = 1 << 2,
     eHyperTextAccessible = 1 << 3,
-    eRootAccessible = 1 << 4,
-    eTextLeafAccessible = 1 << 5
+    eHTMLListItemAccessible = 1 << 4,
+    eRootAccessible = 1 << 5,
+    eTextLeafAccessible = 1 << 6
   };
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
   /**
    * Return ARIA role (helper method).
    */
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -165,32 +165,21 @@ nsApplicationAccessible::GroupPosition(P
   *aGroupLevel = 0;
   NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
   *aSimilarItemsInGroup = 0;
   NS_ENSURE_ARG_POINTER(aPositionInGroup);
   *aPositionInGroup = 0;
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsAccessible*
 nsApplicationAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                         nsIAccessible **aChild)
+                                         EWhichChildAtPoint aWhichChild)
 {
-  NS_ENSURE_ARG_POINTER(aChild);
-  *aChild = nsnull;
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsApplicationAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                                nsIAccessible **aChild)
-{
-  NS_ENSURE_ARG_POINTER(aChild);
-  *aChild = nsnull;
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return nsnull;
 }
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetRelationByType(PRUint32 aRelationType,
                                            nsIAccessibleRelation **aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nsnull;
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -93,18 +93,16 @@ public:
   NS_IMETHOD GetName(nsAString &aName);
   NS_IMETHOD GetValue(nsAString &aValue);
   NS_IMETHOD GetDescription(nsAString &aDescription);
   NS_IMETHOD GetKeyboardShortcut(nsAString &aKeyboardShortcut);
   NS_IMETHOD GetState(PRUint32 *aState , PRUint32 *aExtraState );
   NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
   NS_IMETHOD GroupPosition(PRInt32 *aGroupLevel, PRInt32 *aSimilarItemsInGroup,
                            PRInt32 *aPositionInGroup);
-  NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aChild);
-  NS_IMETHOD GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aChild);
   NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
                                nsIAccessibleRelation **aRelation);
   NS_IMETHOD GetRelationsCount(PRUint32 *aRelationsCount);
   NS_IMETHOD GetRelation(PRUint32 aIndex, nsIAccessibleRelation **aRelation);
   NS_IMETHOD GetRelations(nsIArray **aRelations);
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
   NS_IMETHOD SetSelected(PRBool aIsSelected);
@@ -123,16 +121,18 @@ public:
   virtual PRBool Init();
   virtual void Shutdown();
   virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   virtual void InvalidateChildren();
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
   virtual nsAccessible* GetSiblingAtOffset(PRInt32 aOffset,
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -62,24 +62,22 @@ nsLeafAccessible::
 {
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, nsAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLeafAccessible: nsAccessible public
 
-nsresult
+nsAccessible*
 nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                  PRBool aDeepestChild,
-                                  nsIAccessible **aChild)
+                                  EWhichChildAtPoint aWhichChild)
 {
   // Don't walk into leaf accessibles.
-  NS_ADDREF(*aChild = this);
-  return NS_OK;
+  return this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLeafAccessible: nsAccessible private
 
 void
 nsLeafAccessible::CacheChildren()
 {
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -58,19 +58,18 @@ public:
   using nsAccessible::GetChildAtPoint;
 
   nsLeafAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsAccessible
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
 };
 
 /**
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -645,16 +645,21 @@ nsDocAccessible::Shutdown()
 
   if (mNotificationController) {
     mNotificationController->Shutdown();
     mNotificationController = nsnull;
   }
 
   RemoveEventListeners();
 
+  // Mark the document as shutdown before AT is notified about the document
+  // removal from its container (valid for root documents on ATK).
+  nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
+  mDocument = nsnull;
+
   if (mParent) {
     nsDocAccessible* parentDocument = mParent->GetDocAccessible();
     if (parentDocument)
       parentDocument->RemoveChildDocument(this);
 
     mParent->RemoveChild(this);
   }
 
@@ -667,19 +672,16 @@ nsDocAccessible::Shutdown()
   mChildDocuments.Clear();
 
   mWeakShell = nsnull;  // Avoid reentrancy
 
   mDependentIDsHash.Clear();
   mNodeToAccessibleMap.Clear();
   ClearCache(mAccessibleCache);
 
-  nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
-  mDocument = nsnull;
-
   nsHyperTextAccessibleWrap::Shutdown();
 
   GetAccService()->NotifyOfDocumentShutdown(kungFuDeathGripDoc);
 }
 
 nsIFrame*
 nsDocAccessible::GetFrame() const
 {
@@ -1224,29 +1226,27 @@ nsDocAccessible::ARIAAttributeChanged(ns
 
 void nsDocAccessible::ContentAppended(nsIDocument *aDocument,
                                       nsIContent* aContainer,
                                       nsIContent* aFirstNewContent,
                                       PRInt32 /* unused */)
 {
 }
 
-void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument,
-                                           nsIContent* aContent1,
-                                           nsIContent* aContent2,
-                                           nsEventStates aStateMask)
+void nsDocAccessible::ContentStateChanged(nsIDocument* aDocument,
+                                          nsIContent* aContent,
+                                          nsEventStates aStateMask)
 {
   if (aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
-    nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent1);
-    nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent2);
+    nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent);
   }
 
   if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {
     nsRefPtr<AccEvent> event =
-      new AccStateChangeEvent(aContent1, nsIAccessibleStates::STATE_INVALID,
+      new AccStateChangeEvent(aContent, nsIAccessibleStates::STATE_INVALID,
                               PR_FALSE, PR_TRUE);
     FireDelayedAccessibleEvent(event);
    }
 }
 
 void nsDocAccessible::DocumentStatesChanged(nsIDocument* aDocument,
                                             nsEventStates aStateMask)
 {
@@ -1467,17 +1467,20 @@ nsDocAccessible::NotifyOfCachingEnd(nsAc
     // Invalidate children of container accessible for each element in
     // invalidation list.
     for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) {
       nsIContent* content = mInvalidationList[idx];
       if (!HasAccessible(content)) {
         // Make sure we keep children updated. While we're inside of caching
         // loop then we must exist it with cached children.
         nsAccessible* container = GetContainerAccessible(content);
-        container->UpdateChildren();
+        NS_ASSERTION(container,
+                     "Got a referenced element that is not in document!");
+        if (container)
+          container->UpdateChildren();
       }
     }
     mInvalidationList.Clear();
 
     mCacheRoot = nsnull;
     mIsPostCacheProcessing = PR_FALSE;
   }
 }
@@ -1945,18 +1948,19 @@ nsDocAccessible::UpdateTreeInternal(nsIC
 void
 nsDocAccessible::CacheChildrenInSubtree(nsAccessible* aRoot)
 {
   aRoot->EnsureChildren();
 
   PRUint32 count = aRoot->GetChildCount();
   for (PRUint32 idx = 0; idx < count; idx++)  {
     nsAccessible* child = aRoot->GetChildAt(idx);
+    NS_ASSERTION(child, "Illicit tree change while tree is created!");
     // Don't cross document boundaries.
-    if (child->IsContent())
+    if (child && child->IsContent())
       CacheChildrenInSubtree(child);
   }
 }
 
 void
 nsDocAccessible::UncacheChildrenInSubtree(nsAccessible* aRoot)
 {
   if (aRoot->IsElement())
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -71,42 +71,35 @@ nsOuterDocAccessible::GetStateInternal(P
 {
   nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
   *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
   return NS_OK;
 }
 
-nsresult
+nsAccessible*
 nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                      PRBool aDeepestChild,
-                                      nsIAccessible **aChild)
+                                      EWhichChildAtPoint aWhichChild)
 {
   PRInt32 docX = 0, docY = 0, docWidth = 0, docHeight = 0;
   nsresult rv = GetBounds(&docX, &docY, &docWidth, &docHeight);
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_SUCCESS(rv, nsnull);
 
   if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight)
-    return NS_OK;
+    return nsnull;
 
   // Always return the inner doc as direct child accessible unless bounds
   // outside of it.
-  nsCOMPtr<nsIAccessible> childAcc;
-  rv = GetFirstChild(getter_AddRefs(childAcc));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsAccessible* child = GetChildAt(0);
+  NS_ENSURE_TRUE(child, nsnull);
 
-  if (!childAcc)
-    return NS_OK;
-
-  if (aDeepestChild)
-    return childAcc->GetDeepestChildAtPoint(aX, aY, aChild);
-
-  NS_ADDREF(*aChild = childAcc);
-  return NS_OK;
+  if (aWhichChild = eDeepestChild)
+    return child->GetChildAtPoint(aX, aY, eDeepestChild);
+  return child;
 }
 
 nsresult
 nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsAutoString tag;
   aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
   if (!tag.IsEmpty()) {
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/base/nsOuterDocAccessible.h
@@ -65,19 +65,18 @@ public:
 
   // nsAccessNode
   virtual void Shutdown();
 
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   virtual void InvalidateChildren();
   virtual PRBool AppendChild(nsAccessible *aAccessible);
   virtual PRBool RemoveChild(nsAccessible *aAccessible);
 
 protected:
   // nsAccessible
   virtual void CacheChildren();
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp
@@ -241,24 +241,22 @@ nsHTMLAreaAccessible::GetStateInternal(P
       mRoleMapEntry->role != nsIAccessibleRole::ROLE_NOTHING &&
       mRoleMapEntry->role != nsIAccessibleRole::ROLE_LINK) {
     return nsAccessible::GetStateInternal(aState,aExtraState);
   }
 
   return nsHTMLLinkAccessible::GetStateInternal(aState, aExtraState);
 }
 
-nsresult
+nsAccessible*
 nsHTMLAreaAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                      PRBool aDeepestChild,
-                                      nsIAccessible **aChild)
+                                      EWhichChildAtPoint aWhichChild)
 {
   // Don't walk into area accessibles.
-  NS_ADDREF(*aChild = this);
-  return NS_OK;
+  return this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLImageMapAccessible: HyperLinkAccessible
 
 PRUint32
 nsHTMLAreaAccessible::StartOffset()
 {
--- a/accessible/src/html/nsHTMLImageMapAccessible.h
+++ b/accessible/src/html/nsHTMLImageMapAccessible.h
@@ -89,19 +89,18 @@ public:
   // nsIAccessible
   NS_IMETHOD GetDescription(nsAString& aDescription);
 
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   // HyperLinkAccessible
   virtual PRUint32 StartOffset();
   virtual PRUint32 EndOffset();
 
 protected:
 
   // nsAccessible
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -249,37 +249,36 @@ nsHTMLOutputAccessible::GetAttributesInt
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLIAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLLIAccessible::
   nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
-  nsHyperTextAccessibleWrap(aContent, aShell)
+  nsHyperTextAccessibleWrap(aContent, aShell), mBullet(nsnull)
 {
+  mFlags |= eHTMLListItemAccessible;
+
   nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
-  if (blockFrame && !blockFrame->BulletIsEmptyExternal()) {
-    mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell);
-    GetDocAccessible()->BindToDocument(mBulletAccessible, nsnull);
+  if (blockFrame && blockFrame->HasBullet()) {
+    mBullet = new nsHTMLListBulletAccessible(mContent, mWeakShell);
+    if (!GetDocAccessible()->BindToDocument(mBullet, nsnull))
+      mBullet = nsnull;
   }
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible)
 
 void
 nsHTMLLIAccessible::Shutdown()
 {
-  if (mBulletAccessible) {
-    // Ensure that pointer to this is nulled out.
-    mBulletAccessible->Shutdown();
-  }
+  mBullet = nsnull;
 
   nsHyperTextAccessibleWrap::Shutdown();
-  mBulletAccessible = nsnull;
 }
 
 PRUint32
 nsHTMLLIAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_LISTITEM;
 }
 
@@ -292,63 +291,81 @@ nsHTMLLIAccessible::GetStateInternal(PRU
 
   *aState |= nsIAccessibleStates::STATE_READONLY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
 {
   nsresult rv = nsAccessibleWrap::GetBounds(x, y, width, height);
-  if (NS_FAILED(rv) || !mBulletAccessible) {
+  if (NS_FAILED(rv) || !mBullet)
     return rv;
-  }
 
   PRInt32 bulletX, bulletY, bulletWidth, bulletHeight;
-  rv = mBulletAccessible->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
+  rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *x = bulletX; // Move x coordinate of list item over to cover bullet as well
   *width += bulletWidth;
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// nsHTMLLIAccessible: public
+
+void
+nsHTMLLIAccessible::UpdateBullet(bool aHasBullet)
+{
+  if (aHasBullet == !!mBullet) {
+    NS_NOTREACHED("Bullet and accessible are in sync already!");
+    return;
+  }
+
+  nsDocAccessible* document = GetDocAccessible();
+  if (aHasBullet) {
+    mBullet = new nsHTMLListBulletAccessible(mContent, mWeakShell);
+    if (document->BindToDocument(mBullet, nsnull)) {
+      InsertChildAt(0, mBullet);
+    }
+  } else {
+    RemoveChild(mBullet);
+    document->UnbindFromDocument(mBullet);
+    mBullet = nsnull;
+  }
+
+  // XXXtodo: fire show/hide and reorder events. That's hard to make it
+  // right now because coalescence happens by DOM node.
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLIAccessible: nsAccessible protected
 
 void
 nsHTMLLIAccessible::CacheChildren()
 {
-  if (mBulletAccessible)
-    AppendChild(mBulletAccessible);
+  if (mBullet)
+    AppendChild(mBullet);
 
   // Cache children from subtree.
   nsAccessibleWrap::CacheChildren();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListBulletAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLListBulletAccessible::
   nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
     nsLeafAccessible(aContent, aShell)
 {
-  mBulletText += ' '; // Otherwise bullets are jammed up against list text
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListBulletAccessible: nsAccessNode
 
-void
-nsHTMLListBulletAccessible::Shutdown()
-{
-  mBulletText.Truncate();
-  nsLeafAccessible::Shutdown();
-}
-
 bool
 nsHTMLListBulletAccessible::IsPrimaryForNode() const
 {
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListBulletAccessible: nsAccessible
@@ -358,16 +375,17 @@ nsHTMLListBulletAccessible::GetName(nsAS
 {
   aName.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   // Native anonymous content, ARIA can't be used. Get list bullet text.
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
+  NS_ASSERTION(blockFrame, "No frame for list item!");
   if (blockFrame) {
     blockFrame->GetBulletText(aName);
 
     // Append space otherwise bullets are jammed up against list text.
     aName.Append(' ');
   }
 
   return NS_OK;
@@ -389,27 +407,23 @@ nsHTMLListBulletAccessible::GetStateInte
   *aState |= nsIAccessibleStates::STATE_READONLY;
   return NS_OK;
 }
 
 void
 nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                          PRUint32 aLength)
 {
+  nsAutoString bulletText;
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
-  if (blockFrame) {
-    nsAutoString bulletText;
+  NS_ASSERTION(blockFrame, "No frame for list item!");
+  if (blockFrame)
     blockFrame->GetBulletText(bulletText);
 
-    PRUint32 maxLength = bulletText.Length() - aStartOffset;
-    if (aLength > maxLength)
-      aLength = maxLength;
-
-    aText += Substring(bulletText, aStartOffset, aLength);
-  }
+  aText.Append(Substring(bulletText, aStartOffset, aLength));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLListAccessible::
   nsHTMLListAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -131,33 +131,23 @@ class nsHTMLListBulletAccessible : publi
 {
 public:
   nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell);
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
 
   // nsAccessNode
-  virtual void Shutdown();
   virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
                             PRUint32 aLength = PR_UINT32_MAX);
-
-protected:
-  // XXX: Ideally we'd get the bullet text directly from the bullet frame via
-  // nsBulletFrame::GetListItemText(), but we'd need an interface for getting
-  // text from contentless anonymous frames. Perhaps something like
-  // nsIAnonymousFrame::GetText() ? However, in practice storing the bullet text
-  // here should not be a problem if we invalidate the right parts of
-  // the accessibility cache when mutation events occur.
-  nsString mBulletText;
 };
 
 /**
  * Used for HTML list (like HTML ul).
  */
 class nsHTMLListAccessible : public nsHyperTextAccessibleWrap
 {
 public:
@@ -177,27 +167,37 @@ public:
 class nsHTMLLIAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
+  // nsAccessNode
+  virtual void Shutdown();
+
   // nsIAccessible
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
 
-  // nsAccessNode
-  virtual void Shutdown();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
+  // nsHTMLLIAccessible
+  void UpdateBullet(bool aHasBullet);
+
 protected:
   // nsAccessible
   virtual void CacheChildren();
 
 private:
-  nsRefPtr<nsHTMLListBulletAccessible> mBulletAccessible;
+  nsRefPtr<nsHTMLListBulletAccessible> mBullet;
 };
 
-#endif  
+inline nsHTMLLIAccessible*
+nsAccessible::AsHTMLListItem()
+{
+  return mFlags & eHTMLListItemAccessible ?
+    static_cast<nsHTMLLIAccessible*>(this) : nsnull;
+}
+
+#endif
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -190,21 +190,18 @@ nsHyperTextAccessible::GetStateInternal(
     if (0 == (flags & nsIPlaintextEditor::eEditorReadonlyMask)) {
       *aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE;
     }
   } else if (mContent->Tag() == nsAccessibilityAtoms::article) {
     // We want <article> to behave like a document in terms of readonly state.
     *aState |= nsIAccessibleStates::STATE_READONLY;
   }
 
-  PRInt32 childCount;
-  GetChildCount(&childCount);
-  if (childCount > 0) {
+  if (GetChildCount() > 0)
     *aExtraState |= nsIAccessibleStates::EXT_STATE_SELECTABLE_TEXT;
-  }
 
   return NS_OK;
 }
 
 // Substring must be entirely within the same text node
 nsIntRect nsHyperTextAccessible::GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset,
                                                     PRUint32 aEndRenderedOffset)
 {
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -303,17 +303,17 @@ STDMETHODIMP nsAccessNodeWrap::get_attri
 
 STDMETHODIMP nsAccessNodeWrap::get_attributesForNames( 
     /* [in] */ unsigned short aNumAttribs,
     /* [length_is][size_is][in] */ BSTR __RPC_FAR *aAttribNames,
     /* [length_is][size_is][in] */ short __RPC_FAR *aNameSpaceID,
     /* [length_is][size_is][retval] */ BSTR __RPC_FAR *aAttribValues)
 {
 __try {
-  if (IsDefunct() || IsDocument())
+  if (IsDefunct() || !IsElement())
     return E_FAIL;
 
   nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mContent));
   nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
     do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
 
   PRInt32 index;
 
@@ -611,35 +611,27 @@ void nsAccessNodeWrap::InitAccessibility
     if (!gmNotifyWinEvent)
       gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
     if (!gmGetGUIThreadInfo)
       gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
   }
 
   DoATSpecificProcessing();
 
-  // Register window class that'll be used for document accessibles associated
-  // with tabs.
-  if (nsWinUtils::IsWindowEmulationEnabled()) {
-    nsWinUtils::RegisterNativeWindow(kClassNameTabContent);
-    sHWNDCache.Init(4);
-  }
+  nsWinUtils::MaybeStartWindowEmulation();
 
   nsAccessNode::InitXPAccessibility();
 }
 
 void nsAccessNodeWrap::ShutdownAccessibility()
 {
   NS_IF_RELEASE(gTextEvent);
   ::DestroyCaret();
 
-  // Unregister window call that's used for document accessibles associated
-  // with tabs.
-  if (nsWinUtils::IsWindowEmulationEnabled())
-    ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
+  nsWinUtils::ShutdownWindowEmulation();
 
   nsAccessNode::ShutdownXPAccessibility();
 }
 
 int nsAccessNodeWrap::FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo)
 {
   if (aCode == EXCEPTION_ACCESS_VIOLATION) {
 #ifdef MOZ_CRASHREPORTER
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -198,17 +198,17 @@ STDMETHODIMP nsAccessibleWrap::get_accPa
   if (IsDefunct())
     return E_FAIL;
 
   nsRefPtr<nsDocAccessible> doc(do_QueryObject(this));
   if (doc) {
     // Return window system accessible object for root document and tab document
     // accessibles.
     if (!doc->ParentDocument() ||
-        nsWinUtils::IsWindowEmulationEnabled() &&
+        nsWinUtils::IsWindowEmulationStarted() &&
         nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
       HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
       if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
                                                        IID_IAccessible,
                                                        (void**)ppdispParent))) {
         return S_OK;
       }
     }
@@ -231,19 +231,17 @@ STDMETHODIMP nsAccessibleWrap::get_accPa
 
 STDMETHODIMP nsAccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)
 {
 __try {
   *pcountChildren = 0;
   if (nsAccUtils::MustPrune(this))
     return NS_OK;
 
-  PRInt32 numChildren;
-  GetChildCount(&numChildren);
-  *pcountChildren = numChildren;
+  *pcountChildren = GetChildCount();
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
 
   return S_OK;
 }
 
 STDMETHODIMP nsAccessibleWrap::get_accChild(
       /* [in] */ VARIANT varChild,
       /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
@@ -1009,19 +1007,17 @@ STDMETHODIMP
 nsAccessibleWrap::Skip(ULONG aNumElements)
 {
 __try {
   if (mEnumVARIANTPosition == kIEnumVariantDisconnected)
     return CO_E_OBJNOTCONNECTED;
 
   mEnumVARIANTPosition += aNumElements;
 
-  PRInt32 numChildren;
-  GetChildCount(&numChildren);
-
+  PRInt32 numChildren = GetChildCount();
   if (mEnumVARIANTPosition > numChildren)
   {
     mEnumVARIANTPosition = numChildren;
     return S_FALSE;
   }
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return NOERROR;
 }
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -250,20 +250,21 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 void
 nsDocAccessibleWrap::Shutdown()
 {
-  if (nsWinUtils::IsWindowEmulationEnabled()) {
+  // Do window emulation specific shutdown if emulation was started.
+  if (nsWinUtils::IsWindowEmulationStarted()) {
     // Destroy window created for root document.
     if (nsWinUtils::IsTabDocument(mDocument)) {
-      nsAccessibleWrap::sHWNDCache.Remove(mHWND);
+      sHWNDCache.Remove(mHWND);
       ::DestroyWindow(static_cast<HWND>(mHWND));
     }
 
     mHWND = nsnull;
   }
 
   nsDocAccessible::Shutdown();
 }
@@ -280,40 +281,40 @@ nsDocAccessibleWrap::GetNativeWindow() c
 ////////////////////////////////////////////////////////////////////////////////
 // nsDocAccessible protected
 
 void
 nsDocAccessibleWrap::NotifyOfInitialUpdate()
 {
   nsDocAccessible::NotifyOfInitialUpdate();
 
-  if (nsWinUtils::IsWindowEmulationEnabled()) {
+  if (nsWinUtils::IsWindowEmulationStarted()) {
     // Create window for tab document.
     if (nsWinUtils::IsTabDocument(mDocument)) {
       nsRootAccessible* rootDocument = RootAccessible();
 
       PRBool isActive = PR_TRUE;
       PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0;
-      if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle)) {
+      if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle)) {
         GetBounds(&x, &y, &width, &height);
         PRInt32 rootX = 0, rootY = 0, rootWidth = 0, rootHeight = 0;
         rootDocument->GetBounds(&rootX, &rootY, &rootWidth, &rootHeight);
         x = rootX - x;
         y -= rootY;
 
         nsCOMPtr<nsISupports> container = mDocument->GetContainer();
         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
         docShell->GetIsActive(&isActive);
       }
 
       HWND parentWnd = static_cast<HWND>(rootDocument->GetNativeWindow());
       mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd,
                                              x, y, width, height, isActive);
 
-      nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
+      sHWNDCache.Put(mHWND, this);
 
     } else {
       nsDocAccessible* parentDocument = ParentDocument();
       if (parentDocument)
         mHWND = parentDocument->GetNativeWindow();
     }
   }
 }
--- a/accessible/src/msaa/nsRootAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsRootAccessibleWrap.cpp
@@ -58,17 +58,17 @@ nsRootAccessibleWrap::~nsRootAccessibleW
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsRootAccessible
 
 void
 nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
 {
-  if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle) &&
+  if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle) &&
       nsWinUtils::IsTabDocument(aDocument->GetDocumentNode())) {
     PRUint32 count = mChildDocuments.Length();
     for (PRUint32 idx = 0; idx < count; idx++) {
       nsDocAccessible* childDoc = mChildDocuments[idx];
       HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
       if (childDoc != aDocument)
         nsWinUtils::HideNativeWindow(childDocHWND);
       else
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -94,16 +94,44 @@ nsWinUtils::ConvertToIA2Array(nsIArray *
     ::CoTaskMemFree(*aIA2Array);
     return GetHRESULT(rv);
   }
 
   *aIA2ArrayLen = length;
   return S_OK;
 }
 
+bool
+nsWinUtils::MaybeStartWindowEmulation()
+{
+  // Register window class that'll be used for document accessibles associated
+  // with tabs.
+  if (IsWindowEmulationFor(0)) {
+    RegisterNativeWindow(kClassNameTabContent);
+    nsAccessNodeWrap::sHWNDCache.Init(4);
+    return true;
+  }
+  return false;
+}
+
+void
+nsWinUtils::ShutdownWindowEmulation()
+{
+  // Unregister window call that's used for document accessibles associated
+  // with tabs.
+  if (IsWindowEmulationFor(0))
+    ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
+}
+
+bool
+nsWinUtils::IsWindowEmulationStarted()
+{
+  return nsAccessNodeWrap::sHWNDCache.IsInitialized();
+}
+
 void
 nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
 {
   WNDCLASSW wc;
   wc.style = CS_GLOBALCLASS;
   wc.lpfnWndProc = nsAccessNodeWrap::WindowProc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
@@ -141,17 +169,17 @@ void
 nsWinUtils::HideNativeWindow(HWND aWnd)
 {
   ::SetWindowPos(aWnd, NULL, 0, 0, 0, 0,
                  SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
                  SWP_NOZORDER | SWP_NOACTIVATE);
 }
 
 bool
-nsWinUtils::IsWindowEmulationEnabled(LPCWSTR kModuleHandle)
+nsWinUtils::IsWindowEmulationFor(LPCWSTR kModuleHandle)
 {
   return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) :
     ::GetModuleHandleW(kJAWSModuleHandle) ||
     ::GetModuleHandleW(kWEModuleHandle)  ||
     ::GetModuleHandleW(kDolphinModuleHandle);
 }
 
 bool
--- a/accessible/src/msaa/nsWinUtils.h
+++ b/accessible/src/msaa/nsWinUtils.h
@@ -59,16 +59,31 @@ public:
   /**
    * Convert nsIArray array of accessible objects to an array of IUnknown*
    * objects used in IA2 methods.
    */
   static HRESULT ConvertToIA2Array(nsIArray *aCollection,
                                    IUnknown ***aAccessibles, long *aCount);
 
   /**
+   * Start window emulation if presence of specific AT is detected.
+   */
+  static bool MaybeStartWindowEmulation();
+
+  /**
+   * Free resources used for window emulation.
+   */
+  static void ShutdownWindowEmulation();
+
+  /**
+   * Return true if window emulation is started.
+   */
+  static bool IsWindowEmulationStarted();
+
+  /**
    * Helper to register window class.
    */
   static void RegisterNativeWindow(LPCWSTR aWindowClass);
 
   /**
    * Helper to create a window.
    */
   static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
@@ -83,17 +98,17 @@ public:
   /**
    * Helper to hide window.
    */
   static void HideNativeWindow(HWND aWnd);
 
   /**
    * Return true if window emulation is enabled.
    */
-  static bool IsWindowEmulationEnabled(LPCWSTR kModuleHandle = 0);
+  static bool IsWindowEmulationFor(LPCWSTR kModuleHandle);
 
   /**
    * Return true if the given document node is for tab document accessible.
    */
   static bool IsTabDocument(nsIDocument* aDocumentNode);
 };
 
 #endif
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -223,59 +223,57 @@ nsXULTreeAccessible::GetFocusedChild(nsI
   }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: nsAccessible implementation (DON'T put methods here)
 
-nsresult
+nsAccessible*
 nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                     PRBool aDeepestChild,
-                                     nsIAccessible **aChild)
+                                     EWhichChildAtPoint aWhichChild)
 {
   nsIFrame *frame = GetFrame();
   if (!frame)
-    return NS_ERROR_FAILURE;
+    return nsnull;
 
   nsPresContext *presContext = frame->PresContext();
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
 
   nsIFrame *rootFrame = presShell->GetRootFrame();
-  NS_ENSURE_STATE(rootFrame);
+  NS_ENSURE_TRUE(rootFrame, nsnull);
 
   nsIntRect rootRect = rootFrame->GetScreenRectExternal();
 
   PRInt32 clientX = presContext->DevPixelsToIntCSSPixels(aX - rootRect.x);
   PRInt32 clientY = presContext->DevPixelsToIntCSSPixels(aY - rootRect.y);
 
   PRInt32 row = -1;
   nsCOMPtr<nsITreeColumn> column;
   nsCAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // If we failed to find tree cell for the given point then it might be
   // tree columns.
   if (row == -1 || !column)
-    return nsAccessibleWrap::GetChildAtPoint(aX, aY, aDeepestChild, aChild);
+    return nsAccessibleWrap::GetChildAtPoint(aX, aY, aWhichChild);
 
   nsAccessible *child = GetTreeItemAccessible(row);
-  if (aDeepestChild && child) {
+  if (aWhichChild == eDeepestChild && child) {
     // Look for accessible cell for the found item accessible.
     nsRefPtr<nsXULTreeItemAccessibleBase> treeitem = do_QueryObject(child);
 
     nsAccessible *cell = treeitem->GetCellAccessible(column);
     if (cell)
       child = cell;
   }
 
-  NS_IF_ADDREF(*aChild = child);
-  return NS_OK;
+  return child;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: SelectAccessible
 
 bool
 nsXULTreeAccessible::IsSelect()
 {
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -81,19 +81,18 @@ public:
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual void Shutdown();
 
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   virtual nsAccessible* GetChildAt(PRUint32 aIndex);
   virtual PRInt32 GetChildCount();
 
   // SelectAccessible
   virtual bool IsSelect();
   virtual already_AddRefed<nsIArray> SelectedItems();
   virtual PRUint32 SelectedItemCount();
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -659,48 +659,46 @@ nsXULTreeGridRowAccessible::Shutdown()
 // nsXULTreeGridRowAccessible: nsAccessible implementation
 
 PRUint32
 nsXULTreeGridRowAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_ROW;
 }
 
-nsresult
+nsAccessible*
 nsXULTreeGridRowAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                            PRBool aDeepestChild,
-                                            nsIAccessible **aChild)
+                                            EWhichChildAtPoint aWhichChild)
 {
   nsIFrame *frame = GetFrame();
   if (!frame)
-    return NS_ERROR_FAILURE;
+    return nsnull;
 
   nsPresContext *presContext = frame->PresContext();
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
 
   nsIFrame *rootFrame = presShell->GetRootFrame();
-  NS_ENSURE_STATE(rootFrame);
+  NS_ENSURE_TRUE(rootFrame, nsnull);
 
   nsIntRect rootRect = rootFrame->GetScreenRectExternal();
 
   PRInt32 clientX = presContext->DevPixelsToIntCSSPixels(aX - rootRect.x);
   PRInt32 clientY = presContext->DevPixelsToIntCSSPixels(aY - rootRect.y);
 
   PRInt32 row = -1;
   nsCOMPtr<nsITreeColumn> column;
   nsCAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // Return if we failed to find tree cell in the row for the given point.
   if (row != mRow || !column)
-    return NS_OK;
+    return nsnull;
 
-  NS_IF_ADDREF(*aChild = GetCellAccessible(column));
-  return NS_OK;
+  return GetCellAccessible(column);
 }
 
 nsAccessible*
 nsXULTreeGridRowAccessible::GetChildAt(PRUint32 aIndex)
 {
   if (IsDefunct())
     return nsnull;
 
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -88,19 +88,18 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridRowAccessible,
                                            nsAccessible)
 
   // nsAccessNode
   virtual void Shutdown();
 
   // nsAccessible
   virtual PRUint32 NativeRole();
-  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   PRBool aDeepestChild,
-                                   nsIAccessible **aChild);
+  virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                        EWhichChildAtPoint aWhichChild);
 
   virtual nsAccessible* GetChildAt(PRUint32 aIndex);
   virtual PRInt32 GetChildCount();
 
   // nsXULTreeItemAccessibleBase
   virtual nsAccessible* GetCellAccessible(nsITreeColumn *aColumn);
   virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
 
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -59,16 +59,20 @@ const WIN = (navigator.platform.indexOf(
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible general
 
 const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
 
 const kEmbedChar = String.fromCharCode(0xfffc);
 
+const kDiscBulletText = String.fromCharCode(0x2022) + " ";
+const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
+const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
+
 /**
  * nsIAccessibleRetrieval, initialized when test is loaded.
  */
 var gAccRetrieval = null;
 
 /**
  * Invokes the given function when document is loaded and focused. Preferable
  * to mochitests 'addLoadEvent' function -- additionally ensures state of the
--- a/accessible/tests/mochitest/name/Makefile.in
+++ b/accessible/tests/mochitest/name/Makefile.in
@@ -49,15 +49,16 @@ include $(topsrcdir)/config/rules.mk
 		general.css \
 		general.xbl \
 		markup.js \
 		nsRootAcc_wnd.xul \
 		test_button.html \
 		test_general.html \
 		test_general.xul \
 		test_link.html \
+		test_list.html \
 		test_markup.html \
 		test_nsRootAcc.xul \
 		markuprules.xml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_list.html
@@ -0,0 +1,91 @@
+<html>
+
+<head>
+  <title>nsIAccessible::name calculation for HTML li</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../name.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+    /**
+     * Alter list item numbering and change list style type.
+     */
+    function bulletUpdate()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, getNode("list"))
+      ];
+
+      this.invoke = function bulletUpdate_invoke()
+      {
+        testName("li_end", "1. list end");
+
+        var li = document.createElement("li");
+        li.setAttribute("id", "li_start");
+        li.textContent = "list start";
+        getNode("list").insertBefore(li, getNode("li_end"));
+      }
+
+      this.finalCheck = function bulletUpdate_finalCheck()
+      {
+        testName("li_start", "1. list start");
+        testName("li_end", "2. list end");
+
+        // change list style type
+        var list = getNode("list");
+        list.setAttribute("style", "list-style-type: disc;");
+        getComputedStyle(list, "").color; // make style processing sync
+
+        testName("li_start", kDiscBulletText + "list start");
+        testName("li_end", kDiscBulletText + "list end");
+      }
+
+      this.getID = function bulletUpdate_getID()
+      {
+        return "Update bullet of list items";
+      }
+    }
+
+    var gQueue = null;
+    function doTest()
+    {
+      gQueue = new eventQueue();
+      gQueue.push(new bulletUpdate());
+      gQueue.invoke(); // SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=634200"
+     title="crash [@ nsIFrame::GetStyleVisibility() ]">
+    Mozilla Bug 634200
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <ol id="list">
+    <li id="li_end">list end</li>
+  </ol>
+
+</body>
+</html>
--- a/accessible/tests/mochitest/text/test_hypertext.html
+++ b/accessible/tests/mochitest/text/test_hypertext.html
@@ -1,15 +1,21 @@
 <!DOCTYPE html>
 <html>
 <head>
   <title>nsIAccessibleText getText related function tests for rich text</title>
   <link rel="stylesheet" type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
+  <style>
+    h6.gencontent:before {
+      content: "aga"
+    }
+  </style>
+
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
@@ -35,16 +41,26 @@
       ////////////////////////////////////////////////////////////////////////
       // getText
 
       testText(IDs, 0, 1, "h");
       testText(IDs, 5, 7, " " + kEmbedChar);
       testText(IDs, 10, 13, "e " + kEmbedChar);
       testText(IDs, 0, 13, "hello " + kEmbedChar + " see " + kEmbedChar);
 
+      ////////////////////////////////////////////////////////////////////////
+      // getTextAtOffset line boundary
+
+      testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
+                       "hypertext3", kOk, kOk, kOk);
+
+      // XXX: see bug 638684.
+      testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
+                       "hypertext4", kTodo, kOk, kTodo);
+
       //////////////////////////////////////////////////////////////////////////
       // list
       //////////////////////////////////////////////////////////////////////////
 
       IDs = [ "list" ];
       testCharacterCount(IDs, 1);
       testText(IDs, 0, 1, kEmbedChar);
 
@@ -58,20 +74,39 @@
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
      title="Fix getText"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=630001">Mozilla Bug 630001, part3</a>
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=630001">
+    Bug 630001, part3
+  </a>
+  <a target="_blank"
+     title="getTextAtOffset line boundary may return more than one line"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=638326">
+    Bug 638326
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="hypertext">hello <a>friend</a> see <img></div>
   <div id="hypertext2">hello <a>friend</a> see <input></div>
   <ol id="list"><li id="listitem">foo</li></ol>
 
+  <div id="hypertext3">line
+<!-- haha -->
+<!-- hahaha -->
+<h6>heading</h6>
+  </div>
+
+  <div id="hypertext4">line
+<!-- haha -->
+<!-- hahaha -->
+<h6 role="presentation" class="gencontent">heading</h6>
+  </div>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/tree/test_list.html
+++ b/accessible/tests/mochitest/tree/test_list.html
@@ -35,51 +35,47 @@
       if (aSubtree)
         obj.children.push(aSubtree);
 
       return obj;
     }
 
     function doTest()
     {
-      const discBulletText = String.fromCharCode(0x2022) + " ";
-      const circleBulletText = String.fromCharCode(0x25e6) + " ";
-      const squareBulletText = String.fromCharCode(0x25aa) + " ";
-
       // list1
       var discAccTree = {
         role: ROLE_LIST,
         children: [
-          new listItemTree(discBulletText, "Oranges"),
-          new listItemTree(discBulletText, "Apples"),
-          new listItemTree(discBulletText, "Bananas")
+          new listItemTree(kDiscBulletText, "Oranges"),
+          new listItemTree(kDiscBulletText, "Apples"),
+          new listItemTree(kDiscBulletText, "Bananas")
         ]
       };
 
       testAccessibleTree("list1", discAccTree);
 
       // list2
       var circleAccTree = {
         role: ROLE_LIST,
         children: [
-          new listItemTree(circleBulletText, "Oranges"),
-          new listItemTree(circleBulletText, "Apples"),
-          new listItemTree(circleBulletText, "Bananas")
+          new listItemTree(kCircleBulletText, "Oranges"),
+          new listItemTree(kCircleBulletText, "Apples"),
+          new listItemTree(kCircleBulletText, "Bananas")
         ]
       };
 
       testAccessibleTree("list2", circleAccTree);
 
       // list3
       var squareAccTree = {
         role: ROLE_LIST,
         children: [
-          new listItemTree(squareBulletText, "Oranges"),
-          new listItemTree(squareBulletText, "Apples"),
-          new listItemTree(squareBulletText, "Bananas")
+          new listItemTree(kSquareBulletText, "Oranges"),
+          new listItemTree(kSquareBulletText, "Apples"),
+          new listItemTree(kSquareBulletText, "Bananas")
         ]
       };
 
       testAccessibleTree("list3", squareAccTree);
 
       // list4
       var nestedAccTree = {
         role: ROLE_LIST,
@@ -87,16 +83,53 @@
           new listItemTree("1. ", "Oranges"),
           new listItemTree("2. ", "Apples"),
           new listItemTree("3. ", "Bananas", circleAccTree)
         ]
       };
 
       testAccessibleTree("list4", nestedAccTree);
 
+      // dl list
+      var tree =
+        { LIST: [ // dl
+          { LISTITEM: [ // dt
+            { TEXT_LEAF: [] },
+          ] },
+          { PARAGRAPH: [ // dd
+            { TEXT_LEAF: [] }
+          ] },
+          { LISTITEM: [ // dt
+            { TEXT_LEAF: [] }
+          ] },
+          { PARAGRAPH: [ // dd
+            { TEXT_LEAF: [] }
+          ] }
+        ] };
+
+      testAccessibleTree("list5", tree);
+
+      // dl list inside ordered list
+      tree =
+        { LIST: [ // ol
+          { LISTITEM: [ // li
+            { STATICTEXT: [ ] },
+            { LIST: [ // dl
+              { LISTITEM: [ // dt
+                { TEXT_LEAF: [] }
+              ] },
+              { PARAGRAPH: [ // dd
+                { TEXT_LEAF: [] }
+              ] }
+            ] }
+          ] }
+        ] };
+
+      testAccessibleTree("list6", tree);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -106,16 +139,21 @@
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
     Mozilla Bug 342045
   </a>
   <a target="_blank"
      title="Bullets of nested not ordered lists have one and the same character."
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=604587">
     Mozilla Bug 604587
   </a>
+  <a target="_blank"
+     title="Fix list bullets for DL list (crash [@ nsBulletFrame::GetListItemText])"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=629114">
+    Mozilla Bug 629114
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <ul id="list1">
     <li id="l1_li1">Oranges</li>
     <li id="l1_li2">Apples</li>
@@ -139,10 +177,23 @@
     <li id="li5">Apples</li>
     <li id="li6">Bananas<ul>
         <li id="n_li4">Oranges</li>
         <li id="n_li5">Apples</li>
         <li id="n_li6">Bananas</li>
       </ul>
     </li>
   </ol>
+
+  <dl id="list5">
+    <dt>item1</dt><dd>description</dd>
+    <dt>item2</td><dd>description</dd>
+  </dl>
+
+  <ol id="list6">
+    <li>
+      <dl id="dl">
+        <dt>item1</dt><dd>description</dd>
+      </dl>
+    </li>
+  </ol>
 </body>
 </html>
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -43,16 +43,17 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/treeupdate
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_ariadialog.html \
 		test_doc.html \
+		test_gencontent.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_menu.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_gencontent.html
@@ -0,0 +1,160 @@
+<html>
+
+<head>
+  <title>Elements with CSS generated content</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <style>
+    .gentext:before {
+      content: "START"
+    }
+    .gentext:after {
+      content: "END"
+    }
+  </style>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Insert new node with CSS generated content style applied to container.
+     */
+    function insertNodeHavingGenContent(aContainerID)
+    {
+      this.containerNode = getNode(aContainerID);
+      this.container = getAccessible(this.containerNode);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getFirstChild, this.container),
+        new invokerChecker(EVENT_REORDER, this.container)
+      ];
+
+      this.invoke = function insertNodeHavingGenContent_invoke()
+      {
+        var node = document.createElement("div");
+        node.textContent = "text";
+        node.setAttribute("class", "gentext");
+        this.containerNode.appendChild(node);
+      }
+
+      this.finalCheck = function insertNodeHavingGenContent_finalCheck()
+      {
+        var accTree =
+          { SECTION: [ // container
+            { SECTION: [ // inserted node
+              { STATICTEXT: [] }, // :before
+              { TEXT_LEAF: [] }, // primary text
+              { STATICTEXT: [] } // :after
+            ] }
+          ] };
+        testAccessibleTree(this.container, accTree);
+      }
+
+      this.getID = function insertNodeHavingGenContent_getID()
+      {
+        return "insert node having generated content to " + prettyName(aContainerID);
+      }
+    }
+
+    /**
+     * Add CSS generated content to the given node contained by container node.
+     */
+    function addGenContent(aContainerID, aNodeID)
+    {
+      this.container = getAccessible(aContainerID);
+      this.node = getNode(aNodeID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, this.container.firstChild),
+        new invokerChecker(EVENT_SHOW, getFirstChild, this.container),
+        new invokerChecker(EVENT_REORDER, this.container)
+      ];
+
+      this.invoke = function addGenContent_invoke()
+      {
+        this.node.setAttribute("class", "gentext");
+      }
+
+      this.finalCheck = function insertNodeHavingGenContent_finalCheck()
+      {
+        var accTree =
+          { SECTION: [ // container
+            { SECTION: [ // inserted node
+              { STATICTEXT: [] }, // :before
+              { TEXT_LEAF: [] }, // primary text
+              { STATICTEXT: [] } // :after
+            ] }
+          ] };
+        testAccessibleTree(this.container, accTree);
+      }
+
+      this.getID = function addGenContent_getID()
+      {
+        return "add generated content to" + prettyName(aNodeID);
+      }
+    }
+
+    /**
+     * Target getters.
+     */
+    function getFirstChild(aAcc)
+    {
+      try { return aAcc.getChildAt(0); }
+      catch (e) { return null; }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do tests
+    ////////////////////////////////////////////////////////////////////////////
+
+    var gQueue = null;
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new insertNodeHavingGenContent("container1"));
+      gQueue.push(new addGenContent("container2", "container2_child"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=646350"
+     title="Add a test for dynamic chnages of CSS generated content">
+    Mozilla Bug 646350</a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <div id="container1"></div>
+  <div id="container2"><div id="container2_child">text</div></div>
+</body>
+</html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -43,18 +43,16 @@
 #  The first character after a period must be alphabetic.
 
 #ifdef XP_UNIX
 #ifndef XP_MACOSX
 #define UNIX_BUT_NOT_MAC
 #endif
 #endif
 
-pref("general.startup.browser", true);
-
 pref("browser.chromeURL","chrome://browser/content/");
 pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
 
 // Enables some extra Extension System Logging (can reduce performance)
 pref("extensions.logging.enabled", false);
 
 // Preferences for AMO integration
 pref("extensions.getAddons.cache.enabled", true);
@@ -531,21 +529,16 @@ pref("mousewheel.withaltkey.numlines",1)
 pref("mousewheel.withmetakey.action",0);
 pref("mousewheel.withmetakey.sysnumlines",true);
 pref("mousewheel.withmetakey.numlines",1);
 #endif
 pref("mousewheel.withcontrolkey.action",3);
 pref("mousewheel.withcontrolkey.sysnumlines",false);
 pref("mousewheel.withcontrolkey.numlines",1);
 
-pref("profile.allow_automigration", false);   // setting to false bypasses automigration in the profile code
-
-// Customizable toolbar stuff
-pref("custtoolbar.personal_toolbar_folder", "");
-
 // pref to control the alert notification 
 pref("alerts.slideIncrement", 1);
 pref("alerts.slideIncrementTime", 10);
 pref("alerts.totalOpenTime", 4000);
 
 pref("browser.xul.error_pages.enabled", true);
 pref("browser.xul.error_pages.expert_bad_cert", false);
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5063,33 +5063,29 @@ var TabsInTitlebar = {
     let docElement = document.documentElement;
     if (allowed == (docElement.getAttribute("tabsintitlebar") == "true"))
       return;
 
     function $(id) document.getElementById(id);
     let titlebar = $("titlebar");
 
     if (allowed) {
-      let availTop = screen.availTop;
-      function top(ele)    ele.boxObject.screenY - availTop;
-      function bottom(ele) top(ele) + rect(ele).height;
       function rect(ele)   ele.getBoundingClientRect();
 
       let tabsToolbar       = $("TabsToolbar");
+
       let appmenuButtonBox  = $("appmenu-button-container");
       let captionButtonsBox = $("titlebar-buttonbox");
-
       this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
       this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
 
-      let maxMargin = top(gNavToolbox);
-      let tabsBottom = maxMargin + rect(tabsToolbar).height;
-      let titlebarBottom = Math.max(bottom(appmenuButtonBox), bottom(captionButtonsBox));
-      let distance = tabsBottom - titlebarBottom;
-      titlebar.style.marginBottom = - Math.min(distance, maxMargin) + "px";
+      let tabsToolbarRect = rect(tabsToolbar);
+      let titlebarTop = rect($("titlebar-content")).top;
+      titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop,
+                                               tabsToolbarRect.height) + "px";
 
       docElement.setAttribute("tabsintitlebar", "true");
 
       if (!this._draghandle) {
         let tmp = {};
         Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
         this._draghandle = new tmp.WindowDraggingElement(tabsToolbar, window);
         this._draghandle.mouseDownCheck = function () {
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -79,16 +79,17 @@ function GroupItem(listOfEls, options) {
   this._isStacked = false;
   this.expanded = null;
   this.topChild = null;
   this.hidden = false;
   this.fadeAwayUndoButtonDelay = 15000;
   this.fadeAwayUndoButtonDuration = 300;
 
   this.keepProportional = false;
+  this._frozenItemSizeData = {};
 
   // Double click tracker
   this._lastClick = 0;
   this._lastClickPositions = null;
 
   // Variable: _activeTab
   // The <TabItem> for the groupItem's active tab.
   this._activeTab = null;
@@ -189,16 +190,17 @@ function GroupItem(listOfEls, options) {
   this.$title
     .blur(function() {
       self._titleFocused = false;
       self.$titleShield.show();
       if (self.getTitle())
         gTabView.firstUseExperienced = true;
     })
     .focus(function() {
+      self._unfreezeItemSize();
       if (!self._titleFocused) {
         (self.$title)[0].select();
         self._titleFocused = true;
       }
     })
     .mousedown(function(e) {
       e.stopPropagation();
     })
@@ -639,16 +641,19 @@ GroupItem.prototype = Utils.extend(new I
   //   options - An object with optional settings for this call.
   //
   // Options:
   //   immediately - (bool) if true, no animation will be used
   close: function GroupItem_close(options) {
     this.removeAll({dontClose: true});
     GroupItems.unregister(this);
 
+    // remove unfreeze event handlers, if item size is frozen
+    this._unfreezeItemSize({dontArrange: true});
+
     let self = this;
     let destroyGroup = function () {
       iQ(self.container).remove();
       if (self.$undoContainer) {
         self.$undoContainer.remove();
         self.$undoContainer = null;
       }
       self.removeTrenches();
@@ -672,16 +677,17 @@ GroupItem.prototype = Utils.extend(new I
     this.deleteData();
   },
 
   // ----------
   // Function: closeAll
   // Closes the groupItem and all of its children.
   closeAll: function GroupItem_closeAll() {
     if (this._children.length > 0) {
+      this._unfreezeItemSize();
       this._children.forEach(function(child) {
         iQ(child.container).hide();
       });
 
       iQ(this.container).animate({
          opacity: 0,
          "-moz-transform": "scale(.3)",
       }, {
@@ -873,18 +879,20 @@ GroupItem.prototype = Utils.extend(new I
   // ----------
   // Function: _createUndoButton
   // Makes the affordance for undo a close group action
   _createUndoButton: function GroupItem__createUndoButton() {
     let self = this;
     this.$undoContainer = iQ("<div/>")
       .addClass("undo")
       .attr("type", "button")
+      .appendTo("body");
+    iQ("<span/>")
       .text(tabviewString("groupItem.undoCloseGroup"))
-      .appendTo("body");
+      .appendTo(this.$undoContainer);
     let undoClose = iQ("<span/>")
       .addClass("close")
       .appendTo(this.$undoContainer);
 
     this.$undoContainer.css({
       left: this.bounds.left + this.bounds.width/2 - iQ(self.$undoContainer).width()/2,
       top:  this.bounds.top + this.bounds.height/2 - iQ(self.$undoContainer).height()/2,
       "-moz-transform": "scale(.1)",
@@ -1002,18 +1010,23 @@ GroupItem.prototype = Utils.extend(new I
       item.setZ(this.getZ() + 1);
       $el.addClass("tabInGroupItem");
 
       if (!wasAlreadyInThisGroupItem) {
         item.droppable(false);
         item.groupItemData = {};
 
         item.addSubscriber(this, "close", function() {
+          let count = self._children.length;
+          let dontArrange = self.expanded || !self.shouldStack(count);
           let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
-          self.remove(item, { dontClose: dontClose });
+          self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
+
+          if (dontArrange)
+            self._freezeItemSize(count);
 
           if (self._children.length > 0 && self._activeTab) {
             GroupItems.setActiveGroupItem(self);
             UI.setActiveTab(self._activeTab);
           }
         });
 
         item.setParent(this);
@@ -1030,16 +1043,17 @@ GroupItem.prototype = Utils.extend(new I
         if (item.tab == gBrowser.selectedTab || 
             (!GroupItems.getActiveGroupItem() && !item.tab.hidden))
           GroupItems.setActiveGroupItem(this);
       }
 
       if (!options.dontArrange)
         this.arrange({animate: !options.immediately});
 
+      this._unfreezeItemSize({dontArrange: true});
       this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
 
       UI.setReorderTabsOnHide(this);
     } catch(e) {
       Utils.log('GroupItem.add error', e);
     }
   },
 
@@ -1100,18 +1114,20 @@ GroupItem.prototype = Utils.extend(new I
       // if a blank tab is selected while restoring a tab the blank tab gets
       // removed. we need to keep the group alive for the restored tab.
       if (item.tab._tabViewTabIsRemovedAfterRestore)
         options.dontClose = true;
 
       let closed = options.dontClose ? false : this.closeIfEmpty();
       if (closed)
         this._makeClosestTabActive();
-      else if (!options.dontArrange)
+      else if (!options.dontArrange) {
         this.arrange({animate: !options.immediately});
+        this._unfreezeItemSize({dontArrange: true});
+      }
 
       this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
     } catch(e) {
       Utils.log(e);
     }
   },
 
   // ----------
@@ -1233,16 +1249,76 @@ GroupItem.prototype = Utils.extend(new I
  
     let shouldStack = arrObj.childWidth < TabItems.minTabWidth * 1.35;
     this._columns = shouldStack ? null : arrObj.columns;
 
     return shouldStack;
   },
 
   // ----------
+  // Function: _freezeItemSize
+  // Freezes current item size (when removing a child).
+  //
+  // Parameters:
+  //   itemCount - the number of children before the last one was removed
+  _freezeItemSize: function GroupItem__freezeItemSize(itemCount) {
+    let data = this._frozenItemSizeData;
+
+    if (!data.lastItemCount) {
+      let self = this;
+      data.lastItemCount = itemCount;
+
+      // unfreeze item size when tabview is hidden
+      data.onTabViewHidden = function () self._unfreezeItemSize();
+      window.addEventListener('tabviewhidden', data.onTabViewHidden, false);
+
+      // we don't need to observe mouse movement when expanded because the
+      // tray is closed when we leave it and collapse causes unfreezing
+      if (self.expanded)
+        return;
+
+      // unfreeze item size when cursor is moved out of group bounds
+      data.onMouseMove = function (e) {
+        let cursor = new Point(e.pageX, e.pageY);
+        if (!self.bounds.contains(cursor))
+          self._unfreezeItemSize();
+      }
+      iQ(window).mousemove(data.onMouseMove);
+    }
+
+    this.arrange({animate: true, count: data.lastItemCount});
+  },
+
+  // ----------
+  // Function: _unfreezeItemSize
+  // Unfreezes and updates item size.
+  //
+  // Parameters:
+  //   options - various options (see below)
+  //
+  // Possible options:
+  //   dontArrange - do not arrange items when unfreezing
+  _unfreezeItemSize: function GroupItem__unfreezeItemSize(options) {
+    let data = this._frozenItemSizeData;
+    if (!data.lastItemCount)
+      return;
+
+    if (!options || !options.dontArrange)
+      this.arrange({animate: true});
+
+    // unbind event listeners
+    window.removeEventListener('tabviewhidden', data.onTabViewHidden, false);
+    if (data.onMouseMove)
+      iQ(window).unbind('mousemove', data.onMouseMove);
+
+    // reset freeze status
+    this._frozenItemSizeData = {};
+  },
+
+  // ----------
   // Function: arrange
   // Lays out all of the children.
   //
   // Parameters:
   //   options - passed to <Items.arrange> or <_stackArrange>, except those below
   //
   // Options:
   //   addTab - (boolean) if true, we add one to the child count
@@ -1556,16 +1632,17 @@ GroupItem.prototype = Utils.extend(new I
       this.expanded.$shield.remove();
       this.expanded = null;
 
       this._children.forEach(function(child) {
         child.removeClass("stack-trayed");
       });
 
       this.arrange({z: z + 2});
+      this._unfreezeItemSize({dontArrange: true});
     }
   },
 
   // ----------
   // Function: _addHandlers
   // Helper routine for the constructor; adds various event handlers to the container.
   _addHandlers: function GroupItem__addHandlers(container) {
     let self = this;
@@ -1683,18 +1760,21 @@ GroupItem.prototype = Utils.extend(new I
       self.expand();
     });
   },
 
   // ----------
   // Function: setResizable
   // Sets whether the groupItem is resizable and updates the UI accordingly.
   setResizable: function GroupItem_setResizable(value, immediately) {
+    var self = this;
+
     this.resizeOptions.minWidth = GroupItems.minGroupWidth;
     this.resizeOptions.minHeight = GroupItems.minGroupHeight;
+    this.resizeOptions.start = function () self._unfreezeItemSize();
 
     if (value) {
       immediately ? this.$resizer.show() : this.$resizer.fadeIn();
       this.resizable(true);
     } else {
       immediately ? this.$resizer.hide() : this.$resizer.fadeOut();
       this.resizable(false);
     }
--- a/browser/base/content/tabview/items.js
+++ b/browser/base/content/tabview/items.js
@@ -18,16 +18,17 @@
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  * Ian Gilman <ian@iangilman.com>
  * Aza Raskin <aza@mozilla.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  * Sean Dunn <seanedunn@yahoo.com>
+ * Tim Taubert <tim.taubert@gmx.de>
  *
  * 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
@@ -164,18 +165,20 @@ Item.prototype = {
     }
 
     iQ(this.container).data('item', this);
 
     // ___ drag
     this.dragOptions = {
       cancelClass: 'close stackExpander',
       start: function(e, ui) {
-        if (this.isAGroupItem)
+        if (this.isAGroupItem) {
           GroupItems.setActiveGroupItem(this);
+          this._unfreezeItemSize();
+        }
         // if we start dragging a tab within a group, start with dropSpace on.
         else if (this.parent != null)
           this.parent._dropSpaceActive = true;
         drag.info = new Drag(this, e);
       },
       drag: function(e) {
         drag.info.drag(e);
       },
@@ -593,16 +596,45 @@ Item.prototype = {
       var $container = iQ(this.container);
       var startMouse;
       var startPos;
       var startSent;
       var startEvent;
       var droppables;
       var dropTarget;
 
+      // determine the best drop target based on the current mouse coordinates
+      let determineBestDropTarget = function (e, box) {
+        // drop events
+        var best = {
+          dropTarget: null,
+          score: 0
+        };
+
+        droppables.forEach(function(droppable) {
+          var intersection = box.intersection(droppable.bounds);
+          if (intersection && intersection.area() > best.score) {
+            var possibleDropTarget = droppable.item;
+            var accept = true;
+            if (possibleDropTarget != dropTarget) {
+              var dropOptions = possibleDropTarget.dropOptions;
+              if (dropOptions && typeof dropOptions.accept == "function")
+                accept = dropOptions.accept.apply(possibleDropTarget, [self]);
+            }
+
+            if (accept) {
+              best.dropTarget = possibleDropTarget;
+              best.score = intersection.area();
+            }
+          }
+        });
+
+        return best.dropTarget;
+      }
+
       // ___ mousemove
       var handleMouseMove = function(e) {
         // global drag tracking
         drag.lastMoveTime = Date.now();
 
         // positioning
         var mouse = new Point(e.pageX, e.pageY);
         if (!startSent) {
@@ -619,49 +651,27 @@ Item.prototype = {
           var box = self.getBounds();
           box.left = startPos.x + (mouse.x - startMouse.x);
           box.top = startPos.y + (mouse.y - startMouse.y);
           self.setBounds(box, true);
 
           if (typeof self.dragOptions.drag == "function")
             self.dragOptions.drag.apply(self, [e]);
 
-          // drop events
-          var best = {
-            dropTarget: null,
-            score: 0
-          };
+          let bestDropTarget = determineBestDropTarget(e, box);
 
-          droppables.forEach(function(droppable) {
-            var intersection = box.intersection(droppable.bounds);
-            if (intersection && intersection.area() > best.score) {
-              var possibleDropTarget = droppable.item;
-              var accept = true;
-              if (possibleDropTarget != dropTarget) {
-                var dropOptions = possibleDropTarget.dropOptions;
-                if (dropOptions && typeof dropOptions.accept == "function")
-                  accept = dropOptions.accept.apply(possibleDropTarget, [self]);
-              }
-
-              if (accept) {
-                best.dropTarget = possibleDropTarget;
-                best.score = intersection.area();
-              }
-            }
-          });
-
-          if (best.dropTarget != dropTarget) {
+          if (bestDropTarget != dropTarget) {
             var dropOptions;
             if (dropTarget) {
               dropOptions = dropTarget.dropOptions;
               if (dropOptions && typeof dropOptions.out == "function")
                 dropOptions.out.apply(dropTarget, [e]);
             }
 
-            dropTarget = best.dropTarget;
+            dropTarget = bestDropTarget;
 
             if (dropTarget) {
               dropOptions = dropTarget.dropOptions;
               if (dropOptions && typeof dropOptions.over == "function")
                 dropOptions.over.apply(dropTarget, [e]);
             }
           }
           if (dropTarget) {
@@ -705,32 +715,34 @@ Item.prototype = {
         });
 
         if (cancel) {
           e.preventDefault();
           return;
         }
 
         startMouse = new Point(e.pageX, e.pageY);
-        startPos = self.getBounds().position();
+        let bounds = self.getBounds();
+        startPos = bounds.position();
         startEvent = e;
         startSent = false;
-        dropTarget = null;
 
         droppables = [];
         iQ('.iq-droppable').each(function(elem) {
           if (elem != self.container) {
             var item = Items.item(elem);
             droppables.push({
               item: item,
               bounds: item.getBounds()
             });
           }
         });
 
+        dropTarget = determineBestDropTarget(e, bounds);
+
         iQ(gWindow)
           .mousemove(handleMouseMove)
           .mouseup(handleMouseUp);
 
         e.preventDefault();
       });
     } catch(e) {
       Utils.log(e);
--- a/browser/base/content/tabview/modules/utils.jsm
+++ b/browser/base/content/tabview/modules/utils.jsm
@@ -16,16 +16,17 @@
  * The Initial Developer of the Original Code is the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  * Aza Raskin <aza@mozilla.com>
  * Ian Gilman <ian@iangilman.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
+ * Tim Taubert <tim.taubert@gmx.de>
  *
  * This file incorporates work from:
  * jQuery JavaScript Library v1.4.2: http://code.jquery.com/jquery-1.4.2.js
  * This incorporated work is covered by the following copyright and
  * permission notice:
  * Copyright 2010, John Resig
  * Dual licensed under the MIT or GPL Version 2 licenses.
  * http://jquery.org/license
@@ -165,26 +166,32 @@ Rect.prototype = {
     if (box.width > 0 && box.height > 0)
       return box;
 
     return null;
   },
 
   // ----------
   // Function: contains
-  // Returns a boolean denoting if the given <Rect> is contained within
+  // Returns a boolean denoting if the <Rect> or <Point> is contained inside
   // this rectangle.
   //
-  // Paramaters
-  //  - A <Rect>
-  contains: function Rect_contains(rect) {
-    return (rect.left >= this.left &&
-            rect.right <= this.right &&
-            rect.top >= this.top &&
-            rect.bottom <= this.bottom);
+  // Parameters
+  //  - A <Rect> or a <Point>
+  contains: function Rect_contains(a) {
+    if (Utils.isPoint(a))
+      return (a.x > this.left &&
+              a.x < this.right &&
+              a.y > this.top &&
+              a.y < this.bottom);
+
+    return (a.left >= this.left &&
+            a.right <= this.right &&
+            a.top >= this.top &&
+            a.bottom <= this.bottom);
   },
 
   // ----------
   // Function: center
   // Returns a new <Point> with the center location of this rectangle.
   center: function Rect_center() {
     return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
   },
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -716,16 +716,17 @@ TabItem.prototype = Utils.extend(new Ite
       $canvas.css("-moz-transform", null);
 
       GroupItems.setActiveOrphanTab(null);
 
       if (typeof complete == "function")
         complete();
     };
 
+    UI.setActiveTab(this);
     TabItems._update(this.tab, {force: true});
 
     $tab.addClass("front");
 
     // If we're in a stacked group, make sure we become the
     // topChild now so that we show the zoom animation correctly.
     if (this.parent && this.parent.isStacked())
       this.parent.setTopChild(this);
--- a/browser/base/content/tabview/tabview.css
+++ b/browser/base/content/tabview/tabview.css
@@ -107,21 +107,16 @@ body {
 
 /* Other Items
 ----------------------------------*/
 
 .undo {
   position: absolute;
 }
 
-.undo .close {
-  display: inline-block;
-  position: relative;
-}
-
 .info-item {
   position: absolute;
 }
 
 /* Trenches
 ----------------------------------*/
 
 .guideTrench, 
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -200,16 +200,17 @@ endif
                  browser_pluginnotification.js \
                  browser_relatedTabs.js \
                  browser_sanitize-passwordDisabledHosts.js \
                  browser_sanitize-sitepermissions.js \
                  browser_sanitize-timespans.js \
                  browser_clearplugindata.js \
                  browser_clearplugindata.html \
                  browser_clearplugindata_noage.html \
+                 browser_popupUI.js \
                  browser_sanitizeDialog.js \
                  browser_scope.js \
                  browser_selectTabAtIndex.js \
                  browser_tab_dragdrop.js \
                  browser_tab_dragdrop2.js \
                  browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_isActive.js \
@@ -244,19 +245,16 @@ endif
                  app_subframe_bug575561.html \
                  browser_contentAreaClick.js \
                  browser_addon_bar_close_button.js \
                  browser_addon_bar_shortcut.js \
                  browser_addon_bar_aomlistener.js \
                  test_bug628179.html \
                  $(NULL)
 
-# compartment-disabled
-#                 browser_popupUI.js \
-
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
 		browser_bug565667.js \
 		browser_customize.js \
--- a/browser/base/content/test/browser_popupUI.js
+++ b/browser/base/content/test/browser_popupUI.js
@@ -16,17 +16,17 @@ function test() {
     "data:text/html,<html><script>popup=open('about:blank','','width=300,height=200')</script>";
 }
 
 function findPopup() {
   var enumerator = Services.wm.getEnumerator("navigator:browser");
 
   while (enumerator.hasMoreElements()) {
     let win = enumerator.getNext();
-    if (win.content == content.wrappedJSObject.popup) {
+    if (win.content.wrappedJSObject == content.wrappedJSObject.popup) {
       testPopupUI(win);
       return;
     }
   }
 
   throw "couldn't find the popup";
 }
 
--- a/browser/base/content/test/browser_utilityOverlay.js
+++ b/browser/base/content/test/browser_utilityOverlay.js
@@ -1,15 +1,15 @@
 var gTestTab;
 
 function test() {
   waitForExplicitFinish();
 
   is(getTopWin(), window, "got top window");
-  is(getBoolPref("general.startup.browser", false), true, "getBoolPref");
+  is(getBoolPref("browser.search.openintab", false), false, "getBoolPref");
   is(getBoolPref("this.pref.doesnt.exist", true), true, "getBoolPref fallback");
   is(getBoolPref("this.pref.doesnt.exist", false), false, "getBoolPref fallback #2");
 
 
   gTestTab = openNewTabWith("http://example.com");
   gBrowser.selectedTab = gTestTab;
   gTestTab.linkedBrowser.addEventListener("load", function () {
     gTestTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -80,16 +80,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug604098.js \
                  browser_tabview_bug604699.js \
                  browser_tabview_bug606657.js \
                  browser_tabview_bug606905.js \
                  browser_tabview_bug608037.js \
                  browser_tabview_bug608184.js \
                  browser_tabview_bug608158.js \
                  browser_tabview_bug608405.js \
+                 browser_tabview_bug610208.js \
                  browser_tabview_bug610242.js \
                  browser_tabview_bug612470.js \
                  browser_tabview_bug613541.js \
                  browser_tabview_bug616729.js \
                  browser_tabview_bug616967.js \
                  browser_tabview_bug618816.js \
                  browser_tabview_bug618828.js \
                  browser_tabview_bug619937.js \
--- a/browser/base/content/test/tabview/browser_tabview_bug597980.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug597980.js
@@ -1,18 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
-  newWindowWithTabView(onTabViewShown);
+  newWindowWithTabView(part1);
 }
 
-function onTabViewShown(win) {
+function part1(win) {
+  registerCleanupFunction(function() win.close());
+
   let contentWindow = win.document.getElementById("tab-view").contentWindow;
   is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
 
   let originalTab = win.gBrowser.selectedTab;
   let originalGroup = contentWindow.GroupItems.groupItems[0];
   let newTab = win.gBrowser.loadOneTab("about:blank", {inBackground: true});
   
   is(originalGroup.getChildren().length, 2, "The original group now has two tabs");
@@ -47,13 +49,37 @@ function onTabViewShown(win) {
   EventUtils.sendMouseEvent({ type: "mousedown" },
                             newTab._tabViewTabItem.container, contentWindow);
   EventUtils.sendMouseEvent({ type: "mouseup" },
                             newTab._tabViewTabItem.container, contentWindow);
   setTimeout(function() {
     checkActive(function() {
       checkActive(function() {
         win.close();
-        finish();
+        newWindowWithTabView(part2);
       });
     }, 490);
   }, 10)
 }
+
+function part2(win) {
+  registerCleanupFunction(function() win.close());
+
+  let newTab = win.gBrowser.loadOneTab("about:blank", {inBackground: true});
+  hideTabView(function() {
+    let selectedTab = win.gBrowser.selectedTab;
+    isnot(selectedTab, newTab, "They are different tabs");
+
+    // switch the selected tab to new tab
+    win.gBrowser.selectedTab = newTab;
+
+    win.addEventListener("tabviewhidden", function () {
+      win.removeEventListener("tabviewhidden", arguments.callee, false);
+      is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
+       win.close();
+       finish();
+    }, false);
+    // show tabview
+    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
+    // hide tabview
+    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
+  })
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug600812.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug600812.js
@@ -10,18 +10,18 @@ function test() {
 
     cw.GroupItems.setActiveGroupItem(groupItem);
     gBrowser.loadOneTab('about:blank', {inBackground: true});
 
     return groupItem;
   }
 
   let testVeryQuickDragAndDrop = function () {
-    let sourceGroup = cw.GroupItems.groupItems[0];
-    let targetGroup = createGroupItem();
+    let sourceGroup = createGroupItem();
+    let targetGroup = cw.GroupItems.groupItems[0];
 
     sourceGroup.pushAway(true);
     targetGroup.pushAway(true);
 
     let sourceTab = sourceGroup.getChild(0).container;
     EventUtils.synthesizeMouseAtCenter(sourceTab, {type: 'mousedown'}, cw);
 
     let targetTab = targetGroup.getChild(0).container;
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug610208.js
@@ -0,0 +1,231 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let cw;
+  let win;
+  let groupItem;
+
+  let next = function () {
+    let test = tests.shift();
+
+    if (test) {
+      test();
+      return;
+    }
+
+    win.close();
+    finish();
+  }
+
+  let prepareTest = function (testName) {
+    let originalBounds = groupItem.getChild(0).getBounds();
+
+    let tabItem = groupItem.getChild(1);
+    let bounds = tabItem.getBounds();
+    tabItem.close();
+
+    ok(originalBounds.equals(groupItem.getChild(0).getBounds()), testName + ': tabs did not change their size');
+    ok(bounds.equals(groupItem.getChild(1).getBounds()), testName + ': third tab is now on second tab\'s previous position');
+    
+    return originalBounds;
+  }
+
+  let cleanUpTest = function (testName, originalBounds, callback) {
+    // Use setTimeout here because the groupItem.arrange() call uses
+    // animation to re-arrange the tabItems.
+    win.setTimeout(function () {
+      ok(!originalBounds.equals(groupItem.getChild(0).getBounds()), testName + ': tabs changed their size');
+
+      // cleanup
+      cw.GroupItems.setActiveGroupItem(groupItem);
+      win.gBrowser.loadOneTab('about:blank', {inBackground: true});
+      afterAllTabsLoaded(callback, win);
+    }, 500);
+  }
+
+  let tests = [];
+
+  // focus group title's input field to cause item arrange
+  let testFocusTitle = function () {
+    let originalBounds = prepareTest('testFocusTitle');
+
+    let target = groupItem.$titleShield[0];
+    EventUtils.synthesizeMouseAtCenter(target, {}, cw);
+
+    cleanUpTest('testFocusTitle', originalBounds, next);
+  }
+
+  // hide tabview to cause item arrange
+  let testHideTabView = function () {
+    let originalBounds = prepareTest('testHideTabView');
+
+    hideTabView(function () {
+      cleanUpTest('testHideTabView', originalBounds, function () {
+        showTabView(next, win);
+      });
+    }, win);
+  }
+
+  // (undo) close a group to cause item arrange
+  let testCloseGroupUndo = function () {
+    let originalBounds = prepareTest('testCloseGroupUndo');
+
+    hideGroupItem(groupItem, function () {
+      unhideGroupItem(groupItem, function () {
+        cleanUpTest('testCloseGroupUndo', originalBounds, next);
+      });
+    });
+  }
+
+  // leave the group's container with the mouse to cause item arrange
+  let testMouseOut = function () {
+    let originalBounds = prepareTest('testMouseOut');
+    let doc = cw.document.documentElement;
+    let bounds = groupItem.getBounds();
+
+    EventUtils.synthesizeMouse(doc, bounds.right - 5, bounds.bottom - 5, {type: 'mousemove'}, cw);
+    ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testMouseOut: tabs did not change their size');
+
+    EventUtils.synthesizeMouse(doc, bounds.right + 1, bounds.bottom + 1, {type: 'mousemove'}, cw);
+    cleanUpTest('testMouseOut', originalBounds, next);
+  }
+
+  // sort item (drag it around) in its group to cause item arrange
+  let testSortInGroup = function () {
+    let originalBounds = prepareTest('testSortInGroup');
+    let target = groupItem.getChild(0).container;
+
+    // simulate drag/drop sorting
+    EventUtils.synthesizeMouse(target, 20, 20, {type: 'mousedown'}, cw);
+    EventUtils.synthesizeMouse(target, 40, 20, {type: 'mousemove'}, cw);
+    EventUtils.synthesizeMouse(target, 20, 20, {type: 'mouseup'}, cw);
+
+    cleanUpTest('testSortInGroup', originalBounds, next);
+  }
+
+  // arrange items when the containing group is resized
+  let testResizeGroup = function () {
+    let originalBounds = prepareTest('testResizeGroup');
+    let oldBounds = groupItem.getBounds();
+    let resizer = groupItem.$resizer[0];
+
+    // simulate drag/drop resizing
+    EventUtils.synthesizeMouse(resizer, 5, 5, {type: 'mousedown'}, cw);
+    EventUtils.synthesizeMouse(resizer, 40, 20, {type: 'mousemove'}, cw);
+    EventUtils.synthesizeMouse(resizer, 20, 20, {type: 'mouseup'}, cw);
+
+    // reset group size
+    groupItem.setBounds(oldBounds);
+    groupItem.setUserSize();
+
+    cleanUpTest('testResizeGroup', originalBounds, next);
+  }
+
+  // make sure we don't freeze item size when removing an item from a stack
+  let testRemoveWhileStacked = function () {
+    let oldBounds = groupItem.getBounds();
+    groupItem.setSize(150, 200, true);
+    groupItem.setUserSize();
+
+    let originalBounds = groupItem.getChild(0).getBounds();
+    ok(!groupItem._isStacked, 'testRemoveWhileStacked: group is not stacked');
+
+    // add a new tab to let the group stack
+    win.gBrowser.loadOneTab('about:blank', {inBackground: true});
+    ok(groupItem._isStacked, 'testRemoveWhileStacked: group is now stacked');
+
+    afterAllTabsLoaded(function () {
+      groupItem.getChild(0).close();
+      let bounds = groupItem.getChild(0).getBounds();
+      ok(originalBounds.equals(bounds), 'testRemoveWhileStacked: tabs did not change their size');
+
+      // reset group size
+      groupItem.setBounds(oldBounds);
+      groupItem.setUserSize();
+
+      next();
+    }, win);
+  }
+
+  // 1) make sure item size is frozen when removing an item in expanded mode
+  // 2) make sure item size stays frozen while moving the mouse in the expanded
+  // layer
+  let testExpandedMode = function () {
+    let oldBounds = groupItem.getBounds();
+    groupItem.setSize(100, 100, true);
+    groupItem.setUserSize();
+
+    ok(groupItem._isStacked, 'testExpandedMode: group is stacked');
+
+    groupItem.addSubscriber(groupItem, 'expanded', function () {
+      groupItem.removeSubscriber(groupItem, 'expanded');
+      onExpanded();
+    });
+
+    groupItem.addSubscriber(groupItem, 'collapsed', function () {
+      groupItem.removeSubscriber(groupItem, 'collapsed');
+      onCollapsed();
+    });
+
+    let onExpanded = function () {
+      let originalBounds = groupItem.getChild(0).getBounds();
+      let tabItem = groupItem.getChild(1);
+      let bounds = tabItem.getBounds();
+
+      for (let i=0; i<3; i++)
+        groupItem.getChild(1).close();
+
+      ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testExpandedMode: tabs did not change their size');
+
+      // move the mouse over the expanded layer
+      let trayBounds = groupItem.expanded.bounds;
+      let target = groupItem.expanded.$tray[0];
+      EventUtils.synthesizeMouse(target, trayBounds.right - 5, trayBounds.bottom -5, {type: 'mousemove'}, cw);
+
+      ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testExpandedMode: tabs did not change their size');
+      groupItem.collapse();
+    }
+
+    let onCollapsed = function () {
+      // reset group size
+      groupItem.setBounds(oldBounds);
+      groupItem.setUserSize();
+
+      next();
+    }
+
+    groupItem.expand();
+  }
+
+  tests.push(testFocusTitle);
+  tests.push(testHideTabView);
+  tests.push(testCloseGroupUndo);
+  tests.push(testMouseOut);
+  tests.push(testSortInGroup);
+  tests.push(testResizeGroup);
+  tests.push(testRemoveWhileStacked);
+  tests.push(testExpandedMode);
+
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (tvwin) {
+    win = tvwin;
+
+    registerCleanupFunction(function () {
+      if (!win.closed)
+        win.close();
+    });
+
+    cw = win.TabView.getContentWindow();
+
+    groupItem = cw.GroupItems.groupItems[0];
+    groupItem.setSize(400, 200, true);
+    groupItem.setUserSize();
+
+    for (let i=0; i<3; i++)
+      win.gBrowser.loadOneTab('about:blank', {inBackground: true});
+
+    afterAllTabsLoaded(next, win);
+  });
+}
--- a/browser/components/preferences/advanced.xul
+++ b/browser/components/preferences/advanced.xul
@@ -122,19 +122,16 @@
                   name="security.disable_button.openCertManager"
                   type="bool"/>
       <preference id="security.OCSP.disable_button.managecrl"
                   name="security.OCSP.disable_button.managecrl"
                   type="bool"/>
       <preference id="security.disable_button.openDeviceManager"
                   name="security.disable_button.openDeviceManager"
                   type="bool"/>
-      <preference id="privacy.donottrackheader.enabled"
-                  name="privacy.donottrackheader.enabled"
-                  type="bool"/>
     </preferences>
     
 #ifdef HAVE_SHELL_SERVICE
     <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
     <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
 #endif
 
     <script type="application/javascript" src="chrome://browser/content/preferences/advanced.js"/>
@@ -189,20 +186,16 @@
                       accesskey="&allowHWAccel.accesskey;"
                       preference="layers.acceleration.disabled"/>
             <checkbox id="checkSpelling"
                       label="&checkSpelling.label;"
                       accesskey="&checkSpelling.accesskey;"
                       onsyncfrompreference="return gAdvancedPane.readCheckSpelling();"
                       onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
                       preference="layout.spellcheckDefault"/>
-            <checkbox id="privacyDoNotTrackPrefs"
-                      label="&doNotTrack.label;"
-                      accesskey="&doNotTrack.accesskey;"
-                      preference="privacy.donottrackheader.enabled"/>
           </groupbox>
 
 #ifdef HAVE_SHELL_SERVICE
           <!-- System Defaults -->
           <groupbox id="systemDefaultsGroup" orient="vertical">
             <caption label="&systemDefaults.label;"/>
 
             <hbox id="checkDefaultBox" align="center" flex="1">      
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -52,16 +52,21 @@
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:html="http://www.w3.org/1999/xhtml">
 
   <prefpane id="panePrivacy"
             onpaneload="gPrivacyPane.init();"
             helpTopic="prefs-privacy">
 
     <preferences id="privacyPreferences">
+  
+      <!-- Tracking -->
+      <preference id="privacy.donottrackheader.enabled"
+                  name="privacy.donottrackheader.enabled"
+                  type="bool"/>
 
       <!-- XXX button prefs -->
       <preference id="pref.privacy.disable_button.cookie_exceptions"
                   name="pref.privacy.disable_button.cookie_exceptions"
                   type="bool"/>
       <preference id="pref.privacy.disable_button.view_cookies"
                   name="pref.privacy.disable_button.view_cookies"
                   type="bool"/>
@@ -111,16 +116,26 @@
                   type="bool"/>
 
     </preferences>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
     
     <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/>
 
+    <!-- Tracking -->
+    <groupbox id="trackingGroup">
+      <caption label="&tracking.label;"/>
+
+      <checkbox id="privacyDoNotTrackPrefs"
+                label="&doNotTrack.label;"
+                accesskey="&doNotTrack.accesskey;"
+                preference="privacy.donottrackheader.enabled"/>
+    </groupbox>
+
     <!-- History -->
     <groupbox id="historyGroup">
       <caption label="&history.label;"/>
 
       <hbox align="center">
         <label id="historyModeLabel"
                control="historyMode"
                accesskey="&historyHeader.pre.accesskey;">&historyHeader.pre.label;</label>
--- a/browser/components/preferences/security.xul
+++ b/browser/components/preferences/security.xul
@@ -76,18 +76,17 @@
 
     </preferences>
     
     <script type="application/javascript" src="chrome://browser/content/preferences/security.js"/>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <!-- addons, forgery (phishing) UI -->
-    <groupbox id="addonsPhishingGroup"
-              xmlns:aaa="http://www.w3.org/2005/07/aaa">
+    <groupbox id="addonsPhishingGroup">
       <hbox id="addonInstallBox">
         <checkbox id="warnAddonInstall" flex="1"
                   label="&warnAddonInstall.label;"
                   accesskey="&warnAddonInstall.accesskey;"
                   preference="xpinstall.whitelist.required"
                   onsyncfrompreference="return gSecurityPane.readWarnAddonInstall();"/>
         <button id="addonExceptions"
                 label="&addonExceptions.label;"
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -462,17 +462,17 @@ PrivateBrowsingService.prototype = {
         break;
     }
   },
 
   // nsICommandLineHandler
 
   handle: function PBS_handle(aCmdLine) {
     if (aCmdLine.handleFlag("private", false))
-      ; // It has already been handled
+      aCmdLine.preventDefault = true; // It has already been handled
     else if (aCmdLine.handleFlag("private-toggle", false)) {
       if (this._autoStarted) {
         throw Cr.NS_ERROR_ABORT;
       }
       this.privateBrowsingEnabled = !this.privateBrowsingEnabled;
       this._lastChangedByCommandLine = true;
     }
   },
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -635,16 +635,22 @@
 
           // Add observer for suggest preference
           var ps2 = Components.classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefBranch2);
           ps2.addObserver("browser.search.suggest.enabled", this, false);
         ]]></body>
       </method>
 
+      <!--
+        This method overrides the autocomplete binding's openPopup (essentially
+        duplicating the logic from the autocomplete popup binding's
+        openAutocompletePopup method), modifying it so that the popup is aligned with
+        the inner textbox, but sized to not extend beyond the search bar border.
+      -->
       <method name="openPopup">
         <body><![CDATA[
           var popup = this.popup;
           if (!popup.mPopupOpen) {
             // Initially the panel used for the searchbar (PopupAutoComplete
             // in browser.xul) is hidden to avoid impacting startup / new
             // window performance. The base binding's openPopup would normally
             // call the overriden openAutocompletePopup in urlbarBindings.xml's
@@ -657,28 +663,36 @@
             popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
             popup.invalidate();
 
             popup.showCommentColumn = this.showCommentColumn;
             popup.showImageColumn = this.showImageColumn;
 
             document.popupNode = null;
 
+            const isRTL = getComputedStyle(this, "").direction == "rtl";
+
             var outerRect = this.getBoundingClientRect();
             var innerRect = this.inputField.getBoundingClientRect();
-            var width = outerRect.right - innerRect.left;
+            if (isRTL) {
+              var width = innerRect.right - outerRect.left;
+            } else {
+              var width = outerRect.right - innerRect.left;
+            }
             popup.setAttribute("width", width > 100 ? width : 100);
 
+            var yOffset = outerRect.bottom - innerRect.bottom;
+
             // setConsumeRollupEvent() before we call openPopup(), 
             // see bug #404438 for more details
             popup.popupBoxObject.setConsumeRollupEvent(
               this.consumeRollupEvent ? 
                 Ci.nsIPopupBoxObject.ROLLUP_CONSUME : 
                 Ci.nsIPopupBoxObject.ROLLUP_NO_CONSUME);
-            popup.openPopup(null, "", innerRect.left, outerRect.bottom, false, false);
+            popup.openPopup(this.inputField, "after_start", 0, yOffset, false, false);
           }
         ]]></body>
       </method>
 
       <method name="observe">
         <parameter name="aSubject"/>
         <parameter name="aTopic"/>
         <parameter name="aData"/>
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -3,17 +3,22 @@
 # Win7: AppVendor, AppName, and AppVersion must match the application.ini values
 # of Vendor, Name, and Version. These values are used in registering shortcuts
 # with the taskbar. ExplicitAppUserModelID registration when the app launches is
 # handled in widget/src/windows/WinTaskbar.cpp.
 
 !define AppVendor             "Mozilla"
 !define AppName               "Firefox"
 !define AppVersion            "@APP_VERSION@"
+#ifdef HAVE_64BIT_OS
+// differentiate 64-bit builds, we do the same in widget.
+!define AppUserModelID        "${AppVendor}.${AppName}.${AppVersion}.Win64"
+#else
 !define AppUserModelID        "${AppVendor}.${AppName}.${AppVersion}"
+#endif
 !define GREVersion            @MOZILLA_VERSION@
 !define AB_CD                 "@AB_CD@"
 
 !define FileMainEXE           "@MOZ_APP_NAME@.exe"
 !define WindowClass           "FirefoxMessageWindow"
 !define DDEApplication        "Firefox"
 !define AppRegName            "Firefox"
 
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -16,18 +16,16 @@
 <!ENTITY useAutoScroll.label             "Use autoscrolling">
 <!ENTITY useAutoScroll.accesskey         "a">
 <!ENTITY useSmoothScrolling.label        "Use smooth scrolling">
 <!ENTITY useSmoothScrolling.accesskey    "m">
 <!ENTITY allowHWAccel.label              "Use hardware acceleration when available">
 <!ENTITY allowHWAccel.accesskey          "h">
 <!ENTITY checkSpelling.label             "Check my spelling as I type">
 <!ENTITY checkSpelling.accesskey         "t">
-<!ENTITY doNotTrack.label                "Tell web sites I do not want to be tracked">
-<!ENTITY doNotTrack.accesskey            "d">
 
 <!ENTITY systemDefaults.label            "System Defaults">
 <!ENTITY alwaysCheckDefault.label        "Always check to see if &brandShortName; is the default browser on startup"><!--XXX-->
 <!ENTITY alwaysCheckDefault.accesskey    "w">
 <!ENTITY checkNow.label                  "Check Now">
 <!ENTITY checkNow.accesskey              "N">
 <!ENTITY submitCrashes.label             "Submit crash reports">
 <!ENTITY submitCrashes.accesskey         "S">
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -1,8 +1,13 @@
+<!ENTITY tracking.label                 "Tracking">
+
+<!ENTITY doNotTrack.label               "Tell web sites I do not want to be tracked">
+<!ENTITY doNotTrack.accesskey           "d">
+
 <!ENTITY  history.label                 "History">
 
 <!ENTITY  locationBar.label             "Location Bar">
 
 <!ENTITY  locbar.pre.label              "When using the location bar, suggest:">
 <!ENTITY  locbar.pre.accessKey          "u">
 <!ENTITY  locbar.post.label             "">
 <!ENTITY  locbar.both.label             "History and Bookmarks">
@@ -25,17 +30,16 @@
 <!ENTITY  askEachTime.label             "ask me every time">
 
 <!ENTITY  cookieExceptions.label        "Exceptions…">
 <!ENTITY  cookieExceptions.accesskey    "E">
 
 <!ENTITY  showCookies.label             "Show Cookies…">
 <!ENTITY  showCookies.accesskey         "S">
 
-
 <!ENTITY  historyHeader.pre.label          "&brandShortName; will:">
 <!ENTITY  historyHeader.pre.accesskey      "w">
 <!ENTITY  historyHeader.remember.label     "Remember history">
 <!ENTITY  historyHeader.dontremember.label "Never remember history">
 <!ENTITY  historyHeader.custom.label       "Use custom settings for history">
 <!ENTITY  historyHeader.post.label         "">
 
 <!ENTITY  rememberDescription.label      "&brandShortName; will remember your browsing, download, form and search history, and keep cookies from Web sites you visit.">
--- a/browser/themes/gnomestripe/browser/tabview/tabview.css
+++ b/browser/themes/gnomestripe/browser/tabview/tabview.css
@@ -294,41 +294,44 @@ html[dir=rtl] .appTabTrayContainer {
   cursor: pointer;
   opacity: 0.8;
   padding-bottom: 3px;
   display: block;
 }
 
 .undo {
   background-color: rgba(0,0,0,.2);
-  width: 150px;
-  height: 30px;
-  line-height: 30px;
+  padding-top: 3px;
+  padding-bottom: 3px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 20px;
+  width: 135px;
+  line-height: 25px;
   box-shadow: 0 1px 0 rgba(255,255,255,.4), 0 1px 0 rgba(0,0,0,.3) inset;
   text-shadow: 0 1px 0 rgba(255,255,255,.2);
   color: WindowText;
   border-radius: 0.4em;
   text-align: center;
   border: none;
   cursor: pointer;
 }
 
 .undo:hover {
   background-color: rgba(0,0,0,.3);
 }
 
 .undo .close {
-  top: 4px;
-  left: 4px;
+  top: 7px;
+  right: 7px;
   opacity: 0.5;
 }
 
 html[dir=rtl] .undo .close {
-  left: auto;
-  right: 4px;
+  right: auto;
+  left: 7px;
 }
 
 .undo .close:hover{
   opacity: 1.0;
 }
 
 
 /* InfoItems
--- a/browser/themes/pinstripe/browser/tabview/tabview.css
+++ b/browser/themes/pinstripe/browser/tabview/tabview.css
@@ -288,41 +288,44 @@ html[dir=rtl] .appTabTrayContainer {
   cursor: pointer;
   opacity: 0.8;
   padding-bottom: 3px;
   display: block;
 }
 
 .undo {
   background-color: #A0A0A0;
-  width: 150px;
-  height: 30px;
-  line-height: 30px;
+  padding-top: 3px;
+  padding-bottom: 3px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 20px;
+  width: 135px;
+  line-height: 25px;
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.24);
   text-shadow: 0px -1px 0px rgba(255,255,255,.2);
   color: rgba( 0,0,0, .8);
   border-radius: 0.4em;
   text-align: center;
   border: none;
   cursor: pointer;
 }
 
 .undo:hover {
   background-color: #949494;
 }
 
 .undo .close {
-  top: 4px;
-  left: 4px;
+  top: 7px;
+  right: 7px;
   opacity: 0.5;
 }
 
 html[dir=rtl] .undo .close {
-  left: auto;
-  right: 4px;
+  right: auto;
+  left: 7px;
 }
 
 .undo .close:hover{
   opacity: 1.0;
 }
 
 /* InfoItems
 ----------------------------------*/
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -51,17 +51,17 @@
 %include ../../browserShared.inc
 %filter substitution
 %define toolbarHighlight rgba(255,255,255,.5)
 %define selectedTabHighlight rgba(255,255,255,.7)
 %define toolbarShadowColor rgba(10%,10%,10%,.4)
 %define toolbarShadowOnTab -moz-linear-gradient(bottom, rgba(10%,10%,10%,.4) 1px, transparent 1px)
 %define bgTabTexture -moz-linear-gradient(transparent, hsla(0,0%,45%,.1) 1px, hsla(0,0%,32%,.2) 80%, hsla(0,0%,0%,.2))
 %define bgTabTextureHover -moz-linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2))
-%define navbarTextboxCustomBorder border-color: rgba(0,0,0,.25) rgba(0,0,0,.32) rgba(0,0,0,.37);
+%define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32);
 
 #menubar-items {
   -moz-box-orient: vertical; /* for flex hack */
 }
 
 #main-menubar {
   -moz-box-flex: 1; /* make menu items expand to fill toolbar height */
 }
@@ -600,22 +600,21 @@ menuitem.bookmark-item {
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
 #nav-bar .toolbarbutton-1 {
   -moz-appearance: none;
   padding: 1px 5px;
   background: rgba(151,152,153,.05)
               -moz-linear-gradient(rgba(251,252,253,.95), rgba(246,247,248,.47) 49%, 
                                    rgba(231,232,233,.45) 51%, rgba(225,226,229,.3));
   background-clip: padding-box;
-  border-radius: 4.5px;
+  border-radius: 3.5px;
   border: 1px solid;
   border-color: rgba(0,0,0,.12) rgba(0,0,0,.19) rgba(0,0,0,.38);
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
-              0 0 0 2px rgba(255,255,255,.1) inset,
-              0 1px 0 rgba(0,0,0,.15);
+              0 0 0 2px rgba(255,255,255,.1) inset;
   color: black;
   text-shadow: 0 0 2px white;
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
 #navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 #navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 {
   padding-left: 3px;
@@ -666,17 +665,16 @@ menuitem.bookmark-item {
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
 #nav-bar .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
 #nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover {
   background-color: hsla(190,60%,70%,.5);
   border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8);
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 1.5px rgba(255,255,255,.1) inset,
-              0 1px 0 rgba(0,0,0,.1),
               0 0 3.5px hsl(190,90%,80%);
   -moz-transition: background-color .4s ease-in,
                    border-color .3s ease-in,
                    box-shadow .3s ease-in;
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
 #nav-bar .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
@@ -796,27 +794,25 @@ toolbar[mode="full"] .toolbarbutton-1 > 
   margin-bottom: -2px;
   border: none;
   background-image: -moz-linear-gradient(rgba(251,252,253,.97), rgba(246,247,248,.5) 49%, 
                                          rgba(231,232,233,.45) 51%, rgba(225,226,229,.2));
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 2px rgba(255,255,255,.1) inset,
               0 0 0 1px rgba(0,0,0,.15),
               0 1px 0 rgba(0,0,0,.4),
-              0 1px 1px rgba(0,0,0,.3),
-              1px 2px 1px rgba(0,0,0,.2);
+              0 1px 1px rgba(0,0,0,.3);
 }
 
 #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover {
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 2px rgba(255,255,255,.1) inset,
               0 0 0 1px hsla(190,50%,40%,.3),
               0 1px 0 rgba(0,0,0,.4),
               0 1px 1px rgba(0,0,0,.3),
-              1px 2px 1px rgba(0,0,0,.2),
               0 0 5px 1px hsl(190,90%,80%);
 }
 
 #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):hover:active,
 #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"] {
   box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
               0 0 2px rgba(0,0,0,.4) inset,
               0 0 0 1px rgba(0,0,0,.65),
@@ -1097,19 +1093,17 @@ toolbar[mode="full"] .toolbarbutton-1 > 
 
 #urlbar,
 .searchbar-textbox {
   -moz-appearance: none;
   margin: 1px 3px;
   padding: 2px;
   background-clip: padding-box;
   border: 1px solid ThreeDDarkShadow;
-  border-radius: 4px;
-  box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
-              0 1px 0 rgba(255,255,255,.4);
+  border-radius: 3.5px;
 }
 
 @media all and (-moz-windows-default-theme) {
   #urlbar,
   .searchbar-textbox {
     @navbarTextboxCustomBorder@
   }
 }
--- a/browser/themes/winstripe/browser/tabview/tabview.css
+++ b/browser/themes/winstripe/browser/tabview/tabview.css
@@ -313,41 +313,44 @@ html[dir=rtl] .appTabTrayContainer {
   cursor: pointer;
   opacity: 0.8;
   padding-bottom: 3px;
   display: block;
 }
 
 .undo {
   background-color: #A0A0A0;
-  width: 150px;
-  height: 30px;
-  line-height: 30px;
+  padding-top: 3px;
+  padding-bottom: 3px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 20px;
+  width: 135px;
+  line-height: 25px;
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.24);
   text-shadow: 0px -1px 0px rgba(255,255,255,.2);
   color: rgba( 0,0,0, .8);
   border-radius: 0.4em;
   text-align: center;
   border: none;
   cursor: pointer;
 }
 
 .undo:hover {
   background-color: #949494;
 }
 
 .undo .close {
-  top: 4px;
-  left: 4px;
+  top: 7px;
+  right: 7px;
   opacity: 0.5;
 }
 
 html[dir=rtl] .undo .close {
-  left: auto;
-  right: 4px;
+  right: auto;
+  left: 7px;
 }
 
 .undo .close:hover{
   opacity: 1.0;
 }
 
 /* InfoItems
 ----------------------------------*/
--- a/caps/idl/nsIScriptSecurityManager.idl
+++ b/caps/idl/nsIScriptSecurityManager.idl
@@ -52,17 +52,17 @@ interface nsIScriptSecurityManager : nsI
                                         in JSObjectPtr aJSObject,
                                         in string aClassName,
                                         in jsid aProperty,
                                         in PRUint32 aAction);
 
     /**
      * Check that the script currently running in context "cx" can load "uri".
      *
-     * Will return error code NS_ERROR_DOM_BAD_URI if the load request 
+     * Will return error code NS_ERROR_DOM_BAD_URI if the load request
      * should be denied.
      *
      * @param cx the JSContext of the script causing the load
      * @param uri the URI that is being loaded
      */
     [noscript] void checkLoadURIFromScript(in JSContextPtr cx, in nsIURI uri);
 
     /**
@@ -100,63 +100,63 @@ interface nsIScriptSecurityManager : nsI
     //   Firefox 1.0.4.  Use in prior versions WILL BE IGNORED.
     // When using this, make sure that you actually want DISALLOW_SCRIPT, not
     // DISALLOW_INHERIT_PRINCIPAL
     const unsigned long DISALLOW_SCRIPT = 1 << 3;
 
     /**
      * Check that content with principal aPrincipal can load "uri".
      *
-     * Will return error code NS_ERROR_DOM_BAD_URI if the load request 
+     * Will return error code NS_ERROR_DOM_BAD_URI if the load request
      * should be denied.
      *
      * @param aPrincipal the principal identifying the actor causing the load
      * @param uri the URI that is being loaded
      * @param flags the permission set, see above
      */
     void checkLoadURIWithPrincipal(in nsIPrincipal aPrincipal,
-                                   in nsIURI uri, 
+                                   in nsIURI uri,
                                    in unsigned long flags);
 
     /**
      * Check that content from "from" can load "uri".
      *
-     * Will return error code NS_ERROR_DOM_BAD_URI if the load request 
+     * Will return error code NS_ERROR_DOM_BAD_URI if the load request
      * should be denied.
      *
      * @param from the URI causing the load
      * @param uri the URI that is being loaded
      * @param flags the permission set, see above
      *
      * @deprecated Use checkLoadURIWithPrincipal instead of this function.
      */
-    void checkLoadURI(in nsIURI from, in nsIURI uri, 
-                      in unsigned long flags);
+    [deprecated] void checkLoadURI(in nsIURI from, in nsIURI uri,
+                                   in unsigned long flags);
 
     /**
      * Similar to checkLoadURIWithPrincipal but there are two differences:
      *
      * 1) The URI is a string, not a URI object.
      * 2) This function assumes that the URI may still be subject to fixup (and
      * hence will check whether fixed-up versions of the URI are allowed to
      * load as well); if any of the versions of this URI is not allowed, this
      * function will return error code NS_ERROR_DOM_BAD_URI.
      */
     void checkLoadURIStrWithPrincipal(in nsIPrincipal aPrincipal,
-                                      in AUTF8String uri, 
-                                      in unsigned long flags);     
-    
+                                      in AUTF8String uri,
+                                      in unsigned long flags);
+
     /**
      * Same as CheckLoadURI but takes string arguments for ease of use
      * by scripts
      *
      * @deprecated Use checkLoadURIStrWithPrincipal instead of this function.
      */
-    void checkLoadURIStr(in AUTF8String from, in AUTF8String uri, 
-                         in unsigned long flags);
+    [deprecated] void checkLoadURIStr(in AUTF8String from, in AUTF8String uri,
+                                      in unsigned long flags);
 
     /**
      * Check that the function 'funObj' is allowed to run on 'targetObj'
      *
      * Will return error code NS_ERROR_DOM_SECURITY_ERR if the function
      * should not run
      *
      * @param cx The current active JavaScript context.
@@ -168,20 +168,20 @@ interface nsIScriptSecurityManager : nsI
 
     /**
      * Return true if content from the given principal is allowed to
      * execute scripts.
      */
     [noscript] boolean canExecuteScripts(in JSContextPtr cx,
                                          in nsIPrincipal principal);
 
-    ///////////////// Principals /////////////////////// 
+    ///////////////// Principals ///////////////////////
     /**
-     * Return the principal of the innermost frame of the currently 
-     * executing script. Will return null if there is no script 
+     * Return the principal of the innermost frame of the currently
+     * executing script. Will return null if there is no script
      * currently executing.
      */
     [noscript] nsIPrincipal getSubjectPrincipal();
 
     /**
      * Return the all-powerful system principal.
      */
     nsIPrincipal getSystemPrincipal();
@@ -210,22 +210,22 @@ interface nsIScriptSecurityManager : nsI
     /**
      * Request that 'capability' can be enabled by scripts or applets
      * running with 'principal'. Will prompt user if
      * necessary. Returns nsIPrincipal::ENABLE_GRANTED or
      * nsIPrincipal::ENABLE_DENIED based on user's choice.
      */
     [noscript] short requestCapability(in nsIPrincipal principal,
                                        in string capability);
-    
+
     /**
      * Return true if the currently executing script has 'capability' enabled.
      */
     boolean isCapabilityEnabled(in string capability);
-    
+
     /**
      * Enable 'capability' in the innermost frame of the currently executing
      * script.
      */
     void enableCapability(in string capability);
 
     /**
      * Remove 'capability' from the innermost frame of the currently
@@ -244,17 +244,17 @@ interface nsIScriptSecurityManager : nsI
     /**
      * Allow 'certificateID' to enable 'capability.' Can only be performed
      * by code signed by the system certificate.
      */
     // XXXbz Capabilities can't have non-ascii chars?
     // XXXbz ideally we'd pass a subjectName here too, and the nsISupports
     // cert we're enabling for...
     void setCanEnableCapability(in AUTF8String certificateFingerprint,
-                                in string capability, 
+                                in string capability,
                                 in short canEnable);
 
     ///////////////////////
     /**
      * Return the principal of the specified object in the specified context.
      */
     [noscript] nsIPrincipal getObjectPrincipal(in JSContextPtr cx,
                                                in JSObjectPtr obj);
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -61,26 +61,26 @@ NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrinci
 NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
                              nsIPrincipal,
                              nsISerializable)
 
 NS_IMETHODIMP_(nsrefcnt) 
 nsNullPrincipal::AddRef()
 {
   NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
-  nsrefcnt count = PR_AtomicIncrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
   NS_LOG_ADDREF(this, count, "nsNullPrincipal", sizeof(*this));
   return count;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
 nsNullPrincipal::Release()
 {
   NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
-  nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
   NS_LOG_RELEASE(this, count, "nsNullPrincipal");
   if (count == 0) {
     delete this;
   }
 
   return count;
 }
 
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -149,26 +149,26 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal
                              nsIPrincipal,
                              nsISerializable)
 
 NS_IMETHODIMP_(nsrefcnt)
 nsPrincipal::AddRef()
 {
   NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
   // XXXcaa does this need to be threadsafe?  See bug 143559.
-  nsrefcnt count = PR_AtomicIncrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
   NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
   return count;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
 nsPrincipal::Release()
 {
   NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
-  nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
   NS_LOG_RELEASE(this, count, "nsPrincipal");
   if (count == 0) {
     delete this;
   }
 
   return count;
 }
 
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -58,26 +58,26 @@ NS_IMPL_QUERY_INTERFACE2_CI(nsSystemPrin
 NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal,
                              nsIPrincipal,
                              nsISerializable)
 
 NS_IMETHODIMP_(nsrefcnt) 
 nsSystemPrincipal::AddRef()
 {
   NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
-  nsrefcnt count = PR_AtomicIncrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
   NS_LOG_ADDREF(this, count, "nsSystemPrincipal", sizeof(*this));
   return count;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
 nsSystemPrincipal::Release()
 {
   NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
-  nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
+  nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
   NS_LOG_RELEASE(this, count, "nsSystemPrincipal");
   if (count == 0) {
     delete this;
   }
 
   return count;
 }
 
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -163,16 +163,20 @@ MOZ_TREMOR = @MOZ_TREMOR@
 MOZ_WEBM = @MOZ_WEBM@
 VPX_AS = @VPX_AS@
 VPX_ASFLAGS = @VPX_ASFLAGS@
 VPX_DASH_C_FLAG = @VPX_DASH_C_FLAG@
 VPX_AS_CONVERSION = @VPX_AS_CONVERSION@
 VPX_ASM_SUFFIX = @VPX_ASM_SUFFIX@
 VPX_X86_ASM = @VPX_X86_ASM@
 VPX_ARM_ASM = @VPX_ARM_ASM@
+LIBJPEG_TURBO_AS = @LIBJPEG_TURBO_AS@
+LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@
+LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@
+LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@
 NS_PRINTING = @NS_PRINTING@
 MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
 MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
 MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
 MOC= @MOC@
 MOZ_NSS_PATCH = @MOZ_NSS_PATCH@
 MOZ_WEBGL = @MOZ_WEBGL@
 MOZ_ANGLE = @MOZ_ANGLE@
@@ -380,16 +384,17 @@ CXX		    = @CXX@
 CC_VERSION	= @CC_VERSION@
 CXX_VERSION	= @CXX_VERSION@
 
 GNU_AS		= @GNU_AS@
 GNU_LD		= @GNU_LD@
 GNU_CC		= @GNU_CC@
 GNU_CXX		= @GNU_CXX@
 HAVE_GCC3_ABI	= @HAVE_GCC3_ABI@
+HAVE_OLD_CLANG	= @HAVE_OLD_CLANG@
 INTEL_CC	= @INTEL_CC@
 INTEL_CXX	= @INTEL_CXX@
 
 STL_FLAGS		= @STL_FLAGS@
 WRAP_STL_INCLUDES	= @WRAP_STL_INCLUDES@
 MOZ_MSVC_STL_WRAP__Throw= @MOZ_MSVC_STL_WRAP__Throw@
 MOZ_MSVC_STL_WRAP__RAISE= @MOZ_MSVC_STL_WRAP__RAISE@
 
new file mode 100644
--- /dev/null
+++ b/config/find_OOM_errors.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python
+
+usage = """%prog: A test for OOM conditions in the shell.
+
+%prog finds segfaults and other errors caused by incorrect handling of
+allocation during OOM (out-of-memory) conditions.
+"""
+
+help = """Check for regressions only. This runs a set of files with a known
+number of OOM errors (specified by REGRESSION_COUNT), and exits with a non-zero
+result if more or less errors are found. See js/src/Makefile.in for invocation.
+"""
+
+
+import hashlib
+import re
+import shlex
+import subprocess
+import sys
+import threading
+import time
+
+from optparse import OptionParser
+
+#####################################################################
+# Utility functions
+#####################################################################
+def run(args, stdin=None):
+  class ThreadWorker(threading.Thread):
+    def __init__(self, pipe):
+      super(ThreadWorker, self).__init__()
+      self.all = ""
+      self.pipe = pipe
+      self.setDaemon(True)
+
+    def run(self):
+      while True:
+        line = self.pipe.readline()
+        if line == '': break
+        else:
+          self.all += line
+
+  try:
+    if type(args) == str:
+      args = shlex.split(args)
+
+    args = [str(a) for a in args] # convert to strs
+
+    stdin_pipe = subprocess.PIPE if stdin else None
+    proc = subprocess.Popen(args, stdin=stdin_pipe, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    if stdin_pipe:
+      proc.stdin.write(stdin)
+      proc.stdin.close()
+
+    stdout_worker = ThreadWorker(proc.stdout)
+    stderr_worker = ThreadWorker(proc.stderr)
+    stdout_worker.start()
+    stderr_worker.start()
+
+    proc.wait()
+    stdout_worker.join()
+    stderr_worker.join()
+
+  except KeyboardInterrupt, e:
+    sys.exit(-1)
+
+  stdout, stderr = stdout_worker.all, stderr_worker.all
+  result = (stdout, stderr, proc.returncode)
+  return result
+
+def get_js_files():
+  (out, err, exit) = run('find ../jit-test/tests -name "*.js"')
+  if (err, exit) == ("", 0):
+    sys.exit("Wrong directory, run from an objdir")
+  return out.split()
+
+
+
+#####################################################################
+# Blacklisting
+#####################################################################
+def in_blacklist(sig):
+  return sig in blacklist
+
+def add_to_blacklist(sig):
+  blacklist[sig] = blacklist.get(sig, 0)
+  blacklist[sig] += 1
+
+# How often is a particular lines important for this.
+def count_lines():
+  """Keep track of the amount of times individual lines occur, in order to
+     prioritize the errors which occur most frequently."""
+  counts = {}
+  for string,count in blacklist.items():
+    for line in string.split("\n"):
+      counts[line] = counts.get(line, 0) + count
+
+  lines = []
+  for k,v in counts.items():
+    lines.append("%6d: %s" % (v,k))
+
+  lines.sort()
+
+  countlog = file("../OOM_count_log", "w")
+  countlog.write("\n".join(lines))
+  countlog.flush()
+  countlog.close()
+
+
+#####################################################################
+# Output cleaning
+#####################################################################
+def clean_voutput(err):
+  # Skip what we can't reproduce
+  err = re.sub(r"^--\d+-- run: /usr/bin/dsymutil \"shell/js\"$", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^==\d+==", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^\*\*\d+\*\*", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^\s+by 0x[0-9A-Fa-f]+: ", "by: ", err, flags=re.MULTILINE)
+  err = re.sub(r"^\s+at 0x[0-9A-Fa-f]+: ", "at: ", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is not stack'd)", r"\1\2", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Invalid write of size )\d+", r"\1x", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Invalid read of size )\d+", r"\1x", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is )\d+( bytes inside a block of size )[0-9,]+( free'd)", r"\1\2\3\4", err, flags=re.MULTILINE)
+
+  # Skip the repeating bit due to the segfault
+  lines = []
+  for l in err.split('\n'):
+    if l == " Process terminating with default action of signal 11 (SIGSEGV)":
+      break
+    lines.append(l)
+  err = '\n'.join(lines)
+
+  return err
+
+def remove_failed_allocation_backtraces(err):
+  lines = []
+
+  add = True
+  for l in err.split('\n'):
+
+    # Set start and end conditions for including text
+    if l == " The site of the failed allocation is:":
+      add = False
+    elif l[:2] not in ['by: ', 'at:']:
+      add = True
+
+    if add:
+      lines.append(l)
+
+
+  err = '\n'.join(lines)
+
+  return err
+
+
+def clean_output(err):
+  err = re.sub(r"^js\(\d+,0x[0-9a-f]+\) malloc: \*\*\* error for object 0x[0-9a-f]+: pointer being freed was not allocated\n\*\*\* set a breakppoint in malloc_error_break to debug\n$", "pointer being freed was not allocated", err, flags=re.MULTILINE)
+
+  return err
+
+
+#####################################################################
+# Consts, etc
+#####################################################################
+
+command_template = 'shell/js' \
+                 + ' -m -j -p' \
+                 + ' -e "const platform=\'darwin\'; const libdir=\'../jit-test/lib/\';"' \
+                 + ' -f ../jit-test/lib/prolog.js' \
+                 + ' -f %s'
+
+
+# Blacklists are things we don't want to see in our logs again (though we do
+# want to count them when they happen). Whitelists we do want to see in our
+# logs again, principally because the information we have isn't enough.
+
+blacklist = {}
+add_to_blacklist(r"('', '', 1)") # 1 means OOM if the shell hasn't launched yet.
+add_to_blacklist(r"('', 'out of memory\n', 1)")
+
+whitelist = set()
+whitelist.add(r"('', 'out of memory\n', -11)") # -11 means OOM
+whitelist.add(r"('', 'out of memory\nout of memory\n', -11)")
+
+
+
+#####################################################################
+# Program
+#####################################################################
+
+# Options
+parser = OptionParser(usage=usage)
+parser.add_option("-r", "--regression", action="store", metavar="REGRESSION_COUNT", help=help,
+                  type="int", dest="regression", default=0) # TODO: support a value of zero, eventually
+                  
+(OPTIONS, args) = parser.parse_args()
+
+
+if OPTIONS.regression:
+  # TODO: This should be expanded as we get a better hang of the OOM problems.
+  # For now, we'll just check that the number of OOMs in one short file does not
+  # increase.
+  files = ["../jit-test/tests/arguments/args-createontrace.js"]
+else:
+  files = get_js_files()
+
+  # Use a command-line arg to reduce the set of files
+  if len (args):
+    files = [f for f in files if f.find(args[0]) != -1]
+
+
+if OPTIONS.regression:
+  # Don't use a logfile, this is automated for tinderbox.
+  log = file("../OOM_log", "w")
+
+
+num_failures = 0
+for f in files:
+
+  # Run it once to establish boundaries
+  command = (command_template + ' -O') % (f)
+  out, err, exit = run(command)
+  max = re.match(".*OOM max count: (\d+).*", out, flags=re.DOTALL).groups()[0]
+  max = int(max)
+  
+  # OOMs don't recover well for the first 20 allocations or so.
+  # TODO: revisit this.
+  for i in range(20, max): 
+
+    if OPTIONS.regression == None:
+      print "Testing allocation %d/%d in %s" % (i,max,f)
+
+    command = (command_template + ' -A %d') % (f, i)
+    out, err, exit = run(command)
+
+    # Success (5 is SM's exit code for controlled errors)
+    if exit == 5 and err.find("out of memory") != -1:
+      continue
+
+    # Failure
+    else:
+
+      if OPTIONS.regression:
+        # Just count them
+        num_failures += 1
+        continue
+
+      #########################################################################
+      # The regression tests ends above. The rest of this is for running  the
+      # script manually.
+      #########################################################################
+
+      problem = str((out, err, exit))
+      if in_blacklist(problem) and problem not in whitelist:
+        add_to_blacklist(problem)
+        continue
+
+      add_to_blacklist(problem)
+
+
+      # Get valgrind output for a good stack trace
+      vcommand = "valgrind --dsymutil=yes -q --log-file=OOM_valgrind_log_file " + command
+      run(vcommand)
+      vout = file("OOM_valgrind_log_file").read()
+      vout = clean_voutput(vout)
+      sans_alloc_sites = remove_failed_allocation_backtraces(vout)
+
+      # Don't print duplicate information
+      if in_blacklist(sans_alloc_sites):
+        add_to_blacklist(sans_alloc_sites)
+        continue
+
+      add_to_blacklist(sans_alloc_sites)
+
+      log.write ("\n")
+      log.write ("\n")
+      log.write ("=========================================================================")
+      log.write ("\n")
+      log.write ("An allocation failure at\n\tallocation %d/%d in %s\n\tcauses problems (detected using bug 624094)" % (i, max, f))
+      log.write ("\n")
+      log.write ("\n")
+
+      log.write ("Command (from obj directory, using patch from bug 624094):\n  " + command)
+      log.write ("\n")
+      log.write ("\n")
+      log.write ("stdout, stderr, exitcode:\n  " + problem)
+      log.write ("\n")
+      log.write ("\n")
+
+      double_free = err.find("pointer being freed was not allocated") != -1
+      oom_detected = err.find("out of memory") != -1
+      multiple_oom_detected = err.find("out of memory\nout of memory") != -1
+      segfault_detected = exit == -11
+
+      log.write ("Diagnosis: ")
+      log.write ("\n")
+      if multiple_oom_detected:
+        log.write ("  - Multiple OOMs reported")
+        log.write ("\n")
+      if segfault_detected:
+        log.write ("  - segfault")
+        log.write ("\n")
+      if not oom_detected:
+        log.write ("  - No OOM checking")
+        log.write ("\n")
+      if double_free:
+        log.write ("  - Double free")
+        log.write ("\n")
+
+      log.write ("\n")
+
+      log.write ("Valgrind info:\n" + vout)
+      log.write ("\n")
+      log.write ("\n")
+      log.flush()
+
+  if not OPTIONS.regression == None:
+    count_lines()
+
+
+# Do the actual regression check
+if OPTIONS.regression:
+  expected_num_failures = OPTIONS.regression
+
+  if num_failures != expected_num_failures:
+
+    print "TEST-UNEXPECTED-FAIL |",
+    if num_failures > expected_num_failures:
+      print "More out-of-memory errors were found (%s) than expected (%d). This probably means an allocation site has been added without a NULL-check. If this is unavoidable, you can account for it by updating Makefile.in." % (num_failures, expected_num_failures),
+    else:
+      print "Congratulations, you have removed %d out-of-memory error(s) (%d remain)! Please account for it by updating Makefile.in." % (expected_num_failures - num_failures, num_failures),
+    sys.exit(-1)
+  else:
+    print 'TEST-PASS | find_OOM_errors | Found the expected number of OOM errors (%d)' % (expected_num_failures)
+
--- a/configure.in
+++ b/configure.in
@@ -1165,16 +1165,38 @@ tools are selected during the Xcode/Deve
 
   if test "$result" = "no" ; then
     AC_MSG_ERROR([The selected compiler and Mac OS X SDK are incompatible.])
   fi
 fi
 
 fi # COMPILE_ENVIRONMENT
 
+dnl clang prior to 2.9 (including Xcode 4) does not support all the
+dnl constructs required by the libtheora inline asm. This is used to
+dnl detect and disable it
+AC_LANG_SAVE
+AC_LANG_C
+AC_TRY_COMPILE([
+#if defined(__clang__)
+# if __clang_major__<2 || (__clang_major__==2 && __clang_minor__<9)
+#  error "clang older than 2.9 detected"
+# endif
+#endif
+               ],
+               [],
+               result="yes",
+               result="no")
+if test "$result" = "no"; then
+    AC_DEFINE(HAVE_OLD_CLANG)
+    HAVE_OLD_CLANG=1
+fi
+AC_LANG_RESTORE
+AC_SUBST(HAVE_OLD_CLANG)
+
 if test -n "$MAKE"; then
   if test `echo $MAKE | grep -c make.py` != 1; then
      NOT_PYMAKE=$MAKE
   fi
 fi
 
 case "$host_os" in
 mingw*)
@@ -4947,16 +4969,21 @@ MOZ_MEDIA=
 MOZ_WEBM=1
 VPX_AS=
 VPX_ASFLAGS=
 VPX_AS_DASH_C_FLAG=
 VPX_AS_CONVERSION=
 VPX_ASM_SUFFIX=
 VPX_X86_ASM=
 VPX_ARM_ASM=
+MOZ_LIBJPEG_TURBO=1
+LIBJPEG_TURBO_AS=
+LIBJPEG_TURBO_ASFLAGS=
+LIBJPEG_TURBO_X86_ASM=
+LIBJPEG_TURBO_X64_ASM=
 MOZ_PANGO=1
 MOZ_PERMISSIONS=1
 MOZ_PLACES=1
 MOZ_PLUGINS=1
 MOZ_PREF_EXTENSIONS=1
 MOZ_PROFILELOCKING=1
 MOZ_PSM=1
 MOZ_RDF=1
@@ -6418,16 +6445,95 @@ MOZ_ARG_WITH_STRING(crashreporter-enable
     MOZ_CRASHREPORTER_ENABLE_PERCENT="$val"])
 
 if test -z "$MOZ_CRASHREPORTER_ENABLE_PERCENT"; then
    MOZ_CRASHREPORTER_ENABLE_PERCENT=100
 fi
 AC_DEFINE_UNQUOTED(MOZ_CRASHREPORTER_ENABLE_PERCENT, $MOZ_CRASHREPORTER_ENABLE_PERCENT)
 
 dnl ========================================================
+dnl = libjpeg-turbo configuration
+dnl ========================================================
+
+MOZ_ARG_DISABLE_BOOL(libjpeg_turbo,
+[ --disable-libjpeg-turbo  Disable optimized jpeg decoding routines],
+    MOZ_LIBJPEG_TURBO=,
+    MOZ_LIBJPEG_TURBO=1)
+
+dnl Detect if we can use yasm to compile libjpeg-turbo's optimized assembly
+dnl files.
+
+if test -n "$MOZ_LIBJPEG_TURBO"; then
+
+  dnl Do we support libjpeg-turbo on this platform?
+  case "$OS_ARCH:$OS_TEST" in
+  Linux:x86|Linux:i?86)
+    LIBJPEG_TURBO_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC -DELF"
+    LIBJPEG_TURBO_X86_ASM=1
+  ;;
+  Linux:x86_64)
+    LIBJPEG_TURBO_ASFLAGS="-f elf64 -rnasm -pnasm -D__x86_64__ -DPIC -DELF"
+    LIBJPEG_TURBO_X64_ASM=1
+  ;;
+  SunOS:i?86)
+    LIBJPEG_TURBO_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC -DELF"
+    LIBJPEG_TURBO_X86_ASM=1
+  ;;
+  SunOS:x86_64)
+    LIBJPEG_TURBO_ASFLAGS="-f elf64 -rnasm -pnasm -D__x86_64__ -DPIC -DELF"
+    LIBJPEG_TURBO_X64_ASM=1
+  ;;
+  Darwin:i?86)
+    LIBJPEG_TURBO_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC -DMACHO"
+    LIBJPEG_TURBO_X86_ASM=1
+  ;;
+  Darwin:x86_64)
+    LIBJPEG_TURBO_ASFLAGS="-f macho64 -rnasm -pnasm -D__x86_64__ -DPIC -DMACHO"
+    LIBJPEG_TURBO_X64_ASM=1
+  ;;
+  WINNT:x86|WINNT:i?86)
+    LIBJPEG_TURBO_ASFLAGS="-f win32 -rnasm -pnasm -DPIC -DWIN32"
+    LIBJPEG_TURBO_X86_ASM=1
+  ;;
+  WINNT:x86_64)
+    LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64"
+    LIBJPEG_TURBO_X64_ASM=1
+  ;;
+  esac
+
+fi
+
+dnl If we're on a system which supports libjpeg-turbo's asm routines and
+dnl --disable-libjpeg-turbo wasn't passed, check for yasm, and error out if it
+dnl doesn't exist or we have too old of a version.
+if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
+    AC_MSG_CHECKING([for YASM assembler])
+    AC_CHECK_PROGS(LIBJPEG_TURBO_AS, yasm, "")
+
+    if test -z "$LIBJPEG_TURBO_AS" ; then
+        AC_MSG_ERROR([yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have yasm installed.  Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+    fi
+
+    dnl Check for yasm 1.1 or greater.
+    if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then
+        AC_MSG_ERROR([yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+    fi
+fi
+
+if test -n "$LIBJPEG_TURBO_X86_ASM"; then
+    AC_DEFINE(LIBJPEG_TURBO_X86_ASM)
+elif test -n "$LIBJPEG_TURBO_X64_ASM"; then
+    AC_DEFINE(LIBJPEG_TURBO_X64_ASM)
+elif test -n "$MOZ_LIBJPEG_TURBO"; then
+    dnl Warn if we're not building the optimized routines, even though the user
+    dnl didn't specify --disable-libjpeg-turbo.
+    AC_MSG_WARN([No assembler or assembly support for libjpeg-turbo.  Using unoptimized C routines.])
+fi
+
+dnl ========================================================
 dnl = Enable compilation of specific extension modules
 dnl ========================================================
 
 MOZ_ARG_ENABLE_STRING(extensions,
 [  --enable-extensions     Enable extensions],
 [ for option in `echo $enableval | sed 's/,/ /g'`; do
     if test "$option" = "yes" -o "$option" = "all"; then
         AC_MSG_ERROR([--enable-extensions=$option is no longer supported.])
@@ -9185,16 +9291,20 @@ AC_SUBST(MOZ_OGG)
 AC_SUBST(MOZ_ALSA_LIBS)
 AC_SUBST(VPX_AS)
 AC_SUBST(VPX_ASFLAGS)
 AC_SUBST(VPX_DASH_C_FLAG)
 AC_SUBST(VPX_AS_CONVERSION)
 AC_SUBST(VPX_ASM_SUFFIX)
 AC_SUBST(VPX_X86_ASM)
 AC_SUBST(VPX_ARM_ASM)
+AC_SUBST(LIBJPEG_TURBO_AS)
+AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
+AC_SUBST(LIBJPEG_TURBO_X86_ASM)
+AC_SUBST(LIBJPEG_TURBO_X64_ASM)
 
 if test "$USING_HCC"; then
    CC='${topsrcdir}/build/hcc'
    CC="$CC '$_OLDCC'"
    CXX='${topsrcdir}/build/hcpp'
    CXX="$CXX '$_OLDCXX'"
    AC_SUBST(CC)
    AC_SUBST(CXX)
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -540,17 +540,17 @@ public:
    * @param aCharset the name of the charset; if empty, we assume UTF8
    */
   static nsresult ConvertStringFromCharset(const nsACString& aCharset,
                                            const nsACString& aInput,
                                            nsAString& aOutput);
 
   /**
    * Determine whether a buffer begins with a BOM for UTF-8, UTF-16LE,
-   * UTF-16BE, UTF-32LE, UTF-32BE.
+   * UTF-16BE
    *
    * @param aBuffer the buffer to check
    * @param aLength the length of the buffer
    * @param aCharset empty if not found
    * @return boolean indicating whether a BOM was detected.
    */
   static PRBool CheckForBOM(const unsigned char* aBuffer, PRUint32 aLength,
                             nsACString& aCharset, PRBool *bigEndian = nsnull);
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -71,18 +71,18 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID       \
-{ 0x8331ca9f, 0x8717, 0x4ab4, \
-  { 0xad, 0x17, 0xb4, 0x9d, 0xdc, 0xe8, 0xb6, 0x77 } }
+{ 0x5788c9eb, 0x646a, 0x4285, \
+  { 0xa2, 0x8c, 0xde, 0x0d, 0x43, 0x6b, 0x47, 0x72 } }
 
 /**
  * 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
@@ -901,25 +901,25 @@ public:
   /*
    * Returns a new nsISMILAttr that allows the caller to animate the given
    * attribute on this element.
    *
    * The CALLER OWNS the result and is responsible for deleting it.
    */
   virtual nsISMILAttr* GetAnimatedAttr(PRInt32 aNamespaceID, nsIAtom* aName) = 0;
 
-   /**
-    * Get the SMIL override style for this content node.  This is a style
-    * declaration that is applied *after* the inline style, and it can be used
-    * e.g. to store animated style values.
-    *
-    * Note: This method is analogous to the 'GetStyle' method in
-    * nsGenericHTMLElement and nsStyledElement.
-    */
-  virtual nsresult GetSMILOverrideStyle(nsIDOMCSSStyleDeclaration** aStyle) = 0;
+  /**
+   * Get the SMIL override style for this content node.  This is a style
+   * declaration that is applied *after* the inline style, and it can be used
+   * e.g. to store animated style values.
+   *
+   * Note: This method is analogous to the 'GetStyle' method in
+   * nsGenericHTMLElement and nsStyledElement.
+   */
+  virtual nsIDOMCSSStyleDeclaration* GetSMILOverrideStyle() = 0;
 
   /**
    * Get the SMIL override style rule for this content node.  If the rule
    * hasn't been created (or if this nsIContent object doesn't support SMIL
    * override style), this method simply returns null.
    */
   virtual mozilla::css::StyleRule* GetSMILOverrideStyleRule() = 0;
 
--- a/content/base/public/nsIContentSerializer.h
+++ b/content/base/public/nsIContentSerializer.h
@@ -30,26 +30,30 @@
  * 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 _nsIContentSerializer_h__
-#define _nsIContentSerializer_h__
+#ifndef nsIContentSerializer_h
+#define nsIContentSerializer_h
 
 #include "nsISupports.h"
 
 class nsIContent;
 class nsIDocument;
 class nsAString;
 
-/* starting interface:    nsIContentSerializer */
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
 
 #define NS_ICONTENTSERIALIZER_IID \
 { 0xb1ee32f2, 0xb8c4, 0x49b9, \
   { 0x93, 0xdf, 0xb6, 0xfa, 0xb5, 0xd5, 0x46, 0x88 } }
 
 class nsIContentSerializer : public nsISupports {
  public: 
 
@@ -72,21 +76,21 @@ class nsIContentSerializer : public nsIS
                                          nsAString& aStr) = 0;
 
   NS_IMETHOD AppendComment(nsIContent* aComment, PRInt32 aStartOffset,
                            PRInt32 aEndOffset, nsAString& aStr) = 0;
 
   NS_IMETHOD AppendDoctype(nsIContent *aDoctype,
                            nsAString& aStr) = 0;
 
-  NS_IMETHOD AppendElementStart(nsIContent *aElement,
-                                nsIContent *aOriginalElement,
+  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
+                                mozilla::dom::Element* aOriginalElement,
                                 nsAString& aStr) = 0;
 
-  NS_IMETHOD AppendElementEnd(nsIContent *aElement,
+  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
                               nsAString& aStr) = 0;
 
   NS_IMETHOD Flush(nsAString& aStr) = 0;
 
   /**
    * Append any items in the beginning of the document that won't be 
    * serialized by other methods. XML declaration is the most likely 
    * thing this method can produce.
@@ -95,9 +99,9 @@ class nsIContentSerializer : public nsIS
                                  nsAString& aStr) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentSerializer, NS_ICONTENTSERIALIZER_IID)
 
 #define NS_CONTENTSERIALIZER_CONTRACTID_PREFIX \
 "@mozilla.org/layout/contentserializer;1?mimetype="
 
-#endif /* __gen_nsIContentSerializer_h__ */
+#endif /* nsIContentSerializer_h */
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -118,18 +118,18 @@ class Loader;
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 
 #define NS_IDOCUMENT_IID      \
-{ 0xc38a7935, 0xc854, 0x4df7, \
-  { 0x8f, 0xd4, 0xa2, 0x6f, 0x0d, 0x27, 0x9f, 0x31 } }
+{ 0x2c6ad63f, 0xb7b9, 0x42f8, \
+ { 0xbd, 0xde, 0x76, 0x0a, 0x83, 0xe3, 0xb0, 0x49 } }
 
 // 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              NS_DEFINE_EVENT_STATE_MACRO(0)
@@ -752,21 +752,19 @@ public:
   virtual void EndUpdate(nsUpdateType aUpdateType) = 0;
   virtual void BeginLoad() = 0;
   virtual void EndLoad() = 0;
 
   enum ReadyState { READYSTATE_UNINITIALIZED = 0, READYSTATE_LOADING = 1, READYSTATE_INTERACTIVE = 3, READYSTATE_COMPLETE = 4};
   virtual void SetReadyStateInternal(ReadyState rs) = 0;
   virtual ReadyState GetReadyStateEnum() = 0;
 
-  // notify that one or two content nodes changed state
-  // either may be nsnull, but not both
-  virtual void ContentStatesChanged(nsIContent* aContent1,
-                                    nsIContent* aContent2,
-                                    nsEventStates aStateMask) = 0;
+  // notify that a content node changed state
+  virtual void ContentStateChanged(nsIContent* aContent,
+                                   nsEventStates aStateMask) = 0;
 
   // Notify that a document state has changed.
   // This should only be called by callers whose state is also reflected in the
   // implementation of nsDocument::GetDocumentState.
   virtual void DocumentStatesChanged(nsEventStates aStateMask) = 0;
 
   // Observation hooks for style data to propagate notifications
   // to document observers
--- a/content/base/public/nsIDocumentObserver.h
+++ b/content/base/public/nsIDocumentObserver.h
@@ -44,18 +44,18 @@
 class nsIAtom;
 class nsIContent;
 class nsIStyleSheet;
 class nsIStyleRule;
 class nsString;
 class nsIDocument;
 
 #define NS_IDOCUMENT_OBSERVER_IID \
-{ 0x3d005225, 0x210f, 0x4b07, \
-  { 0xb1, 0xd9, 0x96, 0x02, 0x05, 0x74, 0xc4, 0x37 } }
+{ 0x900bc4bc, 0x8b6c, 0x4cba, \
+ { 0x82, 0xfa, 0x56, 0x8a, 0x80, 0xff, 0xfd, 0x3e } }
 
 typedef PRUint32 nsUpdateType;
 
 #define UPDATE_CONTENT_MODEL 0x00000001
 #define UPDATE_STYLE         0x00000002
 #define UPDATE_CONTENT_STATE 0x00000004
 #define UPDATE_ALL (UPDATE_CONTENT_MODEL | UPDATE_STYLE | UPDATE_CONTENT_STATE)
 
@@ -98,30 +98,22 @@ public:
    * no need to invoke this method directly).  The notification 
    * is passed to any IDocumentObservers. The notification is 
    * passed on to all of the document observers. <p>
    *
    * This notification is not sent when a piece of content is
    * added/removed from the document or the content itself changed 
    * (the other notifications are used for that).
    *
-   * The optional second content node is to allow optimization
-   * of the case where state moves from one node to another
-   * (as is likely for :focus and :hover)
-   *
-   * Either content node may be nsnull, but not both
-   *
    * @param aDocument The document being observed
-   * @param aContent1 the piece of content that changed
-   * @param aContent2 optional second piece of content that changed
+   * @param aContent the piece of content that changed
    */
-  virtual void ContentStatesChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent1,
-                                    nsIContent* aContent2,
-                                    nsEventStates aStateMask) = 0;
+  virtual void ContentStateChanged(nsIDocument* aDocument,
+                                   nsIContent* aContent,
+                                   nsEventStates aStateMask) = 0;
 
   /**
    * Notification that the state of the document has changed.
    *
    * @param aDocument The document being observed
    * @param aStateMask the state that changed
    */
   virtual void DocumentStatesChanged(nsIDocument* aDocument,
@@ -242,21 +234,20 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumen
     virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType);
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD                                \
     virtual void BeginLoad(nsIDocument* aDocument);
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD                                  \
     virtual void EndLoad(nsIDocument* aDocument);
 
-#define NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATESCHANGED                     \
-    virtual void ContentStatesChanged(nsIDocument* aDocument,                \
-                                      nsIContent* aContent1,                 \
-                                      nsIContent* aContent2,                 \
-                                      nsEventStates aStateMask);
+#define NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED                      \
+    virtual void ContentStateChanged(nsIDocument* aDocument,                 \
+                                     nsIContent* aContent,                   \
+                                     nsEventStates aStateMask);
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED                    \
     virtual void DocumentStatesChanged(nsIDocument* aDocument,               \
                                        nsEventStates aStateMask);
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED                          \
     virtual void StyleSheetAdded(nsIDocument* aDocument,                     \
                                  nsIStyleSheet* aStyleSheet,                 \
@@ -288,17 +279,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumen
                                   nsIStyleSheet* aStyleSheet,                \
                                   nsIStyleRule* aStyleRule);
 
 #define NS_DECL_NSIDOCUMENTOBSERVER                                          \
     NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE                                  \
     NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE                                    \
     NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD                                    \
     NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD                                      \
-    NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATESCHANGED                         \
+    NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED                          \
     NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED                        \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED                              \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED                            \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED             \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED                             \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED                               \
     NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED                             \
     NS_DECL_NSIMUTATIONOBSERVER
@@ -322,19 +313,18 @@ void                                    
 }                                                                         \
 void                                                                      \
 _class::EndLoad(nsIDocument* aDocument)                                   \
 {                                                                         \
 }
 
 #define NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(_class)                    \
 void                                                                      \
-_class::ContentStatesChanged(nsIDocument* aDocument,                      \
-                             nsIContent* aContent1,                       \
-                             nsIContent* aContent2,                       \
+_class::ContentStateChanged(nsIDocument* aDocument,                       \
+                             nsIContent* aContent,                        \
                              nsEventStates aStateMask)                    \
 {                                                                         \
 }                                                                         \
                                                                           \
 void                                                                      \
 _class::DocumentStatesChanged(nsIDocument* aDocument,                     \
                               nsEventStates aStateMask)                   \
 {                                                                         \
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -104,17 +104,17 @@ interface nsIXMLHttpRequestUpload : nsIX
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
-[scriptable, uuid(6bb91106-85f0-4d93-8cb4-e57b3d0624f2)]
+[scriptable, uuid(af62a870-820c-4981-96a3-28ab17b779e1)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
    * The request uses a channel in order to perform the
    * request.  This attribute represents the channel used
    * for the request.  NULL if the channel has not yet been
    * created.
    *
@@ -182,52 +182,29 @@ interface nsIXMLHttpRequest : nsISupport
    *
    * @param header The name of the header to retrieve
    * @returns A string containing the text of the header specified.
    *          NULL if the response has not yet been received or the
    *          header does not exist in the response.
    */
   ACString getResponseHeader(in AUTF8String header);
 
-  /**
-   * Native (non-script) method to initialize a request. Note that
-   * the request is not sent until the <code>send</code> method
-   * is invoked.
-   *
-   * If there is an "active" request (that is, if open() or openRequest() has
-   * been called already), this is equivalent to calling abort().
-   *
-   * @param method The HTTP method, for example "POST" or "GET". Ignored
-   *               if the URL is not a HTTP(S) URL.
-   * @param url The URL to which to send the request.
-   * @param async Whether the request is synchronous or asynchronous
-   *              i.e. whether send returns only after the response
-   *              is received or if it returns immediately after
-   *              sending the request. In the latter case, notification
-   *              of completion is sent through the event listeners.
-   *              This argument must be true if the multipart
-   *              attribute has been set to true, or an exception will
-   *              be thrown.
-   * @param user A username for authentication if necessary.
-   * @param password A password for authentication if necessary.
-   */
-  [noscript] void   openRequest(in AUTF8String method,
-                                in AUTF8String url,
-                                in boolean async,
-                                in AString user,
-                                in AString password);
-
+%{C++
+  // note this is NOT virtual so this won't muck with the vtable!
+  inline nsresult Open(const nsACString& method, const nsACString& url,
+                       PRBool async, const nsAString& user,
+                       const nsAString& password) {
+    return Open(method, url, async, user, password, 3);
+  }
+%}
   /**
    * Meant to be a script-only method for initializing a request.
-   * The parameters are similar to the ones detailed in the
-   * description of <code>openRequest</code>, but the last
-   * 3 are optional.
    *
-   * If there is an "active" request (that is, if open() or openRequest() has
-   * been called already), this is equivalent to calling abort().
+   * If there is an "active" request (that is, if open() has been called
+   * already), this is equivalent to calling abort() and then open().
    *
    * @param method The HTTP method - either "POST" or "GET". Ignored
    *               if the URL is not a HTTP URL.
    * @param url The URL to which to send the request.
    * @param async (optional) Whether the request is synchronous or
    *              asynchronous i.e. whether send returns only after
    *              the response is received or if it returns immediately after
    *              sending the request. In the latter case, notification
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -97,17 +97,17 @@ Link::SetLinkState(nsLinkState aState)
   nsIContent *content = Content();
   nsIDocument *doc = content->GetCurrentDoc();
   NS_ASSERTION(doc, "Registered but we have no document?!");
   nsEventStates newLinkState = LinkState();
   NS_ASSERTION(newLinkState == NS_EVENT_STATE_VISITED ||
                newLinkState == NS_EVENT_STATE_UNVISITED,
                "Unexpected state obtained from LinkState()!");
   mozAutoDocUpdate update(doc, UPDATE_CONTENT_STATE, PR_TRUE);
-  doc->ContentStatesChanged(content, nsnull, oldLinkState ^ newLinkState);
+  doc->ContentStateChanged(content, oldLinkState ^ newLinkState);
 }
 
 nsEventStates
 Link::LinkState() const
 {
   // We are a constant method, but we are just lazily doing things and have to
   // track that state.  Cast away that constness!
   Link *self = const_cast<Link *>(this);
@@ -488,17 +488,17 @@ Link::ResetLinkState(bool aNotify)
   // If aNotify is true, notify both of the visited-related states.  We have
   // to do that, because we might be racing with a response from history and
   // hence need to make sure that we get restyled whether we were visited or
   // not before.  In particular, we need to make sure that our LinkState() is
   // called so that we'll start a new history query as needed.
   if (aNotify && doc) {
     nsEventStates changedState = NS_EVENT_STATE_VISITED ^ NS_EVENT_STATE_UNVISITED;
     MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, aNotify);
-    doc->ContentStatesChanged(content, nsnull, changedState);
+    doc->ContentStateChanged(content, changedState);
   }
 }
 
 void
 Link::UnregisterFromHistory()
 {
   // If we are not registered, we have nothing to do.
   if (!mRegistered) {
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -146,16 +146,30 @@ CPPSRCS		= \
 		nsXMLNameSpaceMap.cpp \
 		Link.cpp \
 		nsFileDataProtocolHandler.cpp \
 		nsFrameMessageManager.cpp \
 		nsInProcessTabChildGlobal.cpp \
 		ThirdPartyUtil.cpp \
 		$(NULL)
 
+# Are we targeting x86-32 or x86-64?  If so, we want to include SSE2 code for
+# nsTextFragment.cpp
+ifneq (,$(INTEL_ARCHITECTURE))
+
+CPPSRCS += nsTextFragmentSSE2.cpp
+
+# gcc requires -msse2 for this file since it uses SSE2 intrinsics.  (See bug
+# 585538 comment 12.)
+ifdef GNU_CC
+nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
+endif
+
+endif
+
 GQI_SRCS = contentbase.gqi
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
 EXTRA_COMPONENTS = \
 		$(srcdir)/nsBadCertHandler.js \
--- a/content/base/src/mozSanitizingSerializer.cpp
+++ b/content/base/src/mozSanitizingSerializer.cpp
@@ -58,18 +58,19 @@
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "plstr.h"
 #include "nsIProperties.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsEscape.h"
+#include "mozilla/dom/Element.h"
 
-//#define DEBUG_BenB
+using namespace mozilla::dom;
 
 static inline PRUnichar* escape(const nsString& source)
 {
   return nsEscapeHTML2(source.get(), source.Length()); 
 }
 
 /* XXX: |printf|s in some error conditions. They are intended as information
    for the user, because they complain about malformed pref values.
@@ -236,18 +237,18 @@ mozSanitizingHTMLSerializer::AppendText(
 
   nsAutoString linebuffer;
   rv = DoAddLeaf(eHTMLTag_text, linebuffer);
 
   return rv;
 }
 
 NS_IMETHODIMP 
-mozSanitizingHTMLSerializer::AppendElementStart(nsIContent *aElement,
-                                                nsIContent *aOriginalElement,
+mozSanitizingHTMLSerializer::AppendElementStart(Element* aElement,
+                                                Element* aOriginalElement,
                                                 nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   mContent = aElement;
 
   mOutputString = &aStr;
 
@@ -265,17 +266,17 @@ mozSanitizingHTMLSerializer::AppendEleme
 
   mContent = 0;
   mOutputString = nsnull;
 
   return rv;
 } 
  
 NS_IMETHODIMP 
-mozSanitizingHTMLSerializer::AppendElementEnd(nsIContent *aElement,
+mozSanitizingHTMLSerializer::AppendElementEnd(Element* aElement,
                                               nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   mContent = aElement;
 
   mOutputString = &aStr;
 
--- a/content/base/src/mozSanitizingSerializer.h
+++ b/content/base/src/mozSanitizingSerializer.h
@@ -84,20 +84,21 @@ public:
                                          PRInt32 aEndOffset,
                                          nsAString& aStr)
                       { return NS_OK; }
   NS_IMETHOD AppendComment(nsIContent* aComment, PRInt32 aStartOffset,
                            PRInt32 aEndOffset, nsAString& aStr)
                       { return NS_OK; }
   NS_IMETHOD AppendDoctype(nsIContent *aDoctype, nsAString& aStr)
                       { return NS_OK; }
-  NS_IMETHOD AppendElementStart(nsIContent *aElement,
-                                nsIContent *aOriginalElement,
-                                nsAString& aStr); 
-  NS_IMETHOD AppendElementEnd(nsIContent *aElement, nsAString& aStr);
+  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
+                                mozilla::dom::Element* aOriginalElement,
+                                nsAString& aStr);
+  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
+                              nsAString& aStr);
   NS_IMETHOD Flush(nsAString& aStr);
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr);
 
   // nsIContentSink
   NS_IMETHOD WillParse(void) { return NS_OK; }
   NS_IMETHOD WillInterrupt(void) { return NS_OK; }
@@ -145,17 +146,17 @@ protected:
   nsresult DoAddLeaf(PRInt32 aTag, const nsAString& aText);
   void Write(const nsAString& aString);
 
 protected:
   PRInt32                      mFlags;
   PRUint32                     mSkipLevel;
   nsHashtable                  mAllowedTags;
 
-  nsCOMPtr<nsIContent>         mContent;
+  nsRefPtr<mozilla::dom::Element> mContent;
   nsAString*                   mOutputString;
   nsIParserNode*               mParserNode;
   nsCOMPtr<nsIParserService>   mParserService;
 };
 
 nsresult
 NS_NewSanitizingHTMLSerializer(nsIContentSerializer** aSerializer);
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -443,16 +443,24 @@ nsContentList::nsContentList(nsINode* aR
     mData(aData),
     mState(LIST_DIRTY),
     mMatchAll(PR_FALSE),
     mDeep(aDeep),
     mFuncMayDependOnAttr(aFuncMayDependOnAttr)
 {
   NS_ASSERTION(mRootNode, "Must have root");
   mRootNode->AddMutationObserver(this);
+
+  // We only need to flush if we're in an non-HTML document, since the
+  // HTML5 parser doesn't need flushing.  Further, if we're not in a
+  // document at all right now (in the GetCurrentDoc() sense), we're
+  // not parser-created and don't need to be flushing stuff under us
+  // to get our kids right.
+  nsIDocument* doc = mRootNode->GetCurrentDoc();
+  mFlushesNeeded = doc && !doc->IsHTML();
 }
 
 nsContentList::~nsContentList()
 {
   RemoveFromHashtable();
   if (mRootNode) {
     mRootNode->RemoveMutationObserver(this);
   }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3529,34 +3529,16 @@ nsContentUtils::CheckForBOM(const unsign
   PRBool found = PR_TRUE;
   aCharset.Truncate();
   if (aLength >= 3 &&
       aBuffer[0] == 0xEF &&
       aBuffer[1] == 0xBB &&
       aBuffer[2] == 0xBF) {
     aCharset = "UTF-8";
   }
-  else if (aLength >= 4 &&
-           aBuffer[0] == 0x00 &&
-           aBuffer[1] == 0x00 &&
-           aBuffer[2] == 0xFE &&
-           aBuffer[3] == 0xFF) {
-    aCharset = "UTF-32";
-    if (bigEndian)
-      *bigEndian = PR_TRUE;
-  }
-  else if (aLength >= 4 &&
-           aBuffer[0] == 0xFF &&
-           aBuffer[1] == 0xFE &&
-           aBuffer[2] == 0x00 &&
-           aBuffer[3] == 0x00) {
-    aCharset = "UTF-32";
-    if (bigEndian)
-      *bigEndian = PR_FALSE;
-  }
   else if (aLength >= 2 &&
            aBuffer[0] == 0xFE && aBuffer[1] == 0xFF) {
     aCharset = "UTF-16";
     if (bigEndian)
       *bigEndian = PR_TRUE;
   }
   else if (aLength >= 2 &&
            aBuffer[0] == 0xFF && aBuffer[1] == 0xFE) {
@@ -6381,18 +6363,18 @@ LayerManagerForDocumentInternal(nsIDocum
       docShellTreeItem->GetParent(getter_AddRefs(parent));
       docShellTreeItem = parent;
     }
   }
 
   if (shell) {
     nsIViewManager* VM = shell->GetViewManager();
     if (VM) {
-      nsIView* rootView = nsnull;
-      if (NS_SUCCEEDED(VM->GetRootView(rootView)) && rootView) {
+      nsIView* rootView = VM->GetRootView();
+      if (rootView) {
         nsIView* displayRoot = GetDisplayRootFor(rootView);
         if (displayRoot) {
           nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
           if (widget) {
             nsRefPtr<LayerManager> manager =
               widget->
                 GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT : 
                                                      nsIWidget::LAYER_MANAGER_CURRENT,
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -49,62 +49,347 @@
 #include "nsIStreamConverterService.h"
 #include "nsStringStream.h"
 #include "nsParserUtils.h"
 #include "nsGkAtoms.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsCharSeparatedTokenizer.h"
-#include "nsXMLHttpRequest.h"
 #include "nsAsyncRedirectVerifyHelper.h"
+#include "prclist.h"
+#include "prtime.h"
+#include "nsClassHashtable.h"
+#include "nsHashKeys.h"
+
+#define PREFLIGHT_CACHE_SIZE 100
 
 static PRBool gDisableCORS = PR_FALSE;
 static PRBool gDisableCORSPrivateData = PR_FALSE;
 
-class nsChannelCanceller
+//////////////////////////////////////////////////////////////////////////
+// Preflight cache
+
+class nsPreflightCache
 {
 public:
-  nsChannelCanceller(nsIChannel* aChannel)
-    : mChannel(aChannel)
+  struct TokenTime
+  {
+    nsCString token;
+    PRTime expirationTime;
+  };
+
+  struct CacheEntry : public PRCList
   {
+    CacheEntry(nsCString& aKey)
+      : mKey(aKey)
+    {
+      MOZ_COUNT_CTOR(nsPreflightCache::CacheEntry);
+    }
+    
+    ~CacheEntry()
+    {
+      MOZ_COUNT_DTOR(nsPreflightCache::CacheEntry);
+    }
+
+    void PurgeExpired(PRTime now);
+    PRBool CheckRequest(const nsCString& aMethod,
+                        const nsTArray<nsCString>& aCustomHeaders);
+
+    nsCString mKey;
+    nsTArray<TokenTime> mMethods;
+    nsTArray<TokenTime> mHeaders;
+  };
+
+  nsPreflightCache()
+  {
+    MOZ_COUNT_CTOR(nsPreflightCache);
+    PR_INIT_CLIST(&mList);
+  }
+
+  ~nsPreflightCache()
+  {
+    Clear();
+    MOZ_COUNT_DTOR(nsPreflightCache);
+  }
+
+  PRBool Initialize()
+  {
+    return mTable.Init();
   }
-  ~nsChannelCanceller()
-  {
-    if (mChannel) {
-      mChannel->Cancel(NS_ERROR_DOM_BAD_URI);
+
+  CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                       PRBool aWithCredentials, PRBool aCreate);
+  void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal);
+
+  void Clear();
+
+private:
+  static PLDHashOperator
+    RemoveExpiredEntries(const nsACString& aKey, nsAutoPtr<CacheEntry>& aValue,
+                         void* aUserData);
+
+  static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                            PRBool aWithCredentials, nsACString& _retval);
+
+  nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
+  PRCList mList;
+};
+
+// Will be initialized in EnsurePreflightCache.
+static nsPreflightCache* sPreflightCache = nsnull;
+
+static PRBool EnsurePreflightCache()
+{
+  if (sPreflightCache)
+    return PR_TRUE;
+
+  nsAutoPtr<nsPreflightCache> newCache(new nsPreflightCache());
+
+  if (newCache->Initialize()) {
+    sPreflightCache = newCache.forget();
+    return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
+void
+nsPreflightCache::CacheEntry::PurgeExpired(PRTime now)
+{
+  PRUint32 i;
+  for (i = 0; i < mMethods.Length(); ++i) {
+    if (now >= mMethods[i].expirationTime) {
+      mMethods.RemoveElementAt(i--);
+    }
+  }
+  for (i = 0; i < mHeaders.Length(); ++i) {
+    if (now >= mHeaders[i].expirationTime) {
+      mHeaders.RemoveElementAt(i--);
+    }
+  }
+}
+
+PRBool
+nsPreflightCache::CacheEntry::CheckRequest(const nsCString& aMethod,
+                                           const nsTArray<nsCString>& aHeaders)
+{
+  PurgeExpired(PR_Now());
+
+  if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
+    PRUint32 i;
+    for (i = 0; i < mMethods.Length(); ++i) {
+      if (aMethod.Equals(mMethods[i].token))
+        break;
+    }
+    if (i == mMethods.Length()) {
+      return PR_FALSE;
+    }
+  }
+
+  for (PRUint32 i = 0; i < aHeaders.Length(); ++i) {
+    PRUint32 j;
+    for (j = 0; j < mHeaders.Length(); ++j) {
+      if (aHeaders[i].Equals(mHeaders[j].token,
+                             nsCaseInsensitiveCStringComparator())) {
+        break;
+      }
+    }
+    if (j == mHeaders.Length()) {
+      return PR_FALSE;
     }
   }
 
-  void DontCancel()
-  {
-    mChannel = nsnull;
+  return PR_TRUE;
+}
+
+nsPreflightCache::CacheEntry*
+nsPreflightCache::GetEntry(nsIURI* aURI,
+                           nsIPrincipal* aPrincipal,
+                           PRBool aWithCredentials,
+                           PRBool aCreate)
+{
+  nsCString key;
+  if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
+    NS_WARNING("Invalid cache key!");
+    return nsnull;
+  }
+
+  CacheEntry* entry;
+
+  if (mTable.Get(key, &entry)) {
+    // Entry already existed so just return it. Also update the LRU list.
+
+    // Move to the head of the list.
+    PR_REMOVE_LINK(entry);
+    PR_INSERT_LINK(entry, &mList);
+
+    return entry;
+  }
+
+  if (!aCreate) {
+    return nsnull;
+  }
+
+  // This is a new entry, allocate and insert into the table now so that any
+  // failures don't cause items to be removed from a full cache.
+  entry = new CacheEntry(key);
+  if (!entry) {
+    NS_WARNING("Failed to allocate new cache entry!");
+    return nsnull;
+  }
+
+  NS_ASSERTION(mTable.Count() <= PREFLIGHT_CACHE_SIZE,
+               "Something is borked, too many entries in the cache!");
+
+  // Now enforce the max count.
+  if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
+    // Try to kick out all the expired entries.
+    PRTime now = PR_Now();
+    mTable.Enumerate(RemoveExpiredEntries, &now);
+
+    // If that didn't remove anything then kick out the least recently used
+    // entry.
+    if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
+      CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList));
+      PR_REMOVE_LINK(lruEntry);
+
+      // This will delete 'lruEntry'.
+      mTable.Remove(lruEntry->mKey);
+
+      NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1,
+                   "Somehow tried to remove an entry that was never added!");
+    }
+  }
+  
+  if (!mTable.Put(key, entry)) {
+    // Failed, clean up the new entry.
+    delete entry;
+
+    NS_WARNING("Failed to add entry to the CORS preflight cache!");
+    return nsnull;
   }
 
-private:
-  nsIChannel* mChannel;
-};
+  PR_INSERT_LINK(entry, &mList);
+
+  return entry;
+}
+
+void
+nsPreflightCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
+{
+  CacheEntry* entry;
+  nsCString key;
+  if (GetCacheKey(aURI, aPrincipal, PR_TRUE, key) &&
+      mTable.Get(key, &entry)) {
+    PR_REMOVE_LINK(entry);
+    mTable.Remove(key);
+  }
+
+  if (GetCacheKey(aURI, aPrincipal, PR_FALSE, key) &&
+      mTable.Get(key, &entry)) {
+    PR_REMOVE_LINK(entry);
+    mTable.Remove(key);
+  }
+}
+
+void
+nsPreflightCache::Clear()
+{
+  PR_INIT_CLIST(&mList);
+  mTable.Clear();
+}
 
-NS_IMPL_ISUPPORTS5(nsCrossSiteListenerProxy, nsIStreamListener,
+/* static */ PLDHashOperator
+nsPreflightCache::RemoveExpiredEntries(const nsACString& aKey,
+                                           nsAutoPtr<CacheEntry>& aValue,
+                                           void* aUserData)
+{
+  PRTime* now = static_cast<PRTime*>(aUserData);
+  
+  aValue->PurgeExpired(*now);
+  
+  if (aValue->mHeaders.IsEmpty() &&
+      aValue->mMethods.IsEmpty()) {
+    // Expired, remove from the list as well as the hash table.
+    PR_REMOVE_LINK(aValue);
+    return PL_DHASH_REMOVE;
+  }
+  
+  return PL_DHASH_NEXT;
+}
+
+/* static */ PRBool
+nsPreflightCache::GetCacheKey(nsIURI* aURI,
+                              nsIPrincipal* aPrincipal,
+                              PRBool aWithCredentials,
+                              nsACString& _retval)
+{
+  NS_ASSERTION(aURI, "Null uri!");
+  NS_ASSERTION(aPrincipal, "Null principal!");
+  
+  NS_NAMED_LITERAL_CSTRING(space, " ");
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+  
+  nsCAutoString scheme, host, port;
+  if (uri) {
+    uri->GetScheme(scheme);
+    uri->GetHost(host);
+    port.AppendInt(NS_GetRealPort(uri));
+  }
+
+  nsCAutoString cred;
+  if (aWithCredentials) {
+    _retval.AssignLiteral("cred");
+  }
+  else {
+    _retval.AssignLiteral("nocred");
+  }
+
+  nsCAutoString spec;
+  rv = aURI->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  _retval.Assign(cred + space + scheme + space + host + space + port + space +
+                 spec);
+
+  return PR_TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// nsCORSListenerProxy
+
+NS_IMPL_ISUPPORTS5(nsCORSListenerProxy, nsIStreamListener,
                    nsIRequestObserver, nsIChannelEventSink,
                    nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback)
 
 /* static */
 void
-nsCrossSiteListenerProxy::Startup()
+nsCORSListenerProxy::Startup()
 {
   nsContentUtils::AddBoolPrefVarCache("content.cors.disable", &gDisableCORS);
   nsContentUtils::AddBoolPrefVarCache("content.cors.no_private_data", &gDisableCORSPrivateData);
 }
 
-nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                                                   nsIPrincipal* aRequestingPrincipal,
-                                                   nsIChannel* aChannel,
-                                                   PRBool aWithCredentials,
-                                                   nsresult* aResult)
+/* static */
+void
+nsCORSListenerProxy::Shutdown()
+{
+  delete sPreflightCache;
+  sPreflightCache = nsnull;
+}
+
+nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
+                                         nsIPrincipal* aRequestingPrincipal,
+                                         nsIChannel* aChannel,
+                                         PRBool aWithCredentials,
+                                         nsresult* aResult)
   : mOuterListener(aOuter),
     mRequestingPrincipal(aRequestingPrincipal),
     mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
     mRequestApproved(PR_FALSE),
     mHasBeenCrossSite(PR_FALSE),
     mIsPreflight(PR_FALSE)
 {
   aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
@@ -113,24 +398,23 @@ nsCrossSiteListenerProxy::nsCrossSiteLis
   *aResult = UpdateChannel(aChannel);
   if (NS_FAILED(*aResult)) {
     mOuterListener = nsnull;
     mRequestingPrincipal = nsnull;
     mOuterNotificationCallbacks = nsnull;
   }
 }
 
-
-nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                                                   nsIPrincipal* aRequestingPrincipal,
-                                                   nsIChannel* aChannel,
-                                                   PRBool aWithCredentials,
-                                                   const nsCString& aPreflightMethod,
-                                                   const nsTArray<nsCString>& aPreflightHeaders,
-                                                   nsresult* aResult)
+nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
+                                         nsIPrincipal* aRequestingPrincipal,
+                                         nsIChannel* aChannel,
+                                         PRBool aWithCredentials,
+                                         const nsCString& aPreflightMethod,
+                                         const nsTArray<nsCString>& aPreflightHeaders,
+                                         nsresult* aResult)
   : mOuterListener(aOuter),
     mRequestingPrincipal(aRequestingPrincipal),
     mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
     mRequestApproved(PR_FALSE),
     mHasBeenCrossSite(PR_FALSE),
     mIsPreflight(PR_TRUE),
     mPreflightMethod(aPreflightMethod),
     mPreflightHeaders(aPreflightHeaders)
@@ -147,29 +431,28 @@ nsCrossSiteListenerProxy::nsCrossSiteLis
   if (NS_FAILED(*aResult)) {
     mOuterListener = nsnull;
     mRequestingPrincipal = nsnull;
     mOuterNotificationCallbacks = nsnull;
   }
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
-                                         nsISupports* aContext)
+nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest,
+                                    nsISupports* aContext)
 {
   mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest));
   if (!mRequestApproved) {
-    if (nsXMLHttpRequest::sAccessControlCache) {
+    if (sPreflightCache) {
       nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
       if (channel) {
-      nsCOMPtr<nsIURI> uri;
+        nsCOMPtr<nsIURI> uri;
         NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
         if (uri) {
-          nsXMLHttpRequest::sAccessControlCache->
-            RemoveEntries(uri, mRequestingPrincipal);
+          sPreflightCache->RemoveEntries(uri, mRequestingPrincipal);
         }
       }
     }
 
     aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
     mOuterListener->OnStartRequest(aRequest, aContext);
 
     return NS_ERROR_DOM_BAD_URI;
@@ -214,17 +497,17 @@ IsValidHTTPToken(const nsCSubstring& aTo
     }
     ++iter;
   }
 
   return PR_TRUE;
 }
 
 nsresult
-nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
+nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
 {
   // Check if this was actually a cross domain request
   if (!mHasBeenCrossSite) {
     return NS_OK;
   }
 
   if (gDisableCORS) {
     return NS_ERROR_DOM_BAD_URI;
@@ -321,68 +604,67 @@ nsCrossSiteListenerProxy::CheckRequestAp
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::OnStopRequest(nsIRequest* aRequest,
-                                        nsISupports* aContext,
-                                        nsresult aStatusCode)
+nsCORSListenerProxy::OnStopRequest(nsIRequest* aRequest,
+                                   nsISupports* aContext,
+                                   nsresult aStatusCode)
 {
   return mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::OnDataAvailable(nsIRequest* aRequest,
-                                          nsISupports* aContext, 
-                                          nsIInputStream* aInputStream,
-                                          PRUint32 aOffset,
-                                          PRUint32 aCount)
+nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest,
+                                     nsISupports* aContext, 
+                                     nsIInputStream* aInputStream,
+                                     PRUint32 aOffset,
+                                     PRUint32 aCount)
 {
   if (!mRequestApproved) {
     return NS_ERROR_DOM_BAD_URI;
   }
   return mOuterListener->OnDataAvailable(aRequest, aContext, aInputStream,
                                          aOffset, aCount);
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
+nsCORSListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
 {
   if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
     *aResult = static_cast<nsIChannelEventSink*>(this);
     NS_ADDREF_THIS();
 
     return NS_OK;
   }
 
   return mOuterNotificationCallbacks ?
     mOuterNotificationCallbacks->GetInterface(aIID, aResult) :
     NS_ERROR_NO_INTERFACE;
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
-                                                 nsIChannel *aNewChannel,
-                                                 PRUint32 aFlags,
-                                                 nsIAsyncVerifyRedirectCallback *cb)
+nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
+                                            nsIChannel *aNewChannel,
+                                            PRUint32 aFlags,
+                                            nsIAsyncVerifyRedirectCallback *cb)
 {
   nsresult rv;
   if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
     rv = CheckRequestApproved(aOldChannel);
     if (NS_FAILED(rv)) {
-      if (nsXMLHttpRequest::sAccessControlCache) {
+      if (sPreflightCache) {
         nsCOMPtr<nsIURI> oldURI;
         NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
         if (oldURI) {
-          nsXMLHttpRequest::sAccessControlCache->
-            RemoveEntries(oldURI, mRequestingPrincipal);
+          sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal);
         }
       }
       aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
       return NS_ERROR_DOM_BAD_URI;
     }
   }
 
   // Prepare to receive callback
@@ -403,26 +685,26 @@ nsCrossSiteListenerProxy::AsyncOnChannel
     return rv;  
   }
 
   (void) OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsCrossSiteListenerProxy::OnRedirectVerifyCallback(nsresult result)
+nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
 {
   NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
   NS_ASSERTION(mOldRedirectChannel, "mOldRedirectChannel not set in callback");
   NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
 
   if (NS_SUCCEEDED(result)) {
       nsresult rv = UpdateChannel(mNewRedirectChannel);
       if (NS_FAILED(rv)) {
-          NS_WARNING("nsCrossSiteListenerProxy::OnRedirectVerifyCallback: "
+          NS_WARNING("nsCORSListenerProxy::OnRedirectVerifyCallback: "
                      "UpdateChannel() returned failure");
       }
       result = rv;
   }
 
   if (NS_FAILED(result)) {
     mOldRedirectChannel->Cancel(result);
   }
@@ -430,17 +712,17 @@ nsCrossSiteListenerProxy::OnRedirectVeri
   mOldRedirectChannel = nsnull;
   mNewRedirectChannel = nsnull;
   mRedirectCallback->OnRedirectVerifyCallback(result);
   mRedirectCallback   = nsnull;
   return NS_OK;
 }
 
 nsresult
-nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
+nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel)
 {
   nsCOMPtr<nsIURI> uri, originalURI;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
   NS_ENSURE_SUCCESS(rv, rv);  
 
   // Check that the uri is ok to load
@@ -512,8 +794,309 @@ nsCrossSiteListenerProxy::UpdateChannel(
 
     flags |= nsIRequest::LOAD_ANONYMOUS;
     rv = http->SetLoadFlags(flags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
+
+//////////////////////////////////////////////////////////////////////////
+// Preflight proxy
+
+// Class used as streamlistener and notification callback when
+// doing the initial OPTIONS request for a CORS check
+class nsCORSPreflightListener : public nsIStreamListener,
+                                public nsIInterfaceRequestor,
+                                public nsIChannelEventSink
+{
+public:
+  nsCORSPreflightListener(nsIChannel* aOuterChannel,
+                          nsIStreamListener* aOuterListener,
+                          nsISupports* aOuterContext,
+                          nsIPrincipal* aReferrerPrincipal,
+                          const nsACString& aRequestMethod,
+                          PRBool aWithCredentials)
+   : mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
+     mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
+     mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials)
+  { }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSICHANNELEVENTSINK
+
+private:
+  void AddResultToCache(nsIRequest* aRequest);
+
+  nsCOMPtr<nsIChannel> mOuterChannel;
+  nsCOMPtr<nsIStreamListener> mOuterListener;
+  nsCOMPtr<nsISupports> mOuterContext;
+  nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
+  nsCString mRequestMethod;
+  PRBool mWithCredentials;
+};
+
+NS_IMPL_ISUPPORTS4(nsCORSPreflightListener, nsIStreamListener,
+                   nsIRequestObserver, nsIInterfaceRequestor,
+                   nsIChannelEventSink)
+
+void
+nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
+{
+  nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
+  NS_ASSERTION(http, "Request was not http");
+
+  // The "Access-Control-Max-Age" header should return an age in seconds.
+  nsCAutoString headerVal;
+  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Max-Age"),
+                          headerVal);
+  if (headerVal.IsEmpty()) {
+    return;
+  }
+
+  // Sanitize the string. We only allow 'delta-seconds' as specified by
+  // http://dev.w3.org/2006/waf/access-control (digits 0-9 with no leading or
+  // trailing non-whitespace characters).
+  PRUint32 age = 0;
+  nsCSubstring::const_char_iterator iter, end;
+  headerVal.BeginReading(iter);
+  headerVal.EndReading(end);
+  while (iter != end) {
+    if (*iter < '0' || *iter > '9') {
+      return;
+    }
+    age = age * 10 + (*iter - '0');
+    // Cap at 24 hours. This also avoids overflow
+    age = NS_MIN(age, 86400U);
+    ++iter;
+  }
+
+  if (!age || !EnsurePreflightCache()) {
+    return;
+  }
+
+
+  // String seems fine, go ahead and cache.
+  // Note that we have already checked that these headers follow the correct
+  // syntax.
+
+  nsCOMPtr<nsIURI> uri;
+  NS_GetFinalChannelURI(http, getter_AddRefs(uri));
+
+  // PR_Now gives microseconds
+  PRTime expirationTime = PR_Now() + (PRUint64)age * PR_USEC_PER_SEC;
+
+  nsPreflightCache::CacheEntry* entry =
+    sPreflightCache->GetEntry(uri, mReferrerPrincipal, mWithCredentials,
+                              PR_TRUE);
+  if (!entry) {
+    return;
+  }
+
+  // The "Access-Control-Allow-Methods" header contains a comma separated
+  // list of method names.
+  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
+                          headerVal);
+
+  nsCCharSeparatedTokenizer methods(headerVal, ',');
+  while(methods.hasMoreTokens()) {
+    const nsDependentCSubstring& method = methods.nextToken();
+    if (method.IsEmpty()) {
+      continue;
+    }
+    PRUint32 i;
+    for (i = 0; i < entry->mMethods.Length(); ++i) {
+      if (entry->mMethods[i].token.Equals(method)) {
+        entry->mMethods[i].expirationTime = expirationTime;
+        break;
+      }
+    }
+    if (i == entry->mMethods.Length()) {
+      nsPreflightCache::TokenTime* newMethod =
+        entry->mMethods.AppendElement();
+      if (!newMethod) {
+        return;
+      }
+
+      newMethod->token = method;
+      newMethod->expirationTime = expirationTime;
+    }
+  }
+
+  // The "Access-Control-Allow-Headers" header contains a comma separated
+  // list of method names.
+  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
+                          headerVal);
+
+  nsCCharSeparatedTokenizer headers(headerVal, ',');
+  while(headers.hasMoreTokens()) {
+    const nsDependentCSubstring& header = headers.nextToken();
+    if (header.IsEmpty()) {
+      continue;
+    }
+    PRUint32 i;
+    for (i = 0; i < entry->mHeaders.Length(); ++i) {
+      if (entry->mHeaders[i].token.Equals(header)) {
+        entry->mHeaders[i].expirationTime = expirationTime;
+        break;
+      }
+    }
+    if (i == entry->mHeaders.Length()) {
+      nsPreflightCache::TokenTime* newHeader =
+        entry->mHeaders.AppendElement();
+      if (!newHeader) {
+        return;
+      }
+
+      newHeader->token = header;
+      newHeader->expirationTime = expirationTime;
+    }
+  }
+}
+
+NS_IMETHODIMP
+nsCORSPreflightListener::OnStartRequest(nsIRequest *aRequest,
+                                        nsISupports *aContext)
+{
+  nsresult status;
+  nsresult rv = aRequest->GetStatus(&status);
+
+  if (NS_SUCCEEDED(rv)) {
+    rv = status;
+  }
+
+  if (NS_SUCCEEDED(rv)) {
+    // Everything worked, try to cache and then fire off the actual request.
+    AddResultToCache(aRequest);
+
+    rv = mOuterChannel->AsyncOpen(mOuterListener, mOuterContext);
+  }
+
+  if (NS_FAILED(rv)) {
+    mOuterChannel->Cancel(rv);
+    mOuterListener->OnStartRequest(mOuterChannel, mOuterContext);
+    mOuterListener->OnStopRequest(mOuterChannel, mOuterContext, rv);
+    
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCORSPreflightListener::OnStopRequest(nsIRequest *aRequest,
+                                       nsISupports *aContext,
+                                       nsresult aStatus)
+{
+  return NS_OK;
+}
+
+/** nsIStreamListener methods **/
+
+NS_IMETHODIMP
+nsCORSPreflightListener::OnDataAvailable(nsIRequest *aRequest,
+                                         nsISupports *ctxt,
+                                         nsIInputStream *inStr,
+                                         PRUint32 sourceOffset,
+                                         PRUint32 count)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCORSPreflightListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
+                                                nsIChannel *aNewChannel,
+                                                PRUint32 aFlags,
+                                                nsIAsyncVerifyRedirectCallback *callback)
+{
+  // Only internal redirects allowed for now.
+  if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags))
+    return NS_ERROR_DOM_BAD_URI;
+
+  callback->OnRedirectVerifyCallback(NS_OK);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCORSPreflightListener::GetInterface(const nsIID & aIID, void **aResult)
+{
+  return QueryInterface(aIID, aResult);
+}
+
+
+nsresult
+NS_StartCORSPreflight(nsIChannel* aRequestChannel,
+                      nsIStreamListener* aListener,
+                      nsIPrincipal* aPrincipal,
+                      PRBool aWithCredentials,
+                      nsTArray<nsCString>& aUnsafeHeaders,
+                      nsIChannel** aPreflightChannel)
+{
+  *aPreflightChannel = nsnull;
+
+  nsCAutoString method;
+  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequestChannel));
+  NS_ENSURE_TRUE(httpChannel, NS_ERROR_UNEXPECTED);
+  httpChannel->GetRequestMethod(method);
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsPreflightCache::CacheEntry* entry =
+    sPreflightCache ?
+    sPreflightCache->GetEntry(uri, aPrincipal, aWithCredentials, PR_FALSE) :
+    nsnull;
+
+  if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
+    // We have a cached preflight result, just start the original channel
+    return aRequestChannel->AsyncOpen(aListener, nsnull);
+  }
+
+  // Either it wasn't cached or the cached result has expired. Build a
+  // channel for the OPTIONS request.
+
+  nsCOMPtr<nsILoadGroup> loadGroup;
+  rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsLoadFlags loadFlags;
+  rv = aRequestChannel->GetLoadFlags(&loadFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIChannel> preflightChannel;
+  rv = NS_NewChannel(getter_AddRefs(preflightChannel), uri, nsnull,
+                     loadGroup, nsnull, loadFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIHttpChannel> preHttp = do_QueryInterface(preflightChannel);
+  NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!");
+
+  rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  // Set up listener which will start the original channel
+  nsCOMPtr<nsIStreamListener> preflightListener =
+    new nsCORSPreflightListener(aRequestChannel, aListener, nsnull, aPrincipal,
+                                method, aWithCredentials);
+  NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
+
+  preflightListener =
+    new nsCORSListenerProxy(preflightListener, aPrincipal,
+                            preflightChannel, aWithCredentials,
+                            method, aUnsafeHeaders, &rv);
+  NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Start preflight
+  rv = preflightChannel->AsyncOpen(preflightListener, nsnull);
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  // Return newly created preflight channel
+  preflightChannel.forget(aPreflightChannel);
+
+  return NS_OK;
+}
+
--- a/content/base/src/nsCrossSiteListenerProxy.h
+++ b/content/base/src/nsCrossSiteListenerProxy.h
@@ -30,18 +30,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#ifndef nsCrossSiteListenerProxy_h__
-#define nsCrossSiteListenerProxy_h__
+#ifndef nsCORSListenerProxy_h__
+#define nsCORSListenerProxy_h__
 
 #include "nsIStreamListener.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIURI.h"
 #include "nsTArray.h"
 #include "nsIInterfaceRequestor.h"
@@ -50,45 +50,55 @@
 
 class nsIURI;
 class nsIParser;
 class nsIPrincipal;
 
 extern PRBool
 IsValidHTTPToken(const nsCSubstring& aToken);
 
-class nsCrossSiteListenerProxy : public nsIStreamListener,
-                                 public nsIInterfaceRequestor,
-                                 public nsIChannelEventSink,
-                                 public nsIAsyncVerifyRedirectCallback
+nsresult
+NS_StartCORSPreflight(nsIChannel* aRequestChannel,
+                      nsIStreamListener* aListener,
+                      nsIPrincipal* aPrincipal,
+                      PRBool aWithCredentials,
+                      nsTArray<nsCString>& aACUnsafeHeaders,
+                      nsIChannel** aPreflightChannel);
+
+class nsCORSListenerProxy : public nsIStreamListener,
+                            public nsIInterfaceRequestor,
+                            public nsIChannelEventSink,
+                            public nsIAsyncVerifyRedirectCallback
 {
 public:
-  nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                           nsIPrincipal* aRequestingPrincipal,
-                           nsIChannel* aChannel,
-                           PRBool aWithCredentials,
-                           nsresult* aResult);
-  nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                           nsIPrincipal* aRequestingPrincipal,
-                           nsIChannel* aChannel,
-                           PRBool aWithCredentials,
-                           const nsCString& aPreflightMethod,
-                           const nsTArray<nsCString>& aPreflightHeaders,
-                           nsresult* aResult);
+  nsCORSListenerProxy(nsIStreamListener* aOuter,
+                      nsIPrincipal* aRequestingPrincipal,
+                      nsIChannel* aChannel,
+                      PRBool aWithCredentials,
+                      nsresult* aResult);
+  nsCORSListenerProxy(nsIStreamListener* aOuter,
+                      nsIPrincipal* aRequestingPrincipal,
+                      nsIChannel* aChannel,
+                      PRBool aWithCredentials,
+                      const nsCString& aPreflightMethod,
+                      const nsTArray<nsCString>& aPreflightHeaders,
+                      nsresult* aResult);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
 
   // Must be called at startup.
   static void Startup();
 
+  static void Shutdown();
+
 private:
   nsresult UpdateChannel(nsIChannel* aChannel);
   nsresult CheckRequestApproved(nsIRequest* aRequest);
 
   nsCOMPtr<nsIStreamListener> mOuterListener;
   nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
   nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
   PRBool mWithCredentials;
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Implementation of the |attributes| property of DOM Core's nsIDOMNode object.
  */
 
 #include "nsDOMAttributeMap.h"
 #include "nsDOMAttribute.h"
-#include "nsIDOM3Document.h"
+#include "nsIDOMDocument.h"
 #include "nsGenericElement.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsINameSpaceManager.h"
 #include "nsDOMError.h"
 #include "nsContentUtils.h"
 #include "nsNodeInfoManager.h"
 #include "nsAttrName.h"
@@ -293,17 +293,17 @@ nsDOMAttributeMap::SetNamedItemInternal(
       // setting a preexisting attribute is a no-op, just return the same
       // node.
       NS_ADDREF(*aReturn = aNode);
       
       return NS_OK;
     }
 
     if (!mContent->HasSameOwnerDoc(iAttribute)) {
-      nsCOMPtr<nsIDOM3Document> domDoc =
+      nsCOMPtr<nsIDOMDocument> domDoc =
         do_QueryInterface(mContent->GetOwnerDoc(), &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIDOMNode> adoptedNode;
       rv = domDoc->AdoptNode(aNode, getter_AddRefs(adoptedNode));
       NS_ENSURE_SUCCESS(rv, rv);
 
       NS_ASSERTION(adoptedNode == aNode, "Uh, adopt node changed nodes?");
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -708,33 +708,21 @@ nsDOMFileReader::GuessCharset(const char
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = detector->Done();
     NS_ENSURE_SUCCESS(rv, rv);
 
     aCharset = mCharset;
   } else {
     // no charset detector available, check the BOM
-    unsigned char sniffBuf[4];
+    unsigned char sniffBuf[3];
     PRUint32 numRead = (aDataLen >= sizeof(sniffBuf) ? sizeof(sniffBuf) : aDataLen);
     memcpy(sniffBuf, aFileData, numRead);
 
-    if (numRead >= 4 &&
-        sniffBuf[0] == 0x00 &&
-        sniffBuf[1] == 0x00 &&
-        sniffBuf[2] == 0xfe &&
-        sniffBuf[3] == 0xff) {
-      aCharset = "UTF-32BE";
-    } else if (numRead >= 4 &&
-               sniffBuf[0] == 0xff &&
-               sniffBuf[1] == 0xfe &&
-               sniffBuf[2] == 0x00 &&
-               sniffBuf[3] == 0x00) {
-      aCharset = "UTF-32LE";
-    } else if (numRead >= 2 &&
+    if (numRead >= 2 &&
                sniffBuf[0] == 0xfe &&
                sniffBuf[1] == 0xff) {
       aCharset = "UTF-16BE";
     } else if (numRead >= 2 &&
                sniffBuf[0] == 0xff &&
                sniffBuf[1] == 0xfe) {
       aCharset = "UTF-16LE";
     } else if (numRead >= 3 &&
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -4261,21 +4261,20 @@ nsDocument::EndLoad()
       NS_NewRunnableMethod(this, &nsDocument::DispatchContentLoadedEvents);
     NS_DispatchToCurrentThread(ev);
   } else {
     DispatchContentLoadedEvents();
   }
 }
 
 void
-nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2,
-                                 nsEventStates aStateMask)
-{
-  NS_DOCUMENT_NOTIFY_OBSERVERS(ContentStatesChanged,
-                               (this, aContent1, aContent2, aStateMask));
+nsDocument::ContentStateChanged(nsIContent* aContent, nsEventStates aStateMask)
+{
+  NS_DOCUMENT_NOTIFY_OBSERVERS(ContentStateChanged,
+                               (this, aContent, aStateMask));
 }
 
 void
 nsDocument::DocumentStatesChanged(nsEventStates aStateMask)
 {
   // Invalidate our cached state.
   mGotDocumentState &= ~aStateMask;
   mDocumentState &= ~aStateMask;
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -47,17 +47,16 @@
 #include "nsCRT.h"
 #include "nsIDocument.h"
 #include "nsWeakReference.h"
 #include "nsWeakPtr.h"
 #include "nsVoidArray.h"
 #include "nsTArray.h"
 #include "nsHashSets.h"
 #include "nsIDOMXMLDocument.h"
-#include "nsIDOM3Document.h"
 #include "nsIDOMDocumentView.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMNSDocumentStyle.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsStubDocumentObserver.h"
 #include "nsIDOM3EventTarget.h"
@@ -504,17 +503,16 @@ class nsDocument : public nsIDocument,
                    public nsIDOMNSDocument,
                    public nsIDOMDocumentEvent,
                    public nsIDOM3DocumentEvent,
                    public nsIDOMNSDocumentStyle,
                    public nsIDOMDocumentView,
                    public nsIDOMDocumentRange,
                    public nsIDOMDocumentTraversal,
                    public nsIDOMDocumentXBL,
-                   public nsIDOM3Document,
                    public nsSupportsWeakReference,
                    public nsIDOMEventTarget,
                    public nsIDOM3EventTarget,
                    public nsIDOMNSEventTarget,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
                    public nsIApplicationCacheContainer,
                    public nsStubMutationObserver
@@ -703,19 +701,18 @@ public:
   virtual void BeginUpdate(nsUpdateType aUpdateType);
   virtual void EndUpdate(nsUpdateType aUpdateType);
   virtual void BeginLoad();
   virtual void EndLoad();
 
   virtual void SetReadyStateInternal(ReadyState rs);
   virtual ReadyState GetReadyStateEnum();
 
-  virtual void ContentStatesChanged(nsIContent* aContent1,
-                                    nsIContent* aContent2,
-                                    nsEventStates aStateMask);
+  virtual void ContentStateChanged(nsIContent* aContent,
+                                   nsEventStates aStateMask);
   virtual void DocumentStatesChanged(nsEventStates aStateMask);
 
   virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet,
                                 nsIStyleRule* aOldStyleRule,
                                 nsIStyleRule* aNewStyleRule);
   virtual void StyleRuleAdded(nsIStyleSheet* aStyleSheet,
                               nsIStyleRule* aStyleRule);
   virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
@@ -800,19 +797,16 @@ public:
                          nsRadioGroupStruct **aRadioGroup);
 
   // nsIDOMNode
   NS_DECL_NSIDOMNODE
 
   // nsIDOMDocument
   NS_DECL_NSIDOMDOCUMENT
 
-  // nsIDOM3Document
-  NS_DECL_NSIDOM3DOCUMENT
-
   // nsIDOMXMLDocument
   NS_DECL_NSIDOMXMLDOCUMENT
 
   // nsIDOMNSDocument
   NS_DECL_NSIDOMNSDOCUMENT
 
   // nsIDOMDocumentEvent
   NS_DECL_NSIDOMDOCUMENTEVENT
@@ -1274,12 +1268,11 @@ protected:
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocument, nsDocument)      \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNSDocument, nsDocument)    \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentEvent, nsDocument) \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentView, nsDocument)  \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentTraversal,         \
                                      nsDocument)                              \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMEventTarget, nsDocument)   \
-  NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, nsDocument)          \
-  NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOM3Document, nsDocument)
+  NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, nsDocument)
 
 #endif /* nsDocument_h___ */
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -417,17 +417,17 @@ nsDocumentEncoder::SerializeNodeStart(ns
 nsresult
 nsDocumentEncoder::SerializeNodeEnd(nsINode* aNode,
                                     nsAString& aStr)
 {
   if (!IsVisibleNode(aNode))
     return NS_OK;
 
   if (aNode->IsElement()) {
-    mSerializer->AppendElementEnd(static_cast<nsIContent*>(aNode), aStr);
+    mSerializer->AppendElementEnd(aNode->AsElement(), aStr);
   }
   return NS_OK;
 }
 
 nsresult
 nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
                                               nsAString& aStr,
                                               PRBool aDontSerializeRoot)
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -622,19 +622,17 @@ nsFrameScriptExecutor::LoadFrameScriptIn
     nsContentUtils::ThreadJSContextStack()->Push(mCx);
     {
       // Need to scope JSAutoRequest to happen after Push but before Pop,
       // at least for now. See bug 584673.
       JSAutoRequest ar(mCx);
       JSObject* global = nsnull;
       mGlobal->GetJSObject(&global);
       if (global) {
-        JS_ExecuteScript(mCx, global,
-                         (JSScript*)JS_GetPrivate(mCx, holder->mObject),
-                         nsnull);
+        JS_ExecuteScript(mCx, global, holder->mObject, nsnull);
       }
     }
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
     return;
   }
 
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
@@ -680,41 +678,37 @@ nsFrameScriptExecutor::LoadFrameScriptIn
       if (global) {
         JSPrincipals* jsprin = nsnull;
         mPrincipal->GetJSPrincipals(mCx, &jsprin);
         nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
 
         uint32 oldopts = JS_GetOptions(mCx);
         JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL);
 
-        JSScript* script =
+        JSObject* scriptObj =
           JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin,
                                          (jschar*)dataString.get(),
                                           dataString.Length(),
                                           url.get(), 1);
 
         JS_SetOptions(mCx, oldopts);
 
-        if (script) {
-          JSObject* scriptObj = JS_NewScriptObject(mCx, script);
-          JS_AddObjectRoot(mCx, &scriptObj);
+        if (scriptObj) {
           nsCAutoString scheme;
           uri->GetScheme(scheme);
           // We don't cache data: scripts!
           if (!scheme.EqualsLiteral("data")) {
             nsFrameScriptExecutorJSObjectHolder* holder =
               new nsFrameScriptExecutorJSObjectHolder(scriptObj);
             // Root the object also for caching.
             JS_AddNamedObjectRoot(mCx, &(holder->mObject),
                                   "Cached message manager script");
             sCachedScripts->Put(aURL, holder);
           }
-          JS_ExecuteScript(mCx, global,
-                           (JSScript*)JS_GetPrivate(mCx, scriptObj), nsnull);
-          JS_RemoveObjectRoot(mCx, &scriptObj);
+          JS_ExecuteScript(mCx, global, scriptObj, nsnull);
         }
         //XXX Argh, JSPrincipals are manually refcounted!
         JSPRINCIPALS_DROP(mCx, jsprin);
       }
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -1110,21 +1110,20 @@ nsGenericDOMDataNode::DoGetClasses() con
 
 NS_IMETHODIMP
 nsGenericDOMDataNode::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   return NS_OK;
 }
 
 #ifdef MOZ_SMIL
-nsresult
-nsGenericDOMDataNode::GetSMILOverrideStyle(nsIDOMCSSStyleDeclaration** aStyle)
+nsIDOMCSSStyleDeclaration*
+nsGenericDOMDataNode::GetSMILOverrideStyle()
 {
-  *aStyle = nsnull;
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return nsnull;
 }
 
 css::StyleRule*
 nsGenericDOMDataNode::GetSMILOverrideStyleRule()
 {
   return nsnull;
 }
 
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -229,17 +229,17 @@ public:
   virtual void DestroyContent();
   virtual void SaveSubtreeState();
 
 #ifdef MOZ_SMIL
   virtual nsISMILAttr* GetAnimatedAttr(PRInt32 /*aNamespaceID*/, nsIAtom* /*aName*/)
   {
     return nsnull;
   }
-  virtual nsresult GetSMILOverrideStyle(nsIDOMCSSStyleDeclaration** aStyle);
+  virtual nsIDOMCSSStyleDeclaration* GetSMILOverrideStyle();
   virtual mozilla::css::StyleRule* GetSMILOverrideStyleRule();
   virtual nsresult SetSMILOverrideStyleRule(mozilla::css::StyleRule* aStyleRule,
                                             PRBool aNotify);
 #endif // MOZ_SMIL
 
 #ifdef DEBUG
   virtual void List(FILE* out, PRInt32 aIndent) const;
   virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3344,29 +3344,26 @@ nsGenericElement::DoGetClasses() const
 
 NS_IMETHODIMP
 nsGenericElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   return NS_OK;
 }
 
 #ifdef MOZ_SMIL
-nsresult
-nsGenericElement::GetSMILOverrideStyle(nsIDOMCSSStyleDeclaration** aStyle)
+nsIDOMCSSStyleDeclaration*
+nsGenericElement::GetSMILOverrideStyle()
 {
   nsGenericElement::nsDOMSlots *slots = DOMSlots();
 
   if (!slots->mSMILOverrideStyle) {
     slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, PR_TRUE);
-    NS_ENSURE_TRUE(slots->mSMILOverrideStyle, NS_ERROR_OUT_OF_MEMORY);
-  }
-
-  // Why bother with QI?
-  NS_ADDREF(*aStyle = slots->mSMILOverrideStyle);
-  return NS_OK;
+  }
+
+  return slots->mSMILOverrideStyle;
 }
 
 css::StyleRule*
 nsGenericElement::GetSMILOverrideStyleRule()
 {
   nsGenericElement::nsDOMSlots *slots = GetExistingDOMSlots();
   return slots ? slots->mSMILOverrideStyleRule.get() : nsnull;
 }
@@ -3559,17 +3556,17 @@ nsINode::doInsertChildAt(nsIContent* aKi
   if (!HasSameOwnerDoc(aKid)) {
     nsCOMPtr<nsIDOMNode> kid = do_QueryInterface(aKid, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
  
     PRUint16 nodeType = 0;
     rv = kid->GetNodeType(&nodeType);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIDOM3Document> domDoc = do_QueryInterface(GetOwnerDoc());
+    nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(GetOwnerDoc());
 
     // DocumentType nodes are the only nodes that can have a null
     // ownerDocument according to the DOM spec, and we need to allow
     // inserting them w/o calling AdoptNode().
 
     if (domDoc && (nodeType != nsIDOMNode::DOCUMENT_TYPE_NODE ||
                    aKid->GetOwnerDoc())) {
       nsCOMPtr<nsIDOMNode> adoptedKid;
@@ -4070,17 +4067,17 @@ nsINode::ReplaceOrInsertBefore(PRBool aR
   nsIDocument *doc = GetOwnerDoc();
 
   // DocumentType nodes are the only nodes that can have a null
   // ownerDocument according to the DOM spec, and we need to allow
   // inserting them w/o calling AdoptNode().
   if (!HasSameOwnerDoc(newContent) &&
       (nodeType != nsIDOMNode::DOCUMENT_TYPE_NODE ||
        newContent->GetOwnerDoc())) {
-    nsCOMPtr<nsIDOM3Document> domDoc = do_QueryInterface(doc);
+    nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
 
     if (domDoc) {
       nsresult rv;
       nsCOMPtr<nsIDOMNode> newChild = do_QueryInterface(aNewChild, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIDOMNode> adoptedKid;
       rv = domDoc->AdoptNode(newChild, getter_AddRefs(adoptedKid));
@@ -4761,17 +4758,17 @@ nsGenericElement::SetAttrAndNotify(PRInt
       }
     }
   }
 
   if (aNotify) {
     stateMask ^= IntrinsicState();
     if (document && !stateMask.IsEmpty()) {
       MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
-      document->ContentStatesChanged(this, nsnull, stateMask);
+      document->ContentStateChanged(this, stateMask);
     }
     nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
   }
 
   if (aNamespaceID == kNameSpaceID_XMLEvents && 
       aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
   }
@@ -5008,17 +5005,17 @@ nsGenericElement::UnsetAttr(PRInt32 aNam
       }
     }
   }
 
   if (aNotify) {
     stateMask ^= IntrinsicState();
     if (document && !stateMask.IsEmpty()) {
       MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
-      document->ContentStatesChanged(this, nsnull, stateMask);
+      document->ContentStateChanged(this, stateMask);
     }
     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
                                   nsIDOMMutationEvent::REMOVAL);
   }
 
   rv = AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -5481,18 +5478,17 @@ nsGenericElement::GetLinkTarget(nsAStrin
 }
 
 // NOTE: The aPresContext pointer is NOT addrefed.
 // *aSelectorList might be null even if NS_OK is returned; this
 // happens when all the selectors were pseudo-element selectors.
 static nsresult
 ParseSelectorList(nsINode* aNode,
                   const nsAString& aSelectorString,
-                  nsCSSSelectorList** aSelectorList,
-                  nsPresContext** aPresContext)
+                  nsCSSSelectorList** aSelectorList)
 {
   NS_ENSURE_ARG(aNode);
 
   nsIDocument* doc = aNode->GetOwnerDoc();
   NS_ENSURE_STATE(doc);
 
   nsCSSParser parser(doc->CSSLoader());
   NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
@@ -5513,195 +5509,96 @@ ParseSelectorList(nsINode* aNode,
       cur->mNext = nsnull;
       delete cur;
     } else {
       slot = &cur->mNext;
     }
   } while (*slot);
   *aSelectorList = selectorList;
 
-  // It's not strictly necessary to have a prescontext here, but it's
-  // a bit of an optimization for various stuff.
-  *aPresContext = nsnull;
-  nsIPresShell* shell = doc->GetShell();
-  if (shell) {
-    *aPresContext = shell->GetPresContext();
-  }
-
   return NS_OK;
 }
 
-/*
- * Callback to be called as we iterate over the tree and match elements.  If
- * the callbacks returns false, the iteration should be stopped.
- */
-typedef PRBool
-(* ElementMatchedCallback)(nsIContent* aMatchingElement, void* aClosure);
-
-// returning false means stop iteration
-static PRBool
-TryMatchingElementsInSubtree(nsINode* aRoot,
-                             RuleProcessorData* aParentData,
-                             nsPresContext* aPresContext,
-                             nsCSSSelectorList* aSelectorList,
-                             ElementMatchedCallback aCallback,
-                             void* aClosure)
-{
-  /* To improve the performance of '+' and '~' combinators and the :nth-*
-   * selectors, we keep track of the immediately previous sibling data.  That's
-   * cheaper than heap-allocating all the datas and keeping track of them all,
-   * and helps a good bit in the common cases.  We also keep track of the whole
-   * parent data chain, since we have those Around anyway */
-  union { char c[2 * sizeof(RuleProcessorData)]; void *p; } databuf;
-  RuleProcessorData* prevSibling = nsnull;
-  RuleProcessorData* data = reinterpret_cast<RuleProcessorData*>(databuf.c);
-
-  PRBool continueIteration = PR_TRUE;
-  for (nsINode::ChildIterator iter(aRoot); !iter.IsDone(); iter.Next()) {
-    nsIContent* kid = iter;
-    if (!kid->IsElement()) {
-      continue;
-    }
-    /* See whether we match */
-    new (data) RuleProcessorData(aPresContext, kid->AsElement(), nsnull);
-    NS_ASSERTION(!data->mParentData, "Shouldn't happen");
-    NS_ASSERTION(!data->mPreviousSiblingData, "Shouldn't happen");
-    data->mParentData = aParentData;
-    data->mPreviousSiblingData = prevSibling;
-
-    if (nsCSSRuleProcessor::SelectorListMatches(*data, aSelectorList)) {
-      continueIteration = (*aCallback)(kid, aClosure);
-    }
-
-    if (continueIteration) {
-      continueIteration =
-        TryMatchingElementsInSubtree(kid, data, aPresContext, aSelectorList,
-                                     aCallback, aClosure);
-    }
-    
-    /* Clear out the parent and previous sibling data if we set them, so that
-     * ~RuleProcessorData won't try to delete a placement-new'd object. Make
-     * sure this happens before our possible early break.  Note that we can
-     * have null aParentData but non-null data->mParentData if we're scoped to
-     * an element.  However, prevSibling and data->mPreviousSiblingData must
-     * always match.
-     */
-    NS_ASSERTION(!aParentData || data->mParentData == aParentData,
-                 "Unexpected parent");
-    NS_ASSERTION(data->mPreviousSiblingData == prevSibling,
-                 "Unexpected prev sibling");
-    data->mPreviousSiblingData = nsnull;
-    if (prevSibling) {
-      if (aParentData) {
-        prevSibling->mParentData = nsnull;
-      }
-      prevSibling->~RuleProcessorData();
-    } else {
-      /* This is the first time through, so point |prevSibling| to the location
-         we want to have |data| end up pointing to. */
-      prevSibling = data + 1;
-    }
-
-    /* Now swap |prevSibling| and |data|.  Again, before the early break */
-    RuleProcessorData* temp = prevSibling;
-    prevSibling = data;
-    data = temp;
-    if (!continueIteration) {
-      break;
-    }
-  }
-  if (prevSibling) {
-    if (aParentData) {
-      prevSibling->mParentData = nsnull;
-    }
-    /* Make sure to clean this up */
-    prevSibling->~RuleProcessorData();
-  }
-
-  return continueIteration;
-}
-
-static PRBool
-FindFirstMatchingElement(nsIContent* aMatchingElement,
-                         void* aClosure)
-{
-  NS_PRECONDITION(aMatchingElement && aClosure, "How did that happen?");
-  nsIContent** slot = static_cast<nsIContent**>(aClosure);
-  *slot = aMatchingElement;
-  return PR_FALSE;
-}
-
 /* static */
 nsIContent*
 nsGenericElement::doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
                                   nsresult *aResult)
 {
   NS_PRECONDITION(aResult, "Null out param?");
 
   nsAutoPtr<nsCSSSelectorList> selectorList;
-  nsPresContext* presContext;
   *aResult = ParseSelectorList(aRoot, aSelector,
-                               getter_Transfers(selectorList),
-                               &presContext);
+                               getter_Transfers(selectorList));
   NS_ENSURE_SUCCESS(*aResult, nsnull);
 
-  nsIContent* foundElement = nsnull;
-  TryMatchingElementsInSubtree(aRoot, nsnull, presContext, selectorList,
-                               FindFirstMatchingElement, &foundElement);
-
-  return foundElement;
-}
-
-static PRBool
-AppendAllMatchingElements(nsIContent* aMatchingElement,
-                          void* aClosure)
-{
-  NS_PRECONDITION(aMatchingElement && aClosure, "How did that happen?");
-  static_cast<nsBaseContentList*>(aClosure)->AppendElement(aMatchingElement);
-  return PR_TRUE;
+  TreeMatchContext matchingContext(PR_FALSE,
+                                   nsRuleWalker::eRelevantLinkUnvisited,
+                                   aRoot->GetOwnerDoc());
+  for (nsIContent* cur = aRoot->GetFirstChild();
+       cur;
+       cur = cur->GetNextNode(aRoot)) {
+    if (cur->IsElement() &&
+        nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
+                                                matchingContext,
+                                                selectorList)) {
+      return cur;
+    }
+  }
+
+  return nsnull;
 }
 
 /* static */
 nsresult
 nsGenericElement::doQuerySelectorAll(nsINode* aRoot,
                                      const nsAString& aSelector,
                                      nsIDOMNodeList **aReturn)
 {
   NS_PRECONDITION(aReturn, "Null out param?");
 
   nsBaseContentList* contentList = new nsBaseContentList();
   NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(*aReturn = contentList);
   
   nsAutoPtr<nsCSSSelectorList> selectorList;
-  nsPresContext* presContext;
   nsresult rv = ParseSelectorList(aRoot, aSelector,
-                                  getter_Transfers(selectorList),
-                                  &presContext);
+                                  getter_Transfers(selectorList));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  TryMatchingElementsInSubtree(aRoot, nsnull, presContext, selectorList,
-                               AppendAllMatchingElements, contentList);
+  TreeMatchContext matchingContext(PR_FALSE,
+                                   nsRuleWalker::eRelevantLinkUnvisited,
+                                   aRoot->GetOwnerDoc());
+  for (nsIContent* cur = aRoot->GetFirstChild();
+       cur;
+       cur = cur->GetNextNode(aRoot)) {
+    if (cur->IsElement() &&
+        nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
+                                                matchingContext,
+                                                selectorList)) {
+      contentList->AppendElement(cur);
+    }
+  }
   return NS_OK;
 }
 
 
 PRBool
 nsGenericElement::MozMatchesSelector(const nsAString& aSelector, nsresult* aResult)
 {
   nsAutoPtr<nsCSSSelectorList> selectorList;
-  nsPresContext* presContext;
   PRBool matches = PR_FALSE;
 
-  *aResult = ParseSelectorList(this, aSelector, getter_Transfers(selectorList),
-                               &presContext);
+  *aResult = ParseSelectorList(this, aSelector, getter_Transfers(selectorList));
 
   if (NS_SUCCEEDED(*aResult)) {
-    RuleProcessorData data(presContext, this, nsnull);
-    matches = nsCSSRuleProcessor::SelectorListMatches(data, selectorList);
+    TreeMatchContext matchingContext(PR_FALSE,
+                                     nsRuleWalker::eRelevantLinkUnvisited,
+                                     GetOwnerDoc());
+    matches = nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
+                                                      selectorList);
   }
 
   return matches;
 }
 
 NS_IMETHODIMP
 nsNSElementTearoff::MozMatchesSelector(const nsAString& aSelector, PRBool* aReturn)
 {
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -450,17 +450,17 @@ public:
   virtual void DestroyContent();
   virtual void SaveSubtreeState();
 
 #ifdef MOZ_SMIL
   virtual nsISMILAttr* GetAnimatedAttr(PRInt32 /*aNamespaceID*/, nsIAtom* /*aName*/)
   {
     return nsnull;
   }
-  virtual nsresult GetSMILOverrideStyle(nsIDOMCSSStyleDeclaration** aStyle);
+  virtual nsIDOMCSSStyleDeclaration* GetSMILOverrideStyle();
   virtual mozilla::css::StyleRule* GetSMILOverrideStyleRule();
   virtual nsresult SetSMILOverrideStyleRule(mozilla::css::StyleRule* aStyleRule,
                                             PRBool aNotify);
 #endif // MOZ_SMIL
 
 #ifdef DEBUG
   virtual void List(FILE* out, PRInt32 aIndent) const
   {
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -67,16 +67,19 @@
 #include "nsContentUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsIScriptElement.h"
 #include "nsAttrName.h"
 #include "nsIDocShell.h"
 #include "nsIEditorDocShell.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla::dom;
 
 static const PRInt32 kLongLineLen = 128;
 
 nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsHTMLContentSerializer* it = new nsHTMLContentSerializer();
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -223,18 +226,18 @@ nsHTMLContentSerializer::SerializeHTMLAt
     if (IsShorthandAttr(attrName, aTagName) && valueStr.IsEmpty()) {
       valueStr = nameStr;
     }
     SerializeAttr(EmptyString(), nameStr, valueStr, aStr, !isJS);
   }
 }
 
 NS_IMETHODIMP
-nsHTMLContentSerializer::AppendElementStart(nsIContent *aElement,
-                                            nsIContent *aOriginalElement,
+nsHTMLContentSerializer::AppendElementStart(Element* aElement,
+                                            Element* aOriginalElement,
                                             nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsIContent* content = aElement;
 
   PRBool forceFormat = PR_FALSE;
   if (!CheckElementStart(content, forceFormat, aStr)) {
@@ -337,17 +340,17 @@ nsHTMLContentSerializer::AppendElementSt
   }
 
   AfterElementStart(content, aOriginalElement, aStr);
 
   return NS_OK;
 }
   
 NS_IMETHODIMP 
-nsHTMLContentSerializer::AppendElementEnd(nsIContent *aElement,
+nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
                                           nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsIContent* content = aElement;
 
   nsIAtom *name = content->Tag();
 
--- a/content/base/src/nsHTMLContentSerializer.h
+++ b/content/base/src/nsHTMLContentSerializer.h
@@ -52,21 +52,21 @@
 class nsIContent;
 class nsIAtom;
 
 class nsHTMLContentSerializer : public nsXHTMLContentSerializer {
  public:
   nsHTMLContentSerializer();
   virtual ~nsHTMLContentSerializer();
 
-  NS_IMETHOD AppendElementStart(nsIContent *aElement,
-                                nsIContent *aOriginalElement,
+  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
+                                mozilla::dom::Element* aOriginalElement,
                                 nsAString& aStr);
-  
-  NS_IMETHOD AppendElementEnd(nsIContent *aElement,
+
+  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
                               nsAString& aStr);
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr);
  protected:
 
   virtual void SerializeHTMLAttributes(nsIContent* aContent,
                                        nsIContent *aOriginalElement,
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -824,17 +824,17 @@ nsImageLoadingContent::UpdateImageState(
 
   if (aNotify) {
     nsIDocument* doc = thisContent->GetCurrentDoc();
     if (doc) {
       NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
       nsEventStates changedBits = oldState ^ ImageState();
       if (!changedBits.IsEmpty()) {
         mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
-        doc->ContentStatesChanged(thisContent, nsnull, changedBits);
+        doc->ContentStateChanged(thisContent, changedBits);
       }
     }
   }
 }
 
 void
 nsImageLoadingContent::CancelImageRequests(PRBool aNotify)
 {
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1652,17 +1652,17 @@ nsObjectLoadingContent::NotifyStateChang
 
   if (newState != aOldState) {
     // This will trigger frame construction
     NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
     nsEventStates changedBits = aOldState ^ newState;
 
     {
       mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
-      doc->ContentStatesChanged(thisContent, nsnull, changedBits);
+      doc->ContentStateChanged(thisContent, changedBits);
     }
     if (aSync) {
       // Make sure that frames are actually constructed, and do it after
       // EndUpdate was called.
       doc->FlushPendingNotifications(Flush_Frames);
     }
   } else if (aOldType != mType) {
     // If our state changed, then we already recreated frames
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -52,16 +52,19 @@
 #include "nsIDOMElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsIParserService.h"
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla::dom;
 
 #define PREF_STRUCTS "converter.html2txt.structs"
 #define PREF_HEADER_STRATEGY "converter.html2txt.header_strategy"
 
 static const  PRInt32 kTabSize=4;
 static const  PRInt32 kOLNumberWidth = 3;
 static const  PRInt32 kIndentSizeHeaders = 2;  /* Indention of h1, if
                                                 mHeaderStrategy = 1 or = 2.
@@ -376,18 +379,18 @@ nsPlainTextSerializer::AppendCDATASectio
                                           PRInt32 aStartOffset,
                                           PRInt32 aEndOffset,
                                           nsAString& aStr)
 {
   return AppendText(aCDATASection, aStartOffset, aEndOffset, aStr);
 }
 
 NS_IMETHODIMP
-nsPlainTextSerializer::AppendElementStart(nsIContent *aElement,
-                                          nsIContent *aOriginalElement,
+nsPlainTextSerializer::AppendElementStart(Element* aElement,
+                                          Element* aOriginalElement,
                                           nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   mContent = aElement;
 
   nsresult rv;
   PRInt32 id = GetIdForContent(mContent);
@@ -409,17 +412,17 @@ nsPlainTextSerializer::AppendElementStar
   if (id == eHTMLTag_head) {
     ++mHeadLevel;
   }
 
   return rv;
 } 
  
 NS_IMETHODIMP 
-nsPlainTextSerializer::AppendElementEnd(nsIContent *aElement,
+nsPlainTextSerializer::AppendElementEnd(Element* aElement,
                                         nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   mContent = aElement;
 
   nsresult rv;
   PRInt32 id = GetIdForContent(mContent);
--- a/content/base/src/nsPlainTextSerializer.h
+++ b/content/base/src/nsPlainTextSerializer.h
@@ -51,16 +51,22 @@
 #include "nsString.h"
 #include "nsILineBreaker.h"
 #include "nsIContent.h"
 #include "nsIAtom.h"
 #include "nsIHTMLToTextSink.h"
 #include "nsIDocumentEncoder.h"
 #include "nsTArray.h"
 
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
 class nsPlainTextSerializer : public nsIContentSerializer,
                               public nsIHTMLContentSink,
                               public nsIHTMLToTextSink
 {
 public:
   nsPlainTextSerializer();
   virtual ~nsPlainTextSerializer();
 
@@ -79,20 +85,20 @@ public:
   NS_IMETHOD AppendProcessingInstruction(nsIContent* aPI,
                                          PRInt32 aStartOffset,
                                          PRInt32 aEndOffset,
                                          nsAString& aStr)  { return NS_OK; }
   NS_IMETHOD AppendComment(nsIContent* aComment, PRInt32 aStartOffset,
                            PRInt32 aEndOffset, nsAString& aStr)  { return NS_OK; }
   NS_IMETHOD AppendDoctype(nsIContent *aDoctype,
                            nsAString& aStr)  { return NS_OK; }
-  NS_IMETHOD AppendElementStart(nsIContent *aElement,
-                                nsIContent *aOriginalElement,
+  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
+                                mozilla::dom::Element* aOriginalElement,
                                 nsAString& aStr); 
-  NS_IMETHOD AppendElementEnd(nsIContent *aElement,
+  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
                               nsAString& aStr);
   NS_IMETHOD Flush(nsAString& aStr);
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr);
 
   // nsIContentSink
   NS_IMETHOD WillParse(void) { return NS_OK; }
@@ -230,17 +236,17 @@ protected:
                                               header level (default)
                                           2 = numbering and slight indention */
   PRInt32          mHeaderCounter[7];  /* For header-numbering:
                                           Number of previous headers of
                                           the same depth and in the same
                                           section.
                                           mHeaderCounter[1] for <h1> etc. */
 
-  nsCOMPtr<nsIContent> mContent;
+  nsRefPtr<mozilla::dom::Element> mContent;
 
   // For handling table rows
   nsAutoTArray<PRPackedBool, 8> mHasWrittenCellsForRow;
   
   // Values gotten in OpenContainer that is (also) needed in CloseContainer
   nsAutoTArray<PRPackedBool, 8> mCurrentNodeIsConverted;
   nsAutoTArray<PRPackedBool, 8> mIsInCiteBlockquote;
 
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -215,18 +215,18 @@ nsSyncLoader::LoadDocument(nsIChannel* a
 
     if (aForceToXML) {
         nsCOMPtr<nsIStreamListener> forceListener =
             new nsForceXMLListener(listener);
         listener.swap(forceListener);
     }
 
     if (aLoaderPrincipal) {
-        listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
-                                                mChannel, PR_FALSE, &rv);
+        listener = new nsCORSListenerProxy(listener, aLoaderPrincipal,
+                                           mChannel, PR_FALSE, &rv);
         NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // Register as a load listener on the document
     nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(document);
     NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
 
--- a/content/base/src/nsTextFragment.cpp
+++ b/content/base/src/nsTextFragment.cpp
@@ -43,16 +43,17 @@
 
 #include "nsTextFragment.h"
 #include "nsCRT.h"
 #include "nsReadableUtils.h"
 #include "nsMemory.h"
 #include "nsBidiUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsUTF8Utils.h"
+#include "mozilla/SSE.h"
 
 #define TEXTFRAG_WHITE_AFTER_NEWLINE 50
 #define TEXTFRAG_MAX_NEWLINES 7
 
 // Static buffer used for common fragments
 static char* sSpaceSharedString[TEXTFRAG_MAX_NEWLINES + 1];
 static char* sTabSharedString[TEXTFRAG_MAX_NEWLINES + 1];
 static char sSingleCharSharedString[256];
@@ -139,16 +140,79 @@ nsTextFragment::operator=(const nsTextFr
     if (m1b) {
       mAllBits = aOther.mAllBits;
     }
   }
 
   return *this;
 }
 
+static inline PRBool
+Is8BitUnvectorized(const PRUnichar *str, const PRUnichar *end)
+{
+#if PR_BYTES_PER_WORD == 4
+  const size_t mask = 0xff00ff00;
+  const PRUint32 alignMask = 0x3;
+  const PRUint32 numUnicharsPerWord = 2;
+#elif PR_BYTES_PER_WORD == 8
+  const size_t mask = 0xff00ff00ff00ff00;
+  const PRUint32 alignMask = 0x7;
+  const PRUint32 numUnicharsPerWord = 4;
+#else
+#error Unknown platform!
+#endif
+
+  const PRInt32 len = end - str;
+  PRInt32 i = 0;
+
+  // Align ourselves to a word boundary.
+  PRInt32 alignLen =
+    PR_MIN(len, PRInt32(((-NS_PTR_TO_UINT32(str)) & alignMask) / sizeof(PRUnichar)));
+  for (; i < alignLen; i++) {
+    if (str[i] > 255)
+      return PR_FALSE;
+  }
+
+  // Check one word at a time.
+  const PRInt32 wordWalkEnd = ((len - i) / numUnicharsPerWord) * numUnicharsPerWord;
+  for (; i < wordWalkEnd; i += numUnicharsPerWord) {
+    const size_t word = *reinterpret_cast<const size_t*>(str + i);
+    if (word & mask)
+      return PR_FALSE;
+  }
+
+  // Take care of the remainder one character at a time.
+  for (; i < len; i++) {
+    if (str[i] > 255)
+      return PR_FALSE;
+  }
+
+  return PR_TRUE;
+}
+
+#ifdef MOZILLA_MAY_SUPPORT_SSE2
+namespace mozilla {
+  namespace SSE2 {
+    PRBool Is8Bit(const PRUnichar *str, const PRUnichar *end);
+  }
+}
+#endif
+
+static inline PRBool
+Is8Bit(const PRUnichar *str, const PRUnichar *end)
+{
+#ifdef MOZILLA_MAY_SUPPORT_SSE2
+  if (mozilla::supports_sse2()) {
+    return mozilla::SSE2::Is8Bit(str, end);
+  }
+#endif
+
+  return Is8BitUnvectorized(str, end);
+}
+
 void
 nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
 {
   ReleaseText();
 
   if (aLength == 0) {
     return;
   }
@@ -162,17 +226,18 @@ nsTextFragment::SetTo(const PRUnichar* a
 
     return;
   }
 
   const PRUnichar *ucp = aBuffer;
   const PRUnichar *uend = aBuffer + aLength;
 
   // Check if we can use a shared string
-  if (firstChar == ' ' || firstChar == '\n' || firstChar == '\t') {
+  if (aLength <= 1 + TEXTFRAG_WHITE_AFTER_NEWLINE + TEXTFRAG_MAX_NEWLINES &&
+     (firstChar == ' ' || firstChar == '\n' || firstChar == '\t')) {
     if (firstChar == ' ') {
       ++ucp;
     }
 
     const PRUnichar* start = ucp;
     while (ucp < uend && *ucp == '\n') {
       ++ucp;
     }
@@ -198,43 +263,34 @@ nsTextFragment::SetTo(const PRUnichar* a
       mState.mIs2b = PR_FALSE;
       mState.mLength = aLength;
 
       return;        
     }
   }
 
   // See if we need to store the data in ucs2 or not
-  PRBool need2 = PR_FALSE;
-  while (ucp < uend) {
-    PRUnichar ch = *ucp++;
-    if (ch >= 256) {
-      need2 = PR_TRUE;
-      break;
-    }
-  }
+  PRBool need2 = !Is8Bit(ucp, uend);
 
   if (need2) {
     // Use ucs2 storage because we have to
     m2b = (PRUnichar *)nsMemory::Clone(aBuffer,
                                        aLength * sizeof(PRUnichar));
     if (!m2b) {
       return;
     }
   } else {
     // Use 1 byte storage because we can
     char* buff = (char *)nsMemory::Alloc(aLength * sizeof(char));
     if (!buff) {
       return;
     }
 
     // Copy data
-    // Use the same copying code we use elsewhere; it's likely to be
-    // carefully tuned.
-    LossyConvertEncoding<PRUnichar, char> converter(buff);
+    LossyConvertEncoding16to8 converter(buff);
     copy_string(aBuffer, aBuffer+aLength, converter);
     m1b = buff;
   }
 
   // Setup our fields
   mState.mInHeap = PR_TRUE;
   mState.mIs2b = need2;
   mState.mLength = aLength;
@@ -255,19 +311,18 @@ nsTextFragment::CopyTo(PRUnichar *aDest,
   }
 
   if (aCount != 0) {
     if (mState.mIs2b) {
       memcpy(aDest, m2b + aOffset, sizeof(PRUnichar) * aCount);
     } else {
       const char *cp = m1b + aOffset;
       const char *end = cp + aCount;
-      while (cp < end) {
-        *aDest++ = (unsigned char)(*cp++);
-      }
+      LossyConvertEncoding8to16 converter(aDest);
+      copy_string(cp, end, converter);
     }
   }
 }
 
 void
 nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength)
 {
   // This is a common case because some callsites create a textnode
@@ -291,41 +346,29 @@ nsTextFragment::Append(const PRUnichar* 
     mState.mLength += aLength;
     m2b = buff;
 
     return;
   }
 
   // Current string is a 1-byte string, check if the new data fits in one byte too.
 
-  const PRUnichar* ucp = aBuffer;
-  const PRUnichar* uend = ucp + aLength;
-  PRBool need2 = PR_FALSE;
-  while (ucp < uend) {
-    PRUnichar ch = *ucp++;
-    if (ch >= 256) {
-      need2 = PR_TRUE;
-      break;
-    }
-  }
-
-  if (need2) {
+  if (!Is8Bit(aBuffer, aBuffer + aLength)) {
     // The old data was 1-byte, but the new is not so we have to expand it
     // all to 2-byte
     PRUnichar* buff = (PRUnichar*)nsMemory::Alloc((mState.mLength + aLength) *
                                                   sizeof(PRUnichar));
     if (!buff) {
       return;
     }
 
-    // Copy data
-    for (PRUint32 i = 0; i < mState.mLength; ++i) {
-      buff[i] = (unsigned char)m1b[i];
-    }
-    
+    // Copy data into buff
+    LossyConvertEncoding8to16 converter(buff);
+    copy_string(m1b, m1b+mState.mLength, converter);
+
     memcpy(buff + mState.mLength, aBuffer, aLength * sizeof(PRUnichar));
 
     mState.mLength += aLength;
     mState.mIs2b = PR_TRUE;
 
     if (mState.mInHeap) {
       nsMemory::Free(m2b);
     }
@@ -349,20 +392,20 @@ nsTextFragment::Append(const PRUnichar* 
     buff = (char*)nsMemory::Alloc((mState.mLength + aLength) * sizeof(char));
     if (!buff) {
       return;
     }
 
     memcpy(buff, m1b, mState.mLength);
     mState.mInHeap = PR_TRUE;
   }
-    
-  for (PRUint32 i = 0; i < aLength; ++i) {
-    buff[mState.mLength + i] = (char)aBuffer[i];
-  }
+
+  // Copy aBuffer into buff.
+  LossyConvertEncoding16to8 converter(buff + mState.mLength);
+  copy_string(aBuffer, aBuffer + aLength, converter);
 
   m1b = buff;
   mState.mLength += aLength;
 
 }
 
 // To save time we only do this when we really want to know, not during
 // every allocation
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsTextFragmentSSE2.cpp
@@ -0,0 +1,72 @@
+// This file should only be compiled if you're on x86 or x86_64.  Additionally,
+// you'll need to compile this file with -msse2 if you're using gcc.
+
+#include <emmintrin.h>
+#include "nscore.h"
+
+namespace mozilla {
+namespace SSE2 {
+
+static inline bool
+is_zero (__m128i x)
+{
+  return
+    _mm_movemask_epi8(_mm_cmpeq_epi8(x, _mm_setzero_si128())) == 0xffff;
+}
+
+PRBool
+Is8Bit(const PRUnichar *str, const PRUnichar *end)
+{
+  const PRUint32 numUnicharsPerVector = 8;
+
+#if PR_BYTES_PER_WORD == 4
+  const size_t mask = 0xff00ff00;
+  const PRUint32 numUnicharsPerWord = 2;
+#elif PR_BYTES_PER_WORD == 8
+  const size_t mask = 0xff00ff00ff00ff00;
+  const PRUint32 numUnicharsPerWord = 4;
+#else
+#error Unknown platform!
+#endif
+
+  const PRInt32 len = end - str;
+  PRInt32 i = 0;
+
+  // Align ourselves to a 16-byte boundary, as required by _mm_load_si128
+  // (i.e. MOVDQA).
+  PRInt32 alignLen =
+    PR_MIN(len, PRInt32(((-NS_PTR_TO_UINT32(str)) & 0xf) / sizeof(PRUnichar)));
+  for (; i < alignLen; i++) {
+    if (str[i] > 255)
+      return PR_FALSE;
+  }
+
+  // Check one XMM register (16 bytes) at a time.
+  const PRInt32 vectWalkEnd = ((len - i) / numUnicharsPerVector) * numUnicharsPerVector;
+  __m128i vectmask = _mm_set1_epi16(0xff00);
+  for(; i < vectWalkEnd; i += numUnicharsPerVector) {
+    const __m128i vect = *reinterpret_cast<const __m128i*>(str + i);
+    if (!is_zero(_mm_and_si128(vect, vectmask)))
+      return PR_FALSE;
+  }
+
+  // Check one word at a time.
+  const PRInt32 wordWalkEnd = ((len - i) / numUnicharsPerWord) * numUnicharsPerWord;
+  for(; i < wordWalkEnd; i += numUnicharsPerWord) {
+    const size_t word = *reinterpret_cast<const size_t*>(str + i);
+    if (word & mask)
+      return PR_FALSE;
+  }
+
+  // Take care of the remainder one character at a time.
+  for (; i < len; i++) {
+    if (str[i] > 255) {
+      return PR_FALSE;
+    }
+  }
+
+  return PR_TRUE;
+}
+
+} // namespace SSE2
+} // namespace mozilla
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -59,16 +59,19 @@
 #include "nsTextFragment.h"
 #include "nsString.h"
 #include "prprf.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsAttrName.h"
 #include "nsILineBreaker.h"
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla::dom;
 
 static const char kMozStr[] = "moz";
 
 #define kXMLNS "xmlns"
 
 // to be readable, we assume that an indented line contains
 // at least this number of characters (arbitrary value here).
 // This is a limit for the indentation.
@@ -910,18 +913,18 @@ nsXMLContentSerializer::SerializeAttribu
                    "Namespaced attributes must have a prefix");
       SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, PR_TRUE);
       PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
     }
   }
 }
 
 NS_IMETHODIMP 
-nsXMLContentSerializer::AppendElementStart(nsIContent *aElement,
-                                           nsIContent *aOriginalElement,
+nsXMLContentSerializer::AppendElementStart(Element* aElement,
+                                           Element* aOriginalElement,
                                            nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsIContent* content = aElement;
 
   PRBool forceFormat = PR_FALSE;
   if (!CheckElementStart(content, forceFormat, aStr)) {
@@ -1011,17 +1014,17 @@ nsXMLContentSerializer::AppendEndOfEleme
     AppendToString(NS_LITERAL_STRING("/>"), aStr);
   }
   else {
     AppendToString(kGreaterThan, aStr);
   }
 }
 
 NS_IMETHODIMP 
-nsXMLContentSerializer::AppendElementEnd(nsIContent *aElement,
+nsXMLContentSerializer::AppendElementEnd(Element* aElement,
                                          nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsIContent* content = aElement;
 
   PRBool forceFormat = PR_FALSE, outputElementEnd;
   outputElementEnd = CheckElementEnd(content, forceFormat, aStr);
--- a/content/base/src/nsXMLContentSerializer.h
+++ b/content/base/src/nsXMLContentSerializer.h
@@ -83,21 +83,21 @@ class nsXMLContentSerializer : public ns
                                          nsAString& aStr);
 
   NS_IMETHOD AppendComment(nsIContent* aComment, PRInt32 aStartOffset,
                            PRInt32 aEndOffset, nsAString& aStr);
   
   NS_IMETHOD AppendDoctype(nsIContent *aDoctype,
                            nsAString& aStr);
 
-  NS_IMETHOD AppendElementStart(nsIContent *aElement,
-                                nsIContent *aOriginalElement,
+  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
+                                mozilla::dom::Element* aOriginalElement,
                                 nsAString& aStr);
-  
-  NS_IMETHOD AppendElementEnd(nsIContent *aElement,
+
+  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
                               nsAString& aStr);
 
   NS_IMETHOD Flush(nsAString& aStr) { return NS_OK; }
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr);
 
  protected:
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -82,17 +82,16 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
 #include "nsLayoutStatics.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsDOMError.h"
 #include "nsIHTMLDocument.h"
-#include "nsIDOM3Document.h"
 #include "nsIMultiPartChannel.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIStorageStream.h"
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "nsIChannelPolicy.h"
@@ -141,18 +140,16 @@
   (XML_HTTP_REQUEST_UNINITIALIZED |         \
    XML_HTTP_REQUEST_OPENED |                \
    XML_HTTP_REQUEST_LOADED |                \
    XML_HTTP_REQUEST_INTERACTIVE |           \
    XML_HTTP_REQUEST_COMPLETED |             \
    XML_HTTP_REQUEST_SENT |                  \
    XML_HTTP_REQUEST_STOPPED)
 
-#define ACCESS_CONTROL_CACHE_SIZE 100
-
 #define NS_BADCERTHANDLER_CONTRACTID \
   "@mozilla.org/content/xmlhttprequest-bad-cert-handler;1"
 
 #define NS_PROGRESS_EVENT_INTERVAL 50
 
 class nsResumeTimeoutsEvent : public nsRunnable
 {
 public:
@@ -281,235 +278,16 @@ nsMultipartProxyListener::OnDataAvailabl
                                           nsIInputStream *inStr,
                                           PRUint32 sourceOffset,
                                           PRUint32 count)
 {
   return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset,
                                         count);
 }
 
-// Class used as streamlistener and notification callback when
-// doing the initial GET request for an access-control check
-class nsACProxyListener : public nsIStreamListener,
-                          public nsIInterfaceRequestor,
-                          public nsIChannelEventSink
-{
-public:
-  nsACProxyListener(nsIChannel* aOuterChannel,
-                    nsIStreamListener* aOuterListener,
-                    nsISupports* aOuterContext,
-                    nsIPrincipal* aReferrerPrincipal,
-                    const nsACString& aRequestMethod,
-                    PRBool aWithCredentials)
-   : mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
-     mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
-     mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials)
-  { }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSISTREAMLISTENER
-  NS_DECL_NSIREQUESTOBSERVER
-  NS_DECL_NSIINTERFACEREQUESTOR
-  NS_DECL_NSICHANNELEVENTSINK
-
-private:
-  void AddResultToCache(nsIRequest* aRequest);
-
-  nsCOMPtr<nsIChannel> mOuterChannel;
-  nsCOMPtr<nsIStreamListener> mOuterListener;
-  nsCOMPtr<nsISupports> mOuterContext;
-  nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
-  nsCString mRequestMethod;
-  PRBool mWithCredentials;
-};
-
-NS_IMPL_ISUPPORTS4(nsACProxyListener, nsIStreamListener, nsIRequestObserver,
-                   nsIInterfaceRequestor, nsIChannelEventSink)
-
-void
-nsACProxyListener::AddResultToCache(nsIRequest *aRequest)
-{
-  nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
-  NS_ASSERTION(http, "Request was not http");
-
-  // The "Access-Control-Max-Age" header should return an age in seconds.
-  nsCAutoString headerVal;
-  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Max-Age"),
-                          headerVal);
-  if (headerVal.IsEmpty()) {
-    return;
-  }
-
-  // Sanitize the string. We only allow 'delta-seconds' as specified by
-  // http://dev.w3.org/2006/waf/access-control (digits 0-9 with no leading or
-  // trailing non-whitespace characters).
-  PRUint32 age = 0;
-  nsCSubstring::const_char_iterator iter, end;
-  headerVal.BeginReading(iter);
-  headerVal.EndReading(end);
-  while (iter != end) {
-    if (*iter < '0' || *iter > '9') {
-      return;
-    }
-    age = age * 10 + (*iter - '0');
-    // Cap at 24 hours. This also avoids overflow
-    age = NS_MIN(age, 86400U);
-    ++iter;
-  }
-
-  if (!age || !nsXMLHttpRequest::EnsureACCache()) {
-    return;
-  }
-
-
-  // String seems fine, go ahead and cache.
-  // Note that we have already checked that these headers follow the correct
-  // syntax.
-
-  nsCOMPtr<nsIURI> uri;
-  NS_GetFinalChannelURI(http, getter_AddRefs(uri));
-
-  // PR_Now gives microseconds
-  PRTime expirationTime = PR_Now() + (PRUint64)age * PR_USEC_PER_SEC;
-
-  nsAccessControlLRUCache::CacheEntry* entry =
-    nsXMLHttpRequest::sAccessControlCache->
-    GetEntry(uri, mReferrerPrincipal, mWithCredentials, PR_TRUE);
-  if (!entry) {
-    return;
-  }
-
-  // The "Access-Control-Allow-Methods" header contains a comma separated
-  // list of method names.
-  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
-                          headerVal);
-
-  nsCCharSeparatedTokenizer methods(headerVal, ',');
-  while(methods.hasMoreTokens()) {
-    const nsDependentCSubstring& method = methods.nextToken();
-    if (method.IsEmpty()) {
-      continue;
-    }
-    PRUint32 i;
-    for (i = 0; i < entry->mMethods.Length(); ++i) {
-      if (entry->mMethods[i].token.Equals(method)) {
-        entry->mMethods[i].expirationTime = expirationTime;
-        break;
-      }
-    }
-    if (i == entry->mMethods.Length()) {
-      nsAccessControlLRUCache::TokenTime* newMethod =
-        entry->mMethods.AppendElement();
-      if (!newMethod) {
-        return;
-      }
-
-      newMethod->token = method;
-      newMethod->expirationTime = expirationTime;
-    }
-  }
-
-  // The "Access-Control-Allow-Headers" header contains a comma separated
-  // list of method names.
-  http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
-                          headerVal);
-
-  nsCCharSeparatedTokenizer headers(headerVal, ',');
-  while(headers.hasMoreTokens()) {
-    const nsDependentCSubstring& header = headers.nextToken();
-    if (header.IsEmpty()) {
-      continue;
-    }
-    PRUint32 i;
-    for (i = 0; i < entry->mHeaders.Length(); ++i) {
-      if (entry->mHeaders[i].token.Equals(header)) {
-        entry->mHeaders[i].expirationTime = expirationTime;
-        break;
-      }
-    }
-    if (i == entry->mHeaders.Length()) {
-      nsAccessControlLRUCache::TokenTime* newHeader =
-        entry->mHeaders.AppendElement();
-      if (!newHeader) {
-        return;
-      }
-
-      newHeader->token = header;
-      newHeader->expirationTime = expirationTime;
-    }
-  }
-}
-
-NS_IMETHODIMP
-nsACProxyListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
-{
-  nsresult status;
-  nsresult rv = aRequest->GetStatus(&status);
-
-  if (NS_SUCCEEDED(rv)) {
-    rv = status;
-  }
-
-  if (NS_SUCCEEDED(rv)) {
-    // Everything worked, try to cache and then fire off the actual request.
-    AddResultToCache(aRequest);
-
-    rv = mOuterChannel->AsyncOpen(mOuterListener, mOuterContext);
-  }
-
-  if (NS_FAILED(rv)) {
-    mOuterChannel->Cancel(rv);
-    mOuterListener->OnStartRequest(mOuterChannel, mOuterContext);
-    mOuterListener->OnStopRequest(mOuterChannel, mOuterContext, rv);
-    
-    return rv;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsACProxyListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
-                                 nsresult aStatus)
-{
-  return NS_OK;
-}
-
-/** nsIStreamListener methods **/
-
-NS_IMETHODIMP
-nsACProxyListener::OnDataAvailable(nsIRequest *aRequest,
-                                   nsISupports *ctxt,
-                                   nsIInputStream *inStr,
-                                   PRUint32 sourceOffset,
-                                   PRUint32 count)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsACProxyListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
-                                          nsIChannel *aNewChannel,
-                                          PRUint32 aFlags,
-                                          nsIAsyncVerifyRedirectCallback *callback)
-{
-  // Only internal redirects allowed for now.
-  if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags))
-    return NS_ERROR_DOM_BAD_URI;
-
-  callback->OnRedirectVerifyCallback(NS_OK);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsACProxyListener::GetInterface(const nsIID & aIID, void **aResult)
-{
-  return QueryInterface(aIID, aResult);
-}
-
 /////////////////////////////////////////////
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXHREventTarget,
                                                   nsDOMEventTargetWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
@@ -628,229 +406,21 @@ DOMCI_DATA(XMLHttpRequestUpload, nsXMLHt
 NS_INTERFACE_MAP_BEGIN(nsXMLHttpRequestUpload)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUpload)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XMLHttpRequestUpload)
 NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
 
 NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
 NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
 
-void
-nsAccessControlLRUCache::CacheEntry::PurgeExpired(PRTime now)
-{
-  PRUint32 i;
-  for (i = 0; i < mMethods.Length(); ++i) {
-    if (now >= mMethods[i].expirationTime) {
-      mMethods.RemoveElementAt(i--);
-    }
-  }
-  for (i = 0; i < mHeaders.Length(); ++i) {
-    if (now >= mHeaders[i].expirationTime) {
-      mHeaders.RemoveElementAt(i--);
-    }
-  }
-}
-
-PRBool
-nsAccessControlLRUCache::CacheEntry::CheckRequest(const nsCString& aMethod,
-                                                  const nsTArray<nsCString>& aHeaders)
-{
-  PurgeExpired(PR_Now());
-
-  if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
-    PRUint32 i;
-    for (i = 0; i < mMethods.Length(); ++i) {
-      if (aMethod.Equals(mMethods[i].token))
-        break;
-    }
-    if (i == mMethods.Length()) {
-      return PR_FALSE;
-    }
-  }
-
-  for (PRUint32 i = 0; i < aHeaders.Length(); ++i) {
-    PRUint32 j;
-    for (j = 0; j < mHeaders.Length(); ++j) {
-      if (aHeaders[i].Equals(mHeaders[j].token,
-                             nsCaseInsensitiveCStringComparator())) {
-        break;
-      }
-    }
-    if (j == mHeaders.Length()) {
-      return PR_FALSE;
-    }
-  }
-
-  return PR_TRUE;
-}
-
-nsAccessControlLRUCache::CacheEntry*
-nsAccessControlLRUCache::GetEntry(nsIURI* aURI,
-                                  nsIPrincipal* aPrincipal,
-                                  PRBool aWithCredentials,
-                                  PRBool aCreate)
-{
-  nsCString key;
-  if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
-    NS_WARNING("Invalid cache key!");
-    return nsnull;
-  }
-
-  CacheEntry* entry;
-
-  if (mTable.Get(key, &entry)) {
-    // Entry already existed so just return it. Also update the LRU list.
-
-    // Move to the head of the list.
-    PR_REMOVE_LINK(entry);
-    PR_INSERT_LINK(entry, &mList);
-
-    return entry;
-  }
-
-  if (!aCreate) {
-    return nsnull;
-  }
-
-  // This is a new entry, allocate and insert into the table now so that any
-  // failures don't cause items to be removed from a full cache.
-  entry = new CacheEntry(key);
-  if (!entry) {
-    NS_WARNING("Failed to allocate new cache entry!");
-    return nsnull;
-  }
-
-  if (!mTable.Put(key, entry)) {
-    // Failed, clean up the new entry.
-    delete entry;
-
-    NS_WARNING("Failed to add entry to the access control cache!");
-    return nsnull;
-  }
-
-  PR_INSERT_LINK(entry, &mList);
-
-  NS_ASSERTION(mTable.Count() <= ACCESS_CONTROL_CACHE_SIZE + 1,
-               "Something is borked, too many entries in the cache!");
-
-  // Now enforce the max count.
-  if (mTable.Count() > ACCESS_CONTROL_CACHE_SIZE) {
-    // Try to kick out all the expired entries.
-    PRTime now = PR_Now();
-    mTable.Enumerate(RemoveExpiredEntries, &now);
-
-    // If that didn't remove anything then kick out the least recently used
-    // entry.
-    if (mTable.Count() > ACCESS_CONTROL_CACHE_SIZE) {
-      CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList));
-      PR_REMOVE_LINK(lruEntry);
-
-      // This will delete 'lruEntry'.
-      mTable.Remove(lruEntry->mKey);
-
-      NS_ASSERTION(mTable.Count() == ACCESS_CONTROL_CACHE_SIZE,
-                   "Somehow tried to remove an entry that was never added!");
-    }
-  }
-  
-  return entry;
-}
-
-void
-nsAccessControlLRUCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
-{
-  CacheEntry* entry;
-  nsCString key;
-  if (GetCacheKey(aURI, aPrincipal, PR_TRUE, key) &&
-      mTable.Get(key, &entry)) {
-    PR_REMOVE_LINK(entry);
-    mTable.Remove(key);
-  }
-
-  if (GetCacheKey(aURI, aPrincipal, PR_FALSE, key) &&
-      mTable.Get(key, &entry)) {
-    PR_REMOVE_LINK(entry);
-    mTable.Remove(key);
-  }
-}
-
-void
-nsAccessControlLRUCache::Clear()
-{
-  PR_INIT_CLIST(&mList);
-  mTable.Clear();
-}
-
-/* static */ PLDHashOperator
-nsAccessControlLRUCache::RemoveExpiredEntries(const nsACString& aKey,
-                                              nsAutoPtr<CacheEntry>& aValue,
-                                              void* aUserData)
-{
-  PRTime* now = static_cast<PRTime*>(aUserData);
-  
-  aValue->PurgeExpired(*now);
-  
-  if (aValue->mHeaders.IsEmpty() &&
-      aValue->mHeaders.IsEmpty()) {
-    // Expired, remove from the list as well as the hash table.
-    PR_REMOVE_LINK(aValue);
-    return PL_DHASH_REMOVE;
-  }
-  
-  return PL_DHASH_NEXT;
-}
-
-/* static */ PRBool
-nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI,
-                                     nsIPrincipal* aPrincipal,
-                                     PRBool aWithCredentials,
-                                     nsACString& _retval)
-{
-  NS_ASSERTION(aURI, "Null uri!");
-  NS_ASSERTION(aPrincipal, "Null principal!");
-  
-  NS_NAMED_LITERAL_CSTRING(space, " ");
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, PR_FALSE);
-  
-  nsCAutoString scheme, host, port;
-  if (uri) {
-    uri->GetScheme(scheme);
-    uri->GetHost(host);
-    port.AppendInt(NS_GetRealPort(uri));
-  }
-
-  nsCAutoString cred;
-  if (aWithCredentials) {
-    _retval.AssignLiteral("cred");
-  }
-  else {
-    _retval.AssignLiteral("nocred");
-  }
-
-  nsCAutoString spec;
-  rv = aURI->GetSpec(spec);
-  NS_ENSURE_SUCCESS(rv, PR_FALSE);
-
-  _retval.Assign(cred + space + scheme + space + host + space + port + space +
-                 spec);
-
-  return PR_TRUE;
-}
-
 /////////////////////////////////////////////
 //
 //
 /////////////////////////////////////////////
 
-// Will be initialized in nsXMLHttpRequest::EnsureACCache.
-nsAccessControlLRUCache* nsXMLHttpRequest::sAccessControlCache = nsnull;
-
 nsXMLHttpRequest::nsXMLHttpRequest()
   : mRequestObserver(nsnull), mState(XML_HTTP_REQUEST_UNINITIALIZED),
     mUploadTransferred(0), mUploadTotal(0), mUploadComplete(PR_TRUE),
     mUploadProgress(0), mUploadProgressMax(0),
     mErrorLoad(PR_FALSE), mTimerIsActive(PR_FALSE),
     mProgressEventWasDelayed(PR_FALSE),
     mLoadLengthComputable(PR_FALSE), mLoadTotal(0),
     mFirstStartRequestSeen(PR_FALSE)
@@ -980,17 +550,17 @@ nsXMLHttpRequest::SetRequestObserver(nsI
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
                                                   nsXHREventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mResponseXML)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mACGetChannel)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCORSPreflightChannel)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressEventSink)
@@ -1001,17 +571,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
                                                 nsXHREventTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mResponseXML)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mACGetChannel)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCORSPreflightChannel)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressEventSink)
@@ -1358,18 +928,18 @@ NS_IMETHODIMP
 nsXMLHttpRequest::Abort()
 {
   if (mReadRequest) {
     mReadRequest->Cancel(NS_BINDING_ABORTED);
   }
   if (mChannel) {
     mChannel->Cancel(NS_BINDING_ABORTED);
   }
-  if (mACGetChannel) {
-    mACGetChannel->Cancel(NS_BINDING_ABORTED);
+  if (mCORSPreflightChannel) {
+    mCORSPreflightChannel->Cancel(NS_BINDING_ABORTED);
   }
   mResponseXML = nsnull;
   PRUint32 responseLength = mResponseBody.Length();
   mResponseBody.Truncate();
   mResponseBodyUnicode.SetIsVoid(PR_TRUE);
   mState |= XML_HTTP_REQUEST_ABORTED;
 
   if (!(mState & (XML_HTTP_REQUEST_UNINITIALIZED |
@@ -1385,17 +955,17 @@ nsXMLHttpRequest::Abort()
     if (mUpload && !mUploadComplete) {
       mUploadComplete = PR_TRUE;
       DispatchProgressEvent(mUpload, abortStr, PR_TRUE, mUploadTransferred,
                             mUploadTotal);
     }
   }
 
   // The ChangeState call above calls onreadystatechange handlers which
-  // if they load a new url will cause nsXMLHttpRequest::OpenRequest to clear
+  // if they load a new url will cause nsXMLHttpRequest::Open to clear
   // the abort state bit. If this occurs we're not uninitialized (bug 361773).
   if (mState & XML_HTTP_REQUEST_ABORTED) {
     ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE);  // IE seems to do it
   }
 
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
   return NS_OK;
@@ -1650,38 +1220,40 @@ nsXMLHttpRequest::CheckChannelForCrossSi
   mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
 
   // Check if we need to do a preflight request.
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
   NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);
     
   nsCAutoString method;
   httpChannel->GetRequestMethod(method);
-  if (!mACUnsafeHeaders.IsEmpty() ||
+  if (!mCORSUnsafeHeaders.IsEmpty() ||
       HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) ||
       (mUpload && mUpload->HasListeners()) ||
       (!method.LowerCaseEqualsLiteral("get") &&
        !method.LowerCaseEqualsLiteral("post") &&
        !method.LowerCaseEqualsLiteral("head"))) {
     mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
   }
 
   return NS_OK;
 }
 
-/* noscript void openRequest (in AUTF8String method, in AUTF8String url, in boolean async, in AString user, in AString password); */
 NS_IMETHODIMP
-nsXMLHttpRequest::OpenRequest(const nsACString& method,
-                              const nsACString& url,
-                              PRBool async,
-                              const nsAString& user,
-                              const nsAString& password)
+nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
+                       PRBool async, const nsAString& user,
+                       const nsAString& password, PRUint8 optional_argc)
 {
   NS_ENSURE_ARG(!method.IsEmpty());
 
+  if (!optional_argc) {
+    // No optional arguments were passed in. Default async to true.
+    async = PR_TRUE;
+  }
+
   NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
 
   // Disallow HTTP/1.1 TRACE method (see bug 302489)
   // and MS IIS equivalent TRACK (see bug 381264)
   if (method.LowerCaseEqualsLiteral("trace") ||
       method.LowerCaseEqualsLiteral("track")) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -1801,30 +1373,16 @@ nsXMLHttpRequest::OpenRequest(const nsAC
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   ChangeState(XML_HTTP_REQUEST_OPENED);
 
   return rv;
 }
 
-/* void open (in AUTF8String method, in AUTF8String url); */
-NS_IMETHODIMP
-nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
-                       PRBool async, const nsAString& user,
-                       const nsAString& password, PRUint8 optional_argc)
-{
-  if (!optional_argc) {
-    // No optional arguments were passed in. Default async to true.
-    async = PR_TRUE;
-  }
-
-  return OpenRequest(method, url, async, user, password);
-}
-
 /*
  * "Copy" from a stream.
  */
 NS_METHOD
 nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in,
                                    void* closure,
                                    const char* fromRawSegment,
                                    PRUint32 toOffset,
@@ -2274,23 +1832,20 @@ GetRequestBody(nsIVariant* aBody, nsIInp
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsMemory::Free(iid);
 
     // document?
     nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(supports);
     if (doc) {
       aContentType.AssignLiteral("application/xml");
-      nsCOMPtr<nsIDOM3Document> dom3doc = do_QueryInterface(doc);
-      if (dom3doc) {
-        nsAutoString inputEncoding;
-        dom3doc->GetInputEncoding(inputEncoding);
-        if (!DOMStringIsNull(inputEncoding)) {
-          CopyUTF16toUTF8(inputEncoding, aCharset);
-        }
+      nsAutoString inputEncoding;
+      doc->GetInputEncoding(inputEncoding);
+      if (!DOMStringIsNull(inputEncoding)) {
+        CopyUTF16toUTF8(inputEncoding, aCharset);
       }
 
       // Serialize to a stream so that the encoding used will
       // match the document's.
       nsCOMPtr<nsIDOMSerializer> serializer =
         do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2566,86 +2121,51 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
     if (NS_SUCCEEDED(rv)) {
       nsCAutoString contentType, charset;
       rv = NS_ParseContentType(contentTypeHeader, contentType, charset);
       NS_ENSURE_SUCCESS(rv, rv);
   
       if (!contentType.LowerCaseEqualsLiteral("text/plain") &&
           !contentType.LowerCaseEqualsLiteral("application/x-www-form-urlencoded") &&
           !contentType.LowerCaseEqualsLiteral("multipart/form-data")) {
-        mACUnsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
+        mCORSUnsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
       }
     }
   }
 
   // Reset responseBody
   mResponseBody.Truncate();
   mResponseBodyUnicode.SetIsVoid(PR_TRUE);
 
   // Reset responseXML
   mResponseXML = nsnull;
 
   rv = CheckChannelForCrossSiteRequest(mChannel);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRBool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
 
-  // If so, set up the preflight
-  if (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT) {
-    // Check to see if this initial OPTIONS request has already been cached
-    // in our special Access Control Cache.
-    nsCOMPtr<nsIURI> uri;
-    rv = NS_GetFinalChannelURI(mChannel, getter_AddRefs(uri));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsAccessControlLRUCache::CacheEntry* entry =
-      sAccessControlCache ?
-      sAccessControlCache->GetEntry(uri, mPrincipal, withCredentials, PR_FALSE) :
-      nsnull;
-
-    if (!entry || !entry->CheckRequest(method, mACUnsafeHeaders)) {
-      // Either it wasn't cached or the cached result has expired. Build a
-      // channel for the OPTIONS request.
-      nsCOMPtr<nsILoadGroup> loadGroup;
-      GetLoadGroup(getter_AddRefs(loadGroup));
-
-      nsLoadFlags loadFlags;
-      rv = mChannel->GetLoadFlags(&loadFlags);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      rv = NS_NewChannel(getter_AddRefs(mACGetChannel), uri, nsnull,
-                         loadGroup, nsnull, loadFlags);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsCOMPtr<nsIHttpChannel> acHttp = do_QueryInterface(mACGetChannel);
-      NS_ASSERTION(acHttp, "Failed to QI to nsIHttpChannel!");
-
-      rv = acHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
   // Hook us up to listen to redirects and the like
   mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
   mChannel->SetNotificationCallbacks(this);
 
   // Create our listener
   nsCOMPtr<nsIStreamListener> listener = this;
   if (mState & XML_HTTP_REQUEST_MULTIPART) {
     listener = new nsMultipartProxyListener(listener);
     if (!listener) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   if (!IsSystemXHR()) {
-    // Always create a nsCrossSiteListenerProxy here even if it's
+    // Always create a nsCORSListenerProxy here even if it's
     // a same-origin request right now, since it could be redirected.
-    listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
-                                            withCredentials, &rv);
+    listener = new nsCORSListenerProxy(listener, mPrincipal, mChannel,
+                                       withCredentials, &rv);
     NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Bypass the network cache in cases where it makes no sense:
   // 1) Multipart responses are very large and would likely be doomed by the
   //    cache once they grow too large, so they are not worth caching.
   // 2) POST responses are always unique, and we provide no API that would
@@ -2656,53 +2176,43 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
         nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::INHIBIT_CACHING);
   }
   // When we are sync loading, we need to bypass the local cache when it would
   // otherwise block us waiting for exclusive access to the cache.  If we don't
   // do this, then we could dead lock in some cases (see bug 309424).
   else if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
     AddLoadFlags(mChannel,
         nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY);
-    if (mACGetChannel) {
-      AddLoadFlags(mACGetChannel,
-          nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY);
-    }
   }
 
   // Since we expect XML data, set the type hint accordingly
   // This means that we always try to parse local files as XML
   // ignoring return value, as this is not critical
   mChannel->SetContentType(NS_LITERAL_CSTRING("application/xml"));
 
-  // If we're doing a cross-site non-GET request we need to first do
-  // a GET request to the same URI. Set that up if needed
-  if (mACGetChannel) {
-    nsCOMPtr<nsIStreamListener> acProxyListener =
-      new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method,
-                            withCredentials);
-    NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
-
-    acProxyListener =
-      new nsCrossSiteListenerProxy(acProxyListener, mPrincipal, mACGetChannel,
-                                   withCredentials, method, mACUnsafeHeaders,
-                                   &rv);
-    NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
+  // Set up the preflight if needed
+  if (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT) {
+    // Check to see if this initial OPTIONS request has already been cached
+    // in our special Access Control Cache.
+
+    rv = NS_StartCORSPreflight(mChannel, listener,
+                               mPrincipal, withCredentials,
+                               mCORSUnsafeHeaders,
+                               getter_AddRefs(mCORSPreflightChannel));
     NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mACGetChannel->AsyncOpen(acProxyListener, nsnull);
   }
   else {
     // Start reading from the channel
     rv = mChannel->AsyncOpen(listener, nsnull);
   }
 
   if (NS_FAILED(rv)) {
     // Drop our ref to the channel to avoid cycles
     mChannel = nsnull;
-    mACGetChannel = nsnull;
+    mCORSPreflightChannel = nsnull;
     return rv;
   }
 
   // If we're synchronous, spin an event loop here and wait
   if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
     mState |= XML_HTTP_REQUEST_SYNCLOOPING;
 
     nsCOMPtr<nsIDocument> suspendedDoc;
@@ -2769,27 +2279,27 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
 
 /* void setRequestHeader (in AUTF8String header, in AUTF8String value); */
 NS_IMETHODIMP
 nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
                                    const nsACString& value)
 {
   nsresult rv;
 
-  // Make sure we don't store an invalid header name in mACUnsafeHeaders
+  // Make sure we don't store an invalid header name in mCORSUnsafeHeaders
   if (!IsValidHTTPToken(header)) {
     return NS_ERROR_FAILURE;
   }
 
   // Check that we haven't already opened the channel. We can't rely on
   // the channel throwing from mChannel->SetRequestHeader since we might
-  // still be waiting for mACGetChannel to actually open mChannel
-  if (mACGetChannel) {
+  // still be waiting for mCORSPreflightChannel to actually open mChannel
+  if (mCORSPreflightChannel) {
     PRBool pending;
-    rv = mACGetChannel->IsPending(&pending);
+    rv = mCORSPreflightChannel->IsPending(&pending);
     NS_ENSURE_SUCCESS(rv, rv);
     
     if (pending) {
       return NS_ERROR_IN_PROGRESS;
     }
   }
 
   if (!mChannel)             // open() initializes mChannel, and open()
@@ -2844,17 +2354,17 @@ nsXMLHttpRequest::SetRequestHeader(const
         if (header.LowerCaseEqualsASCII(kCrossOriginSafeHeaders[i])) {
           safeHeader = true;
           break;
         }
       }
     }
 
     if (!safeHeader) {
-      mACUnsafeHeaders.AppendElement(header);
+      mCORSUnsafeHeaders.AppendElement(header);
     }
   }
 
   // We need to set, not add to, the header.
   return httpChannel->SetRequestHeader(header, value, PR_FALSE);
 }
 
 /* readonly attribute long readyState; */
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -55,96 +55,26 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIHttpHeaderVisitor.h"
 #include "nsIProgressEventSink.h"
 #include "nsCOMArray.h"
 #include "nsJSUtils.h"
 #include "nsTArray.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIDOMLSProgressEvent.h"
-#include "nsClassHashtable.h"
-#include "nsHashKeys.h"
-#include "prclist.h"
-#include "prtime.h"
 #include "nsIDOMNSEvent.h"
 #include "nsITimer.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsDOMProgressEvent.h"
 #include "nsDOMEventTargetWrapperCache.h"
 #include "nsContentUtils.h"
 
 class nsILoadGroup;
 class AsyncVerifyRedirectCallbackForwarder;
 
-class nsAccessControlLRUCache
-{
-public:
-  struct TokenTime
-  {
-    nsCString token;
-    PRTime expirationTime;
-  };
-
-  struct CacheEntry : public PRCList
-  {
-    CacheEntry(nsCString& aKey)
-      : mKey(aKey)
-    {
-      MOZ_COUNT_CTOR(nsAccessControlLRUCache::CacheEntry);
-    }
-    
-    ~CacheEntry()
-    {
-      MOZ_COUNT_DTOR(nsAccessControlLRUCache::CacheEntry);
-    }
-
-    void PurgeExpired(PRTime now);
-    PRBool CheckRequest(const nsCString& aMethod,
-                        const nsTArray<nsCString>& aCustomHeaders);
-
-    nsCString mKey;
-    nsTArray<TokenTime> mMethods;
-    nsTArray<TokenTime> mHeaders;
-  };
-
-  nsAccessControlLRUCache()
-  {
-    MOZ_COUNT_CTOR(nsAccessControlLRUCache);
-    PR_INIT_CLIST(&mList);
-  }
-
-  ~nsAccessControlLRUCache()
-  {
-    Clear();
-    MOZ_COUNT_DTOR(nsAccessControlLRUCache);
-  }
-
-  PRBool Initialize()
-  {
-    return mTable.Init();
-  }
-
-  CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
-                       PRBool aWithCredentials, PRBool aCreate);
-  void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal);
-
-  void Clear();
-
-private:
-  static PLDHashOperator
-    RemoveExpiredEntries(const nsACString& aKey, nsAutoPtr<CacheEntry>& aValue,
-                         void* aUserData);
-
-  static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
-                            PRBool aWithCredentials, nsACString& _retval);
-
-  nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
-  PRCList mList;
-};
-
 class nsXHREventTarget : public nsDOMEventTargetWrapperCache,
                          public nsIXMLHttpRequestEventTarget
 {
 public:
   virtual ~nsXHREventTarget() {}
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
                                            nsDOMEventTargetWrapperCache)
@@ -276,42 +206,18 @@ public:
   // This is called by the factory constructor.
   nsresult Init();
 
   void SetRequestObserver(nsIRequestObserver* aObserver);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
                                            nsXHREventTarget)
 
-  static PRBool EnsureACCache()
-  {
-    if (sAccessControlCache)
-      return PR_TRUE;
-
-    nsAutoPtr<nsAccessControlLRUCache> newCache(new nsAccessControlLRUCache());
-    NS_ENSURE_TRUE(newCache, PR_FALSE);
-
-    if (newCache->Initialize()) {
-      sAccessControlCache = newCache.forget();
-      return PR_TRUE;
-    }
-
-    return PR_FALSE;
-  }
-
-  static void ShutdownACCache()
-  {
-    delete sAccessControlCache;
-    sAccessControlCache = nsnull;
-  }
-
   PRBool AllowUploadProgress();
 
-  static nsAccessControlLRUCache* sAccessControlCache;
-
 protected:
   friend class nsMultipartProxyListener;
 
   nsresult DetectCharset(nsACString& aCharset);
   nsresult ConvertBodyToText(nsAString& aOutBuffer);
   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
                 void* closure,
                 const char* fromRawSegment,
@@ -352,18 +258,18 @@ protected:
   void OnRedirectVerifyCallback(nsresult result);
 
   nsCOMPtr<nsISupports> mContext;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   // mReadRequest is different from mChannel for multipart requests
   nsCOMPtr<nsIRequest> mReadRequest;
   nsCOMPtr<nsIDOMDocument> mResponseXML;
-  nsCOMPtr<nsIChannel> mACGetChannel;
-  nsTArray<nsCString> mACUnsafeHeaders;
+  nsCOMPtr<nsIChannel> mCORSPreflightChannel;
+  nsTArray<nsCString> mCORSUnsafeHeaders;
 
   nsRefPtr<nsDOMEventListenerWrapper> mOnUploadProgressListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnReadystatechangeListener;
 
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
 
   // used to implement getAllResponseHeaders()
   class nsHeaderVisitor : public nsIHttpHeaderVisitor {
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -275,16 +275,17 @@ include $(topsrcdir)/config/rules.mk
 		file_CrossSiteXHR_server.sjs \
 		test_CrossSiteXHR_cache.html \
 		file_CrossSiteXHR_cache_server.sjs \
 		test_XHRDocURI.html \
 		file_XHRDocURI.xml \
 		file_XHRDocURI.xml^headers^ \
 		file_XHRDocURI.text \
 		file_XHRDocURI.text^headers^ \
+		test_DOMException.html \
 		$(NULL)
 
 _TEST_FILES2 = \
 		test_bug459424.html \
 		bug461735-redirect1.sjs \
 		bug461735-redirect2.sjs \
 		bug461735-post-redirect.js \
 		test_bug513194.html \
@@ -426,16 +427,17 @@ include $(topsrcdir)/config/rules.mk
 		test_createHTMLDocument.html \
 		test_bug622088.html \
 		file_bug622088_inner.html \
 		file_bug622088.sjs \
 		test_bug564047.html \
 		test_bug567350.html \
 		test_bug574596.html \
 		test_bug578096.html \
+		test_bug585978.html \
 		test_bug592366.html \
 		test_bug597345.html \
 		script-1_bug597345.sjs \
 		script-2_bug597345.js \
 		test_bug598877.html \
 		test_bug599588.html \
 		test_bug600466.html \
 		test_bug600468.html \
--- a/content/base/test/TestGetURL.cpp
+++ b/content/base/test/TestGetURL.cpp
@@ -71,17 +71,17 @@ nsresult TestGetURL(const nsCString& aUR
 
   nsCOMPtr<nsIPrincipal> systemPrincipal;
   rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
   TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
 
   rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
 
-  rv = xhr->OpenRequest(getString, aURL, PR_FALSE, empty, empty);
+  rv = xhr->Open(getString, aURL, PR_FALSE, empty, empty);
   TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
 
   rv = xhr->Send(nsnull);
   TEST_ENSURE_SUCCESS(rv, "Send failed!");
 
   nsAutoString response;
   rv = xhr->GetResponseText(response);
   TEST_ENSURE_SUCCESS(rv, "GetResponse failed!");
--- a/content/base/test/TestNativeXMLHttpRequest.cpp
+++ b/content/base/test/TestNativeXMLHttpRequest.cpp
@@ -72,33 +72,33 @@ nsresult TestNativeXMLHttpRequest()
     do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
   TEST_ENSURE_SUCCESS(rv, "Couldn't create nsIXMLHttpRequest instance!");
 
   NS_NAMED_LITERAL_CSTRING(getString, "GET");
   NS_NAMED_LITERAL_CSTRING(testURL, TEST_URL);
   const nsAString& empty = EmptyString();
   
   printf("*** About to see an expected warning about mPrincipal:\n");
-  rv = xhr->OpenRequest(getString, testURL, PR_FALSE, empty, empty);
+  rv = xhr->Open(getString, testURL, PR_FALSE, empty, empty);
   printf("*** End of expected warning output.\n");
-  TEST_ENSURE_FAILED(rv, "OpenRequest should have failed!");
+  TEST_ENSURE_FAILED(rv, "Open should have failed!");
 
   nsCOMPtr<nsIScriptSecurityManager> secman =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   TEST_ENSURE_SUCCESS(rv, "Couldn't get script security manager!");
 
   nsCOMPtr<nsIPrincipal> systemPrincipal;
   rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
   TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
 
   rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
 
-  rv = xhr->OpenRequest(getString, testURL, PR_FALSE, empty, empty);
-  TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
+  rv = xhr->Open(getString, testURL, PR_FALSE, empty, empty);
+  TEST_ENSURE_SUCCESS(rv, "Open failed!");
 
   rv = xhr->Send(nsnull);
   TEST_ENSURE_SUCCESS(rv, "Send failed!");
 
   nsAutoString response;
   rv = xhr->GetResponseText(response);
   TEST_ENSURE_SUCCESS(rv, "GetResponse failed!");
 
--- a/content/base/test/file_CrossSiteXHR_inner.html
+++ b/content/base/test/file_CrossSiteXHR_inner.html
@@ -20,17 +20,17 @@ window.addEventListener("message", funct
     status: 0,
     responseText: "",
     statusText: "",
     responseXML: null,
     sendThrew: false
   };
   
   var xhr = new XMLHttpRequest();
-  for each(type in ["load", "abort", "error", "loadstart"]) {
+  for each(type in ["load", "abort", "error", "loadstart", "loadend"]) {
     xhr.addEventListener(type, function(e) {
       res.events.push(e.type);
     }, false);
   }
   xhr.addEventListener("readystatechange", function(e) {
     res.events.push("rs" + xhr.readyState);
   }, false);
   xhr.addEventListener("progress", function(e) {
@@ -43,20 +43,20 @@ window.addEventListener("message", funct
       }, false);
     }
     else {
       xhr.upload.addEventListener(req.uploadProgress, function(e) {
         res.progressEvents++;
       }, false);
     }
   }
-  xhr.onload = xhr.onerror = function (event) {
-    if (event.type == "error") {
-      res.didFail = true;
-    }
+  xhr.onerror = function(e) {
+    res.didFail = true;
+  };
+  xhr.onloadend = function (event) {
     res.status = xhr.status;
     try {
       res.statusText = xhr.statusText;
     } catch (e) {
       delete(res.statusText);
     }
     res.responseXML = xhr.responseXML ?
       (new XMLSerializer()).serializeToString(xhr.responseXML) :
index 87bf9568d05b9ada2aafa666e29c66a9e70eda76..9fc85c29c082b1d4c8825c73154fbb1cf91dd7f5
GIT binary patch
literal 1168
zc$^FHW@Zs#U|`^2n9*2aH&g9R!69Y_1}82C1{oks%gjlQcP`2=E)LEtNsaIbiqFi;
zOD)pND9OzU4dG;9et*8(_vVFe-_i<h21b@|j0_B5)7FMX```8wsQbQN;!jHVgE_~w
zSXOlv9htbmRfXTyi6i%|=bovXU%y+&nR&F{ezUmxw#i#ol~izAe?M(*Ja1mjpBmHu
z-~UPFJuBZn{o<D=Z*-V`e5tIfW%?|nIQ`H90|oH}uXTwBwOM}Y&f4|J(l~-ayzf`d
z(k0i7^FEwDd)Qc<DfC;f=B8sVg+7mVCbXsgnyt3+H`h$JjI2e9m6N}0$ddZOWVY#M
z;fehsGhEZtrw5woo?W%*gm((--xo0-Z^gJ}>v8Qo7ZDh<KY(d_Ot9RFNfoV8n^lh~
zN0=y?$8@m-|Bwu1k#hYwk*SGWz&CVm^sGbgzZ?+{Q=M@$<8tw$eFm;FzH{b(VbZAh
zX#V&ri`be=7DXmo>b|nb&HuAItjN>qm(_*;pHgyXWS03)TCwzk#qn_CMvHe`Uo+P}
znZEmWXSaDrkkIF#hgK}kN6e**I(}^pF|&<fetB0S*#5zHwymBqaoj5zBIDH3f)~Gi
zlN{q27O*ktTc}p@f5)XuHvNy_V|}*ro8!F4%T1=V$h-}|KTB3jP9bIT&#u(c#ok)m
zrj|MeGAYmRuHNVB-gCT5VZ+9yhxVjAa_Hx`?3&v5@JeLKFXPqkWlQ(UeY^4P%ZlZ7
zm;L>}zY*Fdd?>>0vy12+{zq#&56A4-(Xhk6t9+`B%u9zq1;TyD_grVa&+cR?Sha5N
z;=df<F8`RHl=0C)`=HX~3$;5$6Wu!VLz<tzjj6cGaKFz;g-<n>yN=8A*sCAy{D)Wg
z@}JmU_?9!;sY5!W{F!Qru>J<8X3zNj;n}BO`P6Q>yL1o#wn+vLj6>#x{$amr?`wQ_
z-?O4L5%JS03+5kEk@)aC|HYQcfzzLerN)11bK{&EJt6;IU#za@{9N&#)}sz9_lvNd
zIsWfAr{1<58xwUe+I(SQ)7$>_i+1FtM~hosj1sq&s1=>{tz5dnWBcnhO9gaR^zCY1
z683zxj@ipH-uCEAMu%)A*T_dMUJ!Ofui>MFUC7iJ=d)X$c|Yva-g(Qx`K)kH-}M`t
zt_6uoZD}!`o1u2#0^9P#9jjMxyRqjQy?2UMoO>nd$)d~<)1r<2+m3$T&>3xB_`;X#
z{a&{Phu{4x*>Y<_Ta@nIEW>BPcO3tJy?(iJi7lUdD!+ZIym{UO9lkq>+y)<v7O(rW
z_<!xKoA<K&-agu9`S(y%*rl?c{>H`5_vBvPe|qO;<;61V(x-Eb&uqyF>6`iV&d+|C
z?LIwoEZrtunyL5lk^iyBQ_pzMi@f4<@8bNk{W8AC-(J65B4f8)Cr^KI{hRGliA9}9
zKB`PAxF7qUF~FOVNsbv;$soZ10>IqPu%r>h!e36XLdprWG9tj6l?`GFBSR99mS6$#
E0KAtMt^fc4
--- a/content/base/test/file_CrossSiteXHR_inner_data.sjs
+++ b/content/base/test/file_CrossSiteXHR_inner_data.sjs
@@ -9,17 +9,17 @@ window.addEventListener("message", funct
   req = eval(e.data);\n\
   var res = {\n\
     didFail: false,\n\
     events: [],\n\
     progressEvents: 0\n\
   };\n\
   \n\
   var xhr = new XMLHttpRequest();\n\
-  for each(type in ["load", "abort", "error", "loadstart"]) {\n\
+  for each(type in ["load", "abort", "error", "loadstart", "loadend"]) {\n\
     xhr.addEventListener(type, function(e) {\n\
       res.events.push(e.type);\n\
     }, false);\n\
   }\n\
   xhr.addEventListener("readystatechange", function(e) {\n\
     res.events.push("rs" + xhr.readyState);\n\
   }, false);\n\
   xhr.addEventListener("progress", function(e) {\n\
@@ -32,36 +32,37 @@ window.addEventListener("message", funct
       }, false);\n\
     }\n\
     else {\n\
       xhr.upload.addEventListener(req.uploadProgress, function(e) {\n\
         res.progressEvents++;\n\
       }, false);\n\
     }\n\
   }\n\
-  xhr.onload = function () {\n\
-    res.status = xhr.status;\n\
-    res.statusText = xhr.statusText;\n\
-    res.responseXML = xhr.responseXML ?\n\
-      (new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
-      null;\n\
-    res.responseText = xhr.responseText;\n\
-    post(e, res);\n\
+  xhr.onerror = function(e) {\n\
+    res.didFail = true;\n\
   };\n\
-  xhr.onerror = function () {\n\
-    res.didFail = true;\n\
+  xhr.onloadend = function (event) {\n\
     res.status = xhr.status;\n\
     try {\n\
       res.statusText = xhr.statusText;\n\
     } catch (e) {\n\
+      delete(res.statusText);\n\
     }\n\
     res.responseXML = xhr.responseXML ?\n\
       (new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
       null;\n\
     res.responseText = xhr.responseText;\n\
+\n\
+    res.responseHeaders = {};\n\
+    for (responseHeader in req.responseHeaders) {\n\
+      res.responseHeaders[responseHeader] =\n\
+        xhr.getResponseHeader(responseHeader);\n\
+    }\n\
+\n\
     post(e, res);\n\
   }\n\
 \n\
   if (req.withCred)\n\
     xhr.withCredentials = true;\n\
   if (req.body)\n\
     sendData = req.body;\n\
 \n\
--- a/content/base/test/test_CrossSiteXHR.html
+++ b/content/base/test/test_CrossSiteXHR.html
@@ -651,26 +651,26 @@ function runTest() {
         is(res.statusText, "OK", "wrong status text for " + test.toSource());
       }
       if (test.method !== "HEAD") {
         is(res.responseXML, "<res>hello pass</res>",
            "wrong responseXML in test for " + test.toSource());
         is(res.responseText, "<res>hello pass</res>\n",
            "wrong responseText in test for " + test.toSource());
         is(res.events.join(","),
-           "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+           "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
            "wrong responseText in test for " + test.toSource());
       }
       else {
         is(res.responseXML, null,
            "wrong responseXML in test for " + test.toSource());
         is(res.responseText, "",
            "wrong responseText in test for " + test.toSource());
         is(res.events.join(","),
-           "opening,rs1,sending,rs1,loadstart,rs2,rs4,load",
+           "opening,rs1,sending,rs1,loadstart,rs2,rs4,load,loadend",
            "wrong responseText in test for " + test.toSource());
       }
       if (test.responseHeaders) {
         for (header in test.responseHeaders) {
           if (test.expectedResponseHeaders.indexOf(header) == -1) {
             is(res.responseHeaders[header], null,
                "wrong response header (" + header + ") in test for " +
                test.toSource());
@@ -689,17 +689,17 @@ function runTest() {
       is(res.status, 0, "wrong status in test for " + test.toSource());
       is(res.statusText, "", "wrong status text for " + test.toSource());
       is(res.responseXML, null,
          "wrong responseXML in test for " + test.toSource());
       is(res.responseText, "",
          "wrong responseText in test for " + test.toSource());
       if (!res.sendThrew) {
         is(res.events.join(","),
-           "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+           "opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
            "wrong events in test for " + test.toSource());
       }
       is(res.progressEvents, 0,
          "wrong events in test for " + test.toSource());
       if (test.responseHeaders) {
         for (header in test.responseHeaders) {
           is(res.responseHeaders[header], null,
              "wrong response header (" + header + ") in test for " +
@@ -817,30 +817,30 @@ function runTest() {
         "shouldn't have failed in test for " + test.toSource());
       is(res.status, 200, "wrong status in test for " + test.toSource());
       is(res.statusText, "OK", "wrong status text for " + test.toSource());
       is(res.responseXML, "<res>hello pass</res>",
          "wrong responseXML in test for " + test.toSource());
       is(res.responseText, "<res>hello pass</res>\n",
          "wrong responseText in test for " + test.toSource());
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
          "wrong responseText in test for " + test.toSource());
     }
     else {
       is(res.didFail, true,
         "should have failed in test for " + test.toSource());
       is(res.status, 0, "wrong status in test for " + test.toSource());
       is(res.statusText, "", "wrong status text for " + test.toSource());
       is(res.responseXML, null,
          "wrong responseXML in test for " + test.toSource());
       is(res.responseText, "",
          "wrong responseText in test for " + test.toSource());
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
          "wrong events in test for " + test.toSource());
       is(res.progressEvents, 0,
          "wrong events in test for " + test.toSource());
     }
   }
 
   // Test redirects
   is(loader.src, "http://example.org/tests/content/base/test/file_CrossSiteXHR_inner.html");
@@ -1086,30 +1086,30 @@ function runTest() {
         "shouldn't have failed in test for " + test.toSource());
       is(res.status, 200, "wrong status in test for " + test.toSource());
       is(res.statusText, "OK", "wrong status text for " + test.toSource());
       is(res.responseXML, "<res>hello pass</res>",
          "wrong responseXML in test for " + test.toSource());
       is(res.responseText, "<res>hello pass</res>\n",
          "wrong responseText in test for " + test.toSource());
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
          "wrong responseText in test for " + test.toSource());
     }
     else {
       is(res.didFail, true,
         "should have failed in test for " + test.toSource());
       is(res.status, 0, "wrong status in test for " + test.toSource());
       is(res.statusText, "", "wrong status text for " + test.toSource());
       is(res.responseXML, null,
          "wrong responseXML in test for " + test.toSource());
       is(res.responseText, "",
          "wrong responseText in test for " + test.toSource());
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
          "wrong events in test for " + test.toSource());
       is(res.progressEvents, 0,
          "wrong progressevents in test for " + test.toSource());
     }
   }
 
 
   SimpleTest.finish();
--- a/content/base/test/test_CrossSiteXHR_cache.html
+++ b/content/base/test/test_CrossSiteXHR_cache.html
@@ -459,37 +459,35 @@ function runTest() {
       is(res.didFail, false,
         "shouldn't have failed in test for " + testName);
       is(res.status, 200, "wrong status in test for " + testName);
       is(res.responseXML, "<res>hello pass</res>",
          "wrong responseXML in test for " + testName);
       is(res.responseText, "<res>hello pass</res>\n",
          "wrong responseText in test for " + testName);
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
          "wrong events in test for " + testName);
     }
     else {
       is(res.didFail, true,
         "should have failed in test for " + testName);
       is(res.status, 0, "wrong status in test for " + testName);
       is(res.responseXML, null,
          "wrong responseXML in test for " + testName);
       is(res.responseText, "",
          "wrong responseText in test for " + testName);
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
          "wrong events in test for " + testName);
       is(res.progressEvents, 0,
          "wrong events in test for " + testName);
     }
   }
 
-
-
   SimpleTest.finish();
 
   yield;
 }
 
 </script>
 </pre>
 </body>
--- a/content/base/test/test_CrossSiteXHR_origin.html
+++ b/content/base/test/test_CrossSiteXHR_origin.html
@@ -128,17 +128,17 @@ function runTest() {
       is(res.status, 200, "wrong status for " + allowOrigin);
       is(res.statusText, "OK", "wrong status text for " + allowOrigin);
       is(res.responseXML,
          "<res>hello pass</res>",
          "wrong responseXML in test for " + allowOrigin);
       is(res.responseText, "<res>hello pass</res>\n",
          "wrong responseText in test for " + allowOrigin);
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
          "wrong responseText in test for " + allowOrigin);
     }
 
     for each(allowOrigin in failTests) {
       req = {
         url: baseURL + "allowOrigin=" + escape(allowOrigin),
         method: "GET",
       };
@@ -146,17 +146,17 @@ function runTest() {
 
       res = eval(yield);
       is(res.didFail, true, "should have failed for " + allowOrigin);
       is(res.responseText, "", "should have no text for " + allowOrigin);
       is(res.status, 0, "should have no status for " + allowOrigin);
       is(res.statusText, "", "wrong status text for " + allowOrigin);
       is(res.responseXML, null, "should have no XML for " + allowOrigin);
       is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
          "wrong events in test for " + allowOrigin);
       is(res.progressEvents, 0,
          "wrong events in test for " + allowOrigin);
     }
   }
 
   SimpleTest.finish();
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_DOMException.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for DOMException constants</title>
+  <script src="/MochiKit/packed.js"></script>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script>
+var constants = [
+  null,
+  "INDEX_SIZE_ERR",
+  "DOMSTRING_SIZE_ERR",
+  "HIERARCHY_REQUEST_ERR",
+  "WRONG_DOCUMENT_ERR",
+  "INVALID_CHARACTER_ERR",
+  "NO_DATA_ALLOWED_ERR",
+  "NO_MODIFICATION_ALLOWED_ERR",
+  "NOT_FOUND_ERR",
+  "NOT_SUPPORTED_ERR",
+  "INUSE_ATTRIBUTE_ERR",
+  "INVALID_STATE_ERR",
+  "SYNTAX_ERR",
+  "INVALID_MODIFICATION_ERR",
+  "NAMESPACE_ERR",
+  "INVALID_ACCESS_ERR",
+  "VALIDATION_ERR",
+  "TYPE_MISMATCH_ERR",
+  null,
+  null,
+  null,
+  null,
+  null,
+  null,
+  null,
+  "DATA_CLONE_ERR"
+];
+for (var i = 0; i < constants.length; ++i) {
+  var constant = constants[i];
+  if (constant)
+    is(DOMException[constant], i, constant)
+}
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug585978.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=585978
+-->
+<head>
+  <title>Test for Bug 585978</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=585978">Mozilla Bug 585978</a>
+
+<script type="application/javascript;version=1.7">
+
+/* Test that if we have a unicode character in the middle of an ascii string,
+   the unicode character survives translation into and out of a text node. */
+
+for (let i = 0; i < 128; i++) {
+  let node = document.createTextNode('');
+  let str = '';
+  for (let j = 0; j < i; j++) {
+    str += 'a';
+  }
+  str += '\uA0A9'
+  node.data = str;
+
+  for (let j = 0; j < 32; j++) {
+    is(node.data, str);
+
+    str += 'b';
+    node.appendData('b');
+  }
+}
+
+</script>
+</body>
+</html>
--- a/content/base/test/test_fileapi.html
+++ b/content/base/test/test_fileapi.html
@@ -110,23 +110,16 @@ expectedTestCount++;
 
 r = new FileReader();
 r.readAsText(createFileWithData(convertToUTF16(testTextData)), "utf-16");
 r.onload = getLoadHandler(testTextData,
                           convertToUTF16(testTextData).length,
                           "utf16 reading");
 expectedTestCount++;
 
-r = new FileReader();
-r.onload = getLoadHandler(testTextData,
-                          convertToUTF32(testTextData).length,
-                          "utf32 reading");
-r.readAsText(createFileWithData(convertToUTF32(testTextData)), "UTF-32");
-expectedTestCount++;
-
 
 // Test loading an empty file works (and doesn't crash!)
 var emptyFile = createFileWithData("");
 dump("hello nurse");
 r = new FileReader();
 r.onload = getLoadHandler("", 0, "empty no encoding reading");
 r.readAsText(emptyFile, "");
 expectedTestCount++;
@@ -346,25 +339,16 @@ function convertToUTF16(s) {
   res = "";
   for (var i = 0; i < s.length; ++i) {
     c = s.charCodeAt(i);
     res += String.fromCharCode(c >>> 8, c & 255);
   }
   return res;
 }
 
-function convertToUTF32(s) {
-  res = "";
-  for (var i = 0; i < s.length; ++i) {
-    c = s.charCodeAt(i);
-    res += "\0\0" + String.fromCharCode(c >>> 8, c & 255);
-  }
-  return res;
-}
-
 function convertToUTF8(s) {
   return unescape(encodeURIComponent(s));
 }
 
 function convertToDataURL(s) {
   return "data:application/octet-stream;base64," + btoa(s);
 }
 
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -1973,17 +1973,17 @@ nsCanvasRenderingContext2D::DrawPath(Sty
 //
 // rects
 //
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
 {
     if (!FloatValidate(x,y,w,h))
-        return NS_ERROR_DOM_SYNTAX_ERR;
+        return NS_OK;
 
     PathAutoSaveRestore pathSR(this);
     gfxContextAutoSaveRestore autoSR(mThebes);
 
     mThebes->SetOperator(gfxContext::OPERATOR_CLEAR);
     mThebes->NewPath();
     mThebes->Rectangle(gfxRect(x, y, w, h));
     mThebes->Fill();
@@ -3435,34 +3435,57 @@ nsCanvasRenderingContext2D::DrawImage(ns
         dy = a6;
         dw = a7;
         dh = a8;
     } else {
         // XXX ERRMSG we need to report an error to developers here! (bug 329026)
         return NS_ERROR_INVALID_ARG;
     }
 
+    if (sw == 0.0 || sh == 0.0) {
+        // zero-sized source -- failure !?
+        return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    }
+
     if (dw == 0.0 || dh == 0.0) {
         // not really failure, but nothing to do --
         // and noone likes a divide-by-zero
         return NS_OK;
     }
 
-    if (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh)) {
+    // The following check might do the validation of the float arguments:
+    //   (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh))
+    // but we would also need to validate some sums for overflow (e.g. sx + sw).
+    if (!FloatValidate(sx + sw, sy + sh, dx + dw, dy + dh)) {
         return NS_ERROR_DOM_SYNTAX_ERR;
     }
 
-    // check args
-    if (sx < 0.0 || sy < 0.0 ||
-        sw < 0.0 || sw > (double) imgSize.width ||
-        sh < 0.0 || sh > (double) imgSize.height ||
-        dw < 0.0 || dh < 0.0)
-    {
-        // XXX ERRMSG we need to report an error to developers here! (bug 329026)
-        return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    // Handle negative sw, sh, dw and dh by flipping the rectangle over in the
+    // relevant direction.
+    if (sw < 0.0) {
+      sx += sw;
+      sw = -sw;
+    }
+    if (sh < 0.0) {
+      sy += sh;
+      sh = -sh;
+    }
+    if (dw < 0.0) {
+      dx += dw;
+      dw = -dw;
+    }
+    if (dh < 0.0) {
+      dy += dh;
+      dh = -dh;
+    }
+
+    // Checking source image boundaries.
+    if (sx < 0 || sx + sw > (double) imgSize.width || 
+        sy < 0 || sy + sh > (double) imgSize.height) {
+      return NS_ERROR_DOM_INDEX_SIZE_ERR;
     }
 
     matrix.Translate(gfxPoint(sx, sy));
     matrix.Scale(sw/dw, sh/dh);
 #ifdef WINCE
     /* cairo doesn't have consistent semantics for drawing a surface onto
      * itself. Specifically, pixman will not preserve the contents when doing
      * the copy. So to get the desired semantics a temporary copy would be needed.
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -10,17 +10,17 @@
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
 # The Original Code is mozilla.org code.
 #
 # The Initial Developer of the Original Code is
-# Mozilla Corporation.
+# the Mozilla Foundation.
 # Portions created by the Initial Developer are Copyright (C) 2007
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Philip Taylor <philip.taylor@cl.cam.ac.uk>
 #
 # 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"),
@@ -74,16 +74,17 @@ include $(topsrcdir)/config/rules.mk
 	test_2d.composite.canvas.source-out.html \
 	test_2d.composite.image.destination-atop.html \
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
+	test_toDataURL_lowercase_ascii.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_drawImage_edge_cases.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -240,17 +240,17 @@ ctx.clearRect(0, Infinity, Infinity, Inf
 ctx.clearRect(0, Infinity, 100, Infinity);
 ctx.clearRect(0, 0, Infinity, Infinity);
 
 isPixel(ctx, 50,25, 0,255,0,255, 0);
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 
 <!-- [[[ test_2d.clearRect.path.html ]]] -->
 
 <p>Canvas test: 2d.clearRect.path</p>
@@ -3033,51 +3033,75 @@ todo(img.complete === false, "img.comple
 var _thrown = undefined; try {
   ctx.drawImage(img, 0, 0);
 } catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
 
 
 }
 </script>
 
+<!-- [[[ test_2d.drawImage.negativedir.html ]]] -->
+
+<p>Canvas test: 2d.drawImage.negativedir</p>
+<canvas id="c117a" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+
+function test_2d_drawImage_negativedir() {
+
+var canvas = document.getElementById('c117a');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('ggrr-256x256_0.png'), 0, 178, 50, -100, 0, 0, 50, 100);
+ctx.drawImage(document.getElementById('ggrr-256x256_0.png'), 0, 78, 50, 100, 50, 100, 50, -100);
+isPixel(ctx, 1,1, 0,255,0,255, 2);
+isPixel(ctx, 1,48, 0,255,0,255, 2);
+isPixel(ctx, 98,1, 0,255,0,255, 2);
+isPixel(ctx, 98,48, 0,255,0,255, 2);
+isPixel(ctx, 48,1, 0,255,0,255, 2);
+isPixel(ctx, 48,48, 0,255,0,255, 2);
+isPixel(ctx, 51,1, 0,255,0,255, 2);
+isPixel(ctx, 51,48, 0,255,0,255, 2);
+isPixel(ctx, 25,25, 0,255,0,255, 2);
+isPixel(ctx, 75,25, 0,255,0,255, 2);
+
+
+}
+</script>
+<img src="image_ggrr-256x256.png" id="ggrr-256x256_0.png" class="resource">
+
 <!-- [[[ test_2d.drawImage.negativedest.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.negativedest</p>
 <canvas id="c117" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 
 function test_2d_drawImage_negativedest() {
 
 var canvas = document.getElementById('c117');
 var ctx = canvas.getContext('2d');
 
-var _thrown_outer = false;
-try {
-
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_1.png'), 100, 78, 50, 50, 0, 50, 50, -50);
 ctx.drawImage(document.getElementById('ggrr-256x256_1.png'), 100, 128, 50, -50, 100, 50, -50, -50);
 isPixel(ctx, 1,1, 0,255,0,255, 2);
 isPixel(ctx, 1,48, 0,255,0,255, 2);
 isPixel(ctx, 98,1, 0,255,0,255, 2);
 isPixel(ctx, 98,48, 0,255,0,255, 2);
 isPixel(ctx, 48,1, 0,255,0,255, 2);
 isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
-} catch (e) {
-    _thrown_outer = true;
-}
-todo(!_thrown_outer, 'should not throw exception');
-
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_1.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.negativesource.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.negativesource</p>
@@ -3085,39 +3109,31 @@ todo(!_thrown_outer, 'should not throw e
 <script>
 
 
 function test_2d_drawImage_negativesource() {
 
 var canvas = document.getElementById('c118');
 var ctx = canvas.getContext('2d');
 
-var _thrown_outer = false;
-try {
-
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_2.png'), 100, 78, -100, 50, 0, 0, 50, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_2.png'), 100, 128, -100, -50, 50, 0, 50, 50);
 isPixel(ctx, 1,1, 0,255,0,255, 2);
 isPixel(ctx, 1,48, 0,255,0,255, 2);
 isPixel(ctx, 98,1, 0,255,0,255, 2);
 isPixel(ctx, 98,48, 0,255,0,255, 2);
 isPixel(ctx, 48,1, 0,255,0,255, 2);
 isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
-} catch (e) {
-    _thrown_outer = true;
-}
-todo(!_thrown_outer, 'should not throw exception');
-
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_2.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.nonfinite.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.nonfinite</p>
@@ -3502,52 +3518,45 @@ var _thrown = undefined; try {
 
 
 
 function test_2d_drawImage_outsidesource() {
 
 var canvas = document.getElementById('c122');
 var ctx = canvas.getContext('2d');
 
-var _thrown_outer = false;
-try {
-
 ctx.drawImage(document.getElementById('green_7.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50);
 ctx.drawImage(document.getElementById('green_7.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50);
 ctx.drawImage(document.getElementById('green_7.png'), 100, 50, -5, -5, 0, 0, 100, 50);
+
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), -0.001, 0, 100, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, -0.001, 100, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100.001, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100, 50.001, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 50, 0, 50.001, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, -5, 5, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 5, -5, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 110, 60, -20, -20, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
-todo_isPixel(ctx, 50,25, 0,255,0,255, 2);
-
-} catch (e) {
-    _thrown_outer = true;
-}
-todo(!_thrown_outer, 'should not throw exception');
+isPixel(ctx, 50,25, 0,255,0,255, 2);
 
 
 }
 </script>
 <img src="image_green.png" id="green_7.png" class="resource">
 <img src="image_red.png" id="red_11.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.path.html ]]] -->
@@ -3694,23 +3703,23 @@ function test_2d_drawImage_zerosource() 
 
 var canvas = document.getElementById('c128');
 var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 100, 50);
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 1, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 1, 0, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 0, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 isPixel(ctx, 50,25, 0,255,0,255, 2);
 
 
 }
 </script>
 <img src="image_red.png" id="red_14.png" class="resource">
 
 <!-- [[[ test_2d.fillRect.basic.html ]]] -->
@@ -7762,24 +7771,24 @@ var _thrown_outer = false;
 try {
 
 ctx.fillStyle = '#000';
 ctx.fillRect(0, 0, 100, 50);
 ctx.fillStyle = '#fff';
 ctx.fillRect(20, 10, 60, 10);
 
 var imgdata1 = ctx.getImageData(85, 25, -10, -10);
-ok(imgdata1.data[0] === 0, "imgdata1.data[\""+(0)+"\"] === 0");
-ok(imgdata1.data[1] === 0, "imgdata1.data[\""+(1)+"\"] === 0");
-ok(imgdata1.data[2] === 0, "imgdata1.data[\""+(2)+"\"] === 0");
+ok(imgdata1.data[0] === 255, "imgdata1.data[\""+(0)+"\"] === 255");
+ok(imgdata1.data[1] === 255, "imgdata1.data[\""+(1)+"\"] === 255");
+ok(imgdata1.data[2] === 255, "imgdata1.data[\""+(2)+"\"] === 255");
 ok(imgdata1.data[3] === 255, "imgdata1.data[\""+(3)+"\"] === 255");
-ok(imgdata1.data[imgdata1.length-4+0] === 255, "imgdata1.data[imgdata1.length-4+0] === 255");
-ok(imgdata1.data[imgdata1.length-4+1] === 255, "imgdata1.data[imgdata1.length-4+1] === 255");
-ok(imgdata1.data[imgdata1.length-4+2] === 255, "imgdata1.data[imgdata1.length-4+2] === 255");
-ok(imgdata1.data[imgdata1.length-4+3] === 255, "imgdata1.data[imgdata1.length-4+3] === 255");
+ok(imgdata1.data[imgdata1.data.length-4+0] === 0, "imgdata1.data[imgdata1.data.length-4+0] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+1] === 0, "imgdata1.data[imgdata1.data.length-4+1] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+2] === 0, "imgdata1.data[imgdata1.data.length-4+2] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+3] === 255, "imgdata1.data[imgdata1.data.length-4+3] === 255");
 
 var imgdata2 = ctx.getImageData(0, 0, -1, -1);
 ok(imgdata2.data[0] === 0, "imgdata2.data[\""+(0)+"\"] === 0");
 ok(imgdata2.data[1] === 0, "imgdata2.data[\""+(1)+"\"] === 0");
 ok(imgdata2.data[2] === 0, "imgdata2.data[\""+(2)+"\"] === 0");
 ok(imgdata2.data[3] === 0, "imgdata2.data[\""+(3)+"\"] === 0");
 
 } catch (e) {
@@ -19163,18 +19172,18 @@ ok(ctx.arcTo(0, 0, 0, 0, 1) === undefine
 ok(ctx.rect(0, 0, 0, 0) === undefined, "ctx.rect(0, 0, 0, 0) === undefined");
 ok(ctx.arc(0, 0, 1, 0, 0, true) === undefined, "ctx.arc(0, 0, 1, 0, 0, true) === undefined");
 ok(ctx.fill() === undefined, "ctx.fill() === undefined");
 ok(ctx.stroke() === undefined, "ctx.stroke() === undefined");
 ok(ctx.clip() === undefined, "ctx.clip() === undefined");
 if (ctx.putImageData) {
     ok(ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined, "ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined");
 }
-ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined");
-ok(ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined");
+ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined");
+ok(ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined");
 ok(ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined, "ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined");
 
 
 }
 </script>
 <img src="image_yellow.png" id="yellow_11.png" class="resource">
 
 <!-- [[[ test_bug397524.html ]]] -->
@@ -21505,16 +21514,21 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_floatsource");
  }
  try {
   test_2d_drawImage_incomplete();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_incomplete");
  }
  try {
+  test_2d_drawImage_negativedir();
+ } catch (e) {
+  ok(false, "unexpected exception thrown in: test_2d_drawImage_negativedir");
+ }
+ try {
   test_2d_drawImage_negativedest();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_negativedest");
  }
  try {
   test_2d_drawImage_negativesource();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_negativesource");
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_toDataURL_lowercase_ascii.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<title>Canvas test: toDataURL.lowercase.ascii</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext("2d");
+
+var data = canvas.toDataURL('ImAgE/PnG');
+ok(data.match(/^data:image\/png[;,]/), "data =~ /^data:image\\/png[;,]/");
+
+// If JPEG is supported at all, it must be supported case-insensitively
+data = canvas.toDataURL('image/jpeg');
+if (data.match(/^data:image\/jpeg[;,]/)) {
+    data = canvas.toDataURL('ImAgE/JpEg');
+    ok(data.match(/^data:image\/jpeg[;,]/), "data =~ /^data:image\\/jpeg[;,]/");
+}
+</script>
--- a/content/events/public/nsIEventStateManager.h
+++ b/content/events/public/nsIEventStateManager.h
@@ -95,19 +95,22 @@ public:
    *                      will pretend that those states are also set on aContent.
    * @return              The content state.
    */
   virtual nsEventStates GetContentState(nsIContent *aContent,
                                         PRBool aFollowLabels = PR_FALSE) = 0;
 
   /**
    * Notify that the given NS_EVENT_STATE_* bit has changed for this content.
-   * @param aContent Content which has changed states
-   * @param aState   Corresponding state flags such as NS_EVENT_STATE_FOCUS 
-   *                 defined in the nsIEventStateManager interface
+   * @param aContent Content which has changed states.  This may be null to
+   *                 indicate that nothing is in this state anymore.
+   * @param aState   One of NS_EVENT_STATE_ACTIVE, NS_EVENT_STATE_HOVER,
+   *                 NS_EVENT_STATE_DRAGOVER, NS_EVENT_STATE_URLTARGET.  Don't
+   *                 pass anything else!  Passing in a state object that has
+   *                 more than one of those states set is not supported.
    * @return  Whether the content was able to change all states. Returns PR_FALSE
    *                  if a resulting DOM event causes the content node passed in
    *                  to not change states. Note, the frame for the content may
    *                  change as a result of the content state change, because of
    *                  frame reconstructions that may occur, but this does not
    *                  affect the return value.
    */
   virtual PRBool SetContentState(nsIContent *aContent, nsEventStates aState) = 0;
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -153,16 +153,17 @@
 #include "nsDOMDataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
 #include "nsIController.h"
 #include "nsICommandParams.h"
 #include "mozilla/Services.h"
+#include "mozAutoDocUpdate.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
 #endif
 
 #ifdef MOZ_IPC
 using namespace mozilla::dom;
 #endif
@@ -4217,16 +4218,28 @@ IsAncestorOf(nsIContent* aPossibleAncest
       nsCOMPtr<nsIContent> labelTarget = GetLabelTarget(aPossibleDescendant);
       if (labelTarget == aPossibleAncestor)
         return true;
     }
   }
   return false;
 }
 
+static bool
+ShouldShowFocusRing(nsIContent* aContent)
+{
+  nsIDocument* doc = aContent->GetOwnerDoc();
+  if (doc) {
+    nsPIDOMWindow* window = doc->GetWindow();
+    return window && window->ShouldShowFocusRing();
+  }
+
+  return false;
+}
+
 nsEventStates
 nsEventStateManager::GetContentState(nsIContent *aContent, PRBool aFollowLabels)
 {
   nsEventStates state = aContent->IntrinsicState();
 
   if (IsAncestorOf(aContent, mActiveContent, aFollowLabels)) {
     state |= NS_EVENT_STATE_ACTIVE;
   }
@@ -4234,22 +4247,18 @@ nsEventStateManager::GetContentState(nsI
     state |= NS_EVENT_STATE_HOVER;
   }
 
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   nsIContent* focusedContent = fm ? fm->GetFocusedContent() : nsnull;
   if (aContent == focusedContent) {
     state |= NS_EVENT_STATE_FOCUS;
 
-    nsIDocument* doc = focusedContent->GetOwnerDoc();
-    if (doc) {
-      nsPIDOMWindow* window = doc->GetWindow();
-      if (window && window->ShouldShowFocusRing()) {
-        state |= NS_EVENT_STATE_FOCUSRING;
-      }
+    if (ShouldShowFocusRing(aContent)) {
+      state |= NS_EVENT_STATE_FOCUSRING;
     }
   }
   if (aContent == mDragOverContent) {
     state |= NS_EVENT_STATE_DRAGOVER;
   }
   if (aContent == mURLTargetContent) {
     state |= NS_EVENT_STATE_URLTARGET;
   }
@@ -4300,214 +4309,129 @@ static nsIContent* FindCommonAncestor(ns
   return nsnull;
 }
 
 static void
 NotifyAncestors(nsIDocument* aDocument, nsIContent* aStartNode,
                 nsIContent* aStopBefore, nsEventStates aState)
 {
   while (aStartNode && aStartNode != aStopBefore) {
-    aDocument->ContentStatesChanged(aStartNode, nsnull, aState);
+    aDocument->ContentStateChanged(aStartNode, aState);
     nsCOMPtr<nsIContent> labelTarget = GetLabelTarget(aStartNode);
     if (labelTarget) {
-      aDocument->ContentStatesChanged(labelTarget, nsnull, aState);
+      aDocument->ContentStateChanged(labelTarget, aState);
     }
     aStartNode = aStartNode->GetParent();
   }
 }
 
 PRBool
 nsEventStateManager::SetContentState(nsIContent *aContent, nsEventStates aState)
 {
-  const PRInt32 maxNotify = 5;
-  // We must initialize this array with memset for the sake of the boneheaded
-  // OS X compiler.  See bug 134934.
-  nsIContent  *notifyContent[maxNotify];
-  memset(notifyContent, 0, sizeof(notifyContent));
-
-  // check to see that this state is allowed by style. Check dragover too?
-  // XXX This doesn't consider that |aState| is a bitfield.
-  // XXX Is this even what we want?
-  if (mCurrentTarget && (aState == NS_EVENT_STATE_ACTIVE || aState == NS_EVENT_STATE_HOVER))
-  {
-    const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
-    if (ui->mUserInput == NS_STYLE_USER_INPUT_NONE)
-      return PR_FALSE;
-  }
-
-  if (aState.HasState(NS_EVENT_STATE_DRAGOVER) && aContent != mDragOverContent) {
-    notifyContent[3] = mDragOverContent; // notify dragover first, since more common case
-    NS_IF_ADDREF(notifyContent[3]);
-    mDragOverContent = aContent;
-  }
-
-  if (aState.HasState(NS_EVENT_STATE_URLTARGET) && aContent != mURLTargetContent) {
-    notifyContent[4] = mURLTargetContent;
-    NS_IF_ADDREF(notifyContent[4]);
-    mURLTargetContent = aContent;
-  }
-
-  nsCOMPtr<nsIContent> commonActiveAncestor, oldActive, newActive;
-  if (aState.HasState(NS_EVENT_STATE_ACTIVE) && aContent != mActiveContent) {
-    oldActive = mActiveContent;
-    newActive = aContent;
-    commonActiveAncestor = FindCommonAncestor(mActiveContent, aContent);
-    mActiveContent = aContent;
-  }
-
-  nsCOMPtr<nsIContent> commonHoverAncestor, oldHover, newHover;
-  if (aState.HasState(NS_EVENT_STATE_HOVER) && aContent != mHoverContent) {
-    oldHover = mHoverContent;
-
-    if (mPresContext->IsDynamic()) {
-      newHover = aContent;
+  // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET
+  // The input must be exactly one of them.
+  NS_PRECONDITION(aState == NS_EVENT_STATE_ACTIVE ||
+                  aState == NS_EVENT_STATE_HOVER ||
+                  aState == NS_EVENT_STATE_DRAGOVER ||
+                  aState == NS_EVENT_STATE_URLTARGET,
+                  "Unexpected state");
+
+  nsCOMPtr<nsIContent> notifyContent1;
+  nsCOMPtr<nsIContent> notifyContent2;
+  PRBool notifyAncestors;
+
+  if (aState == NS_EVENT_STATE_HOVER || aState == NS_EVENT_STATE_ACTIVE) {
+    // Hover and active are hierarchical
+    notifyAncestors = PR_TRUE;
+
+    // check to see that this state is allowed by style. Check dragover too?
+    // XXX Is this even what we want?
+    if (mCurrentTarget)
+    {
+      const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
+      if (ui->mUserInput == NS_STYLE_USER_INPUT_NONE)
+        return PR_FALSE;
+    }
+
+    if (aState == NS_EVENT_STATE_ACTIVE) {
+      if (aContent != mActiveContent) {
+        notifyContent1 = aContent;
+        notifyContent2 = mActiveContent;
+        mActiveContent = aContent;
+      }
     } else {
-      NS_ASSERTION(!aContent ||
-                   aContent->GetCurrentDoc() == mPresContext->PresShell()->GetDocument(),
-                   "Unexpected document");
-      nsIFrame *frame = aContent ? aContent->GetPrimaryFrame() : nsnull;
-      if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {
-        // The scrollbars of viewport should not ignore the hover state.
-        // Because they are *not* the content of the web page.
+      NS_ASSERTION(aState == NS_EVENT_STATE_HOVER, "How did that happen?");
+      nsIContent* newHover;
+      
+      if (mPresContext->IsDynamic()) {
         newHover = aContent;
       } else {
-        // All contents of the web page should ignore the hover state.
-        newHover = nsnull;
+        NS_ASSERTION(!aContent ||
+                     aContent->GetCurrentDoc() == mPresContext->PresShell()->GetDocument(),
+                     "Unexpected document");
+        nsIFrame *frame = aContent ? aContent->GetPrimaryFrame() : nsnull;
+        if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {
+          // The scrollbars of viewport should not ignore the hover state.
+          // Because they are *not* the content of the web page.
+          newHover = aContent;
+        } else {
+          // All contents of the web page should ignore the hover state.
+          newHover = nsnull;
+        }
+      }
+
+      if (newHover != mHoverContent) {
+        notifyContent1 = newHover;
+        notifyContent2 = mHoverContent;
+        mHoverContent = newHover;
       }
     }
-
-    commonHoverAncestor = FindCommonAncestor(mHoverContent, aContent);
-    mHoverContent = aContent;
-  }
-
-  if (aState.HasState(NS_EVENT_STATE_FOCUS)) {
-    aState |= NS_EVENT_STATE_FOCUSRING;
-    notifyContent[2] = aContent;
-    NS_IF_ADDREF(notifyContent[2]);
-  }
-
-  nsEventStates simpleStates = aState;
-  simpleStates &= ~(NS_EVENT_STATE_ACTIVE|NS_EVENT_STATE_HOVER);
-
-  if (aContent && !simpleStates.IsEmpty()) {
-    // notify about new content too
-    notifyContent[0] = aContent;
-    NS_ADDREF(aContent);  // everything in notify array has a ref
-  }
-
-  // remove duplicates
-  if ((notifyContent[4] == n