Merge mozilla-central into Places
authorShawn Wilsher <me@shawnwilsher.com>
Wed, 17 Nov 2010 10:55:34 -0800
changeset 59340 aa2c205e34acd8d4dd6ad83b8a4557649ca05241
parent 59339 68f6d3af58622fc13bb0bf88ed7a5554ccad05b4 (current diff)
parent 57648 ad227939db8264407c22615e5acc4b18c77b49f3 (diff)
child 59341 78b90bdb9500ce6bc7187e63ead5ff888ee6b12e
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
milestone2.0b8pre
Merge mozilla-central into Places
accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
browser/components/places/tests/browser/Makefile.in
browser/installer/package-manifest.in
configure.in
content/base/test/test_bug308484.html
content/canvas/test/webgl/conformance/00_test_list.txt
content/canvas/test/webgl/conformance/context-attributes.html
dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
editor/libeditor/html/tests/test_bug601881.html
extensions/cookie/test/unit/test_bug481775.js
gfx/ycbcr/bug572034_mac_64bit.patch
gfx/ycbcr/bug577645_movntq.patch
gfx/ycbcr/bustage.patch
gfx/ycbcr/export.patch
gfx/ycbcr/picture_region.patch
gfx/ycbcr/remove_scale.patch
gfx/ycbcr/row_c_fix.patch
gfx/ycbcr/win64_mac64.patch
gfx/ycbcr/yuv_row_linux.cpp
gfx/ycbcr/yuv_row_mac.cpp
gfx/ycbcr/yv24.patch
media/libvorbis/bug487519.patch
modules/freetype2/Makefile.in
modules/plugin/test/crashtests/522512-1.html
toolkit/components/console/hudservice/tests/browser/browser_webconsole_get_display_by_uri_spec.js
toolkit/components/places/public/nsINavHistoryService.idl
toolkit/components/places/src/nsNavBookmarks.cpp
toolkit/components/places/src/nsNavBookmarks.h
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/src/nsNavHistory.h
toolkit/components/places/tests/head_common.js
toolkit/locales/en-US/chrome/global-region/region.dtd
toolkit/xre/nsSetDllDirectory.cpp
toolkit/xre/nsSetDllDirectory.h
uriloader/exthandler/tests/unit_ipc/disable_t_encoding.js
--- a/accessible/public/nsIAccessibleRole.idl
+++ b/accessible/public/nsIAccessibleRole.idl
@@ -777,14 +777,20 @@ interface nsIAccessibleRole : nsISupport
   const unsigned long ROLE_GRID_CELL = 121;
 
   /**
    * Represents an embedded object. It is used for html:object or html:embed.
    */
   const unsigned long ROLE_EMBEDDED_OBJECT = 122;
 
   /**
+   * A note. Originally intended to be hidden until activated, but now also used
+   * for things like html 'aside'.
+   */
+  const unsigned long ROLE_NOTE = 123;
+
+  /**
    * It's not role actually. This constant is important to help ensure
    * nsRoleMap's are synchronized.
    */
-  const unsigned long ROLE_LAST_ENTRY = 123;
+  const unsigned long ROLE_LAST_ENTRY = 124;
 };
 
--- a/accessible/src/atk/nsRoleMap.h
+++ b/accessible/src/atk/nsRoleMap.h
@@ -164,11 +164,12 @@ static const PRUint32 atkRoleMap[] = {
     ATK_ROLE_MENU_ITEM,           // nsIAccessibleRole::ROLE_COMBOBOX_OPTION      115
     ATK_ROLE_IMAGE,               // nsIAccessibleRole::ROLE_IMAGE_MAP            116
     ATK_ROLE_LIST_ITEM,           // nsIAccessibleRole::ROLE_OPTION               117
     ATK_ROLE_LIST_ITEM,           // nsIAccessibleRole::ROLE_RICH_OPTION          118
     ATK_ROLE_LIST,                // nsIAccessibleRole::ROLE_LISTBOX              119
     ATK_ROLE_UNKNOWN,             // nsIAccessibleRole::ROLE_FLAT_EQUATION        120
     ATK_ROLE_TABLE_CELL,          // nsIAccessibleRole::ROLE_GRID_CELL            121
     ATK_ROLE_PANEL,               // nsIAccessibleRole::ROLE_EMBEDDED_OBJECT      122
+    ATK_ROLE_SECTION,             // nsIAccessibleRole::ROLE_NOTE                 123
     kROLE_ATK_LAST_ENTRY          // nsIAccessibleRole::ROLE_LAST_ENTRY
 };
 
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -451,37 +451,38 @@ nsAccDocManager::CreateDocOrRootAccessib
   }
 
   if (!outerDocAcc)
     return nsnull;
 
   // We only create root accessibles for the true root, otherwise create a
   // doc accessible.
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
-  nsDocAccessible *docAcc = isRootDoc ?
+  nsRefPtr<nsDocAccessible> docAcc = isRootDoc ?
     new nsRootAccessibleWrap(aDocument, rootElm, weakShell) :
     new nsDocAccessibleWrap(aDocument, rootElm, weakShell);
 
-  if (!docAcc)
+  // Cache the document accessible into document cache.
+  if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
     return nsnull;
 
-  // Cache and addref document accessible.
-  if (!mDocAccessibleCache.Put(aDocument, docAcc)) {
-    delete docAcc;
+  // Bind the document accessible into tree.
+  if (!outerDocAcc->AppendChild(docAcc)) {
+    mDocAccessibleCache.Remove(aDocument);
     return nsnull;
   }
 
-  // XXX: ideally we should initialize an accessible and then put it into tree,
-  // we can't since document accessible fires reorder event on its container
-  // while initialized.
-  if (!outerDocAcc->AppendChild(docAcc) ||
-      !GetAccService()->InitAccessible(docAcc, nsAccUtils::GetRoleMapEntry(aDocument))) {
+  // Initialize the document accessible. Note, Init() should be called after
+  // the document accessible is bound to the tree.
+  if (!docAcc->Init()) {
+    docAcc->Shutdown();
     mDocAccessibleCache.Remove(aDocument);
     return nsnull;
   }
+  docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument));
 
   NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/nsAccTreeWalker.cpp
+++ b/accessible/src/base/nsAccTreeWalker.cpp
@@ -108,26 +108,26 @@ nsAccTreeWalker::GetNextChildInternal(PR
   PRUint32 length = 0;
   if (mState->childList)
     mState->childList->GetLength(&length);
 
   while (mState->childIdx < length) {
     nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx);
     mState->childIdx++;
 
-    PRBool isHidden = PR_FALSE;
+    bool isSubtreeHidden = false;
     nsRefPtr<nsAccessible> accessible =
       GetAccService()->GetOrCreateAccessible(childNode, presShell, mWeakShell,
-                                             &isHidden);
+                                             &isSubtreeHidden);
 
     if (accessible)
       return accessible.forget();
 
     // Walk down into subtree to find accessibles.
-    if (!isHidden) {
+    if (!isSubtreeHidden) {
       if (!PushState(childNode))
         break;
 
       accessible = GetNextChildInternal(PR_TRUE);
       if (accessible)
         return accessible.forget();
     }
   }
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -96,16 +96,17 @@ ACCESSIBILITY_ATOM(tableRowGroupFrame, "
 ACCESSIBILITY_ATOM(tableRowFrame, "TableRowFrame")
 
   // Alphabetical list of tag names
 ACCESSIBILITY_ATOM(a, "a")
 ACCESSIBILITY_ATOM(abbr, "abbr")
 ACCESSIBILITY_ATOM(acronym, "acronym")
 ACCESSIBILITY_ATOM(area, "area")
 ACCESSIBILITY_ATOM(article, "article") // HTML landmark
+ACCESSIBILITY_ATOM(aside, "aside") // HTML landmark
 ACCESSIBILITY_ATOM(autocomplete, "autocomplete")
 ACCESSIBILITY_ATOM(blockquote, "blockquote")
 ACCESSIBILITY_ATOM(br, "br")
 ACCESSIBILITY_ATOM(body, "body")
 ACCESSIBILITY_ATOM(caption, "caption") // XUL
 ACCESSIBILITY_ATOM(choices, "choices") // XForms
 ACCESSIBILITY_ATOM(description, "description")    // XUL
 ACCESSIBILITY_ATOM(dd, "dd")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -832,38 +832,16 @@ nsAccessibilityService::GetCachedAccessi
 
   nsAccessible *accessible = nsnull;
   while (!(accessible = GetCachedAccessible(currNode, weakShell)) &&
          (currNode = currNode->GetNodeParent()));
 
   return accessible;
 }
 
-PRBool
-nsAccessibilityService::InitAccessible(nsAccessible *aAccessible,
-                                       nsRoleMapEntry *aRoleMapEntry)
-{
-  if (!aAccessible)
-    return PR_FALSE;
-
-  // Add to cache an accessible, etc.
-  if (!aAccessible->Init()) {
-    NS_ERROR("Failed to initialize an accessible!");
-
-    aAccessible->Shutdown();
-    return PR_FALSE;
-  }
-
-  NS_ASSERTION(aAccessible->IsInCache(),
-               "Initialized accessible not in the cache!");
-
-  aAccessible->SetRoleMapEntry(aRoleMapEntry);
-  return PR_TRUE;
-}
-
 static PRBool HasRelatedContent(nsIContent *aContent)
 {
   nsAutoString id;
   if (!aContent || !nsCoreUtils::GetID(aContent, id) || id.IsEmpty()) {
     return PR_FALSE;
   }
 
   nsIAtom *relationAttrs[] = {nsAccessibilityAtoms::aria_labelledby,
@@ -886,23 +864,23 @@ static PRBool HasRelatedContent(nsIConte
 
   return PR_FALSE;
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
                                               nsIPresShell* aPresShell,
                                               nsIWeakReference* aWeakShell,
-                                              PRBool* aIsHidden)
+                                              bool* aIsSubtreeHidden)
 {
   if (!aPresShell || !aWeakShell || !aNode || gIsShutdown)
     return nsnull;
 
-  if (aIsHidden)
-    *aIsHidden = PR_FALSE;
+  if (aIsSubtreeHidden)
+    *aIsSubtreeHidden = false;
 
   // Check to see if we already have an accessible for this node in the cache.
   nsAccessible *cachedAccessible = GetCachedAccessible(aNode, aWeakShell);
   if (cachedAccessible) {
     NS_ADDREF(cachedAccessible);
     return cachedAccessible;
   }
 
@@ -933,55 +911,63 @@ nsAccessibilityService::GetOrCreateAcces
     return nsnull;
 
   // Frames can be deallocated when we flush layout, or when we call into code
   // that can flush layout, either directly, or via DOM manipulation, or some
   // CSS styles like :hover. We use the weak frame checks to avoid calling
   // methods on a dead frame pointer.
   nsWeakFrame weakFrame = content->GetPrimaryFrame();
 
-  // Check frame to see if it is hidden.
-  if (!weakFrame.GetFrame()) {
-    if (aIsHidden)
-      *aIsHidden = PR_TRUE;
+  // Check frame and its visibility. Note, hidden frame allows visible
+  // elements in subtree.
+  if (!weakFrame.GetFrame() || !weakFrame->GetStyleVisibility()->IsVisible()) {
+    if (aIsSubtreeHidden && !weakFrame.GetFrame())
+      *aIsSubtreeHidden = true;
 
     return nsnull;
   }
 
   if (weakFrame.GetFrame()->GetContent() != content) {
     // Not the main content for this frame. This happens because <area>
     // elements return the image frame as their primary frame. The main content
     // for the image frame is the image content. If the frame is not an image
     // frame or the node is not an area element then null is returned.
     // This setup will change when bug 135040 is fixed.
     nsAccessible* areaAcc = GetAreaAccessible(weakFrame.GetFrame(),
                                               aNode, aWeakShell);
     NS_IF_ADDREF(areaAcc);
     return areaAcc;
   }
 
+  nsDocAccessible* docAcc =
+    GetAccService()->GetDocAccessible(aNode->GetOwnerDoc());
+  if (!docAcc) {
+    NS_NOTREACHED("No document for accessible being created!");
+    return nsnull;
+  }
+
   // Attempt to create an accessible based on what we know.
   nsRefPtr<nsAccessible> newAcc;
   if (content->IsNodeOfType(nsINode::eTEXT)) {
     // --- Create HTML for visible text frames ---
     nsIFrame* f = weakFrame.GetFrame();
     if (f && f->IsEmpty()) {
       nsAutoString renderedWhitespace;
       f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
       if (renderedWhitespace.IsEmpty()) {
         // Really empty -- nothing is rendered
-        if (aIsHidden)
-          *aIsHidden = PR_TRUE;
+        if (aIsSubtreeHidden)
+          *aIsSubtreeHidden = true;
 
         return nsnull;
       }
     }
     if (weakFrame.IsAlive()) {
       newAcc = weakFrame.GetFrame()->CreateAccessible();
-      if (InitAccessible(newAcc, nsnull))
+      if (docAcc->BindToDocument(newAcc, nsnull))
         return newAcc.forget();
       return nsnull;
     }
 
     return nsnull;
   }
 
   PRBool isHTML = content->IsHTML();
@@ -992,24 +978,24 @@ nsAccessibilityService::GetOrCreateAcces
     // suppose it is used for links grouping. Otherwise we think it is used in
     // conjuction with HTML image element and in this case we don't create any
     // accessible for it and don't walk into it. The accessibles for HTML area
     // (nsHTMLAreaAccessible) the map contains are attached as children of the
     // appropriate accessible for HTML image (nsHTMLImageAccessible).
     nsAutoString name;
     content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name);
     if (!name.IsEmpty()) {
-      if (aIsHidden)
-        *aIsHidden = PR_TRUE;
+      if (aIsSubtreeHidden)
+        *aIsSubtreeHidden = true;
 
       return nsnull;
     }
 
     newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell);
-    if (InitAccessible(newAcc, nsAccUtils::GetRoleMapEntry(aNode)))
+    if (docAcc->BindToDocument(newAcc, nsAccUtils::GetRoleMapEntry(aNode)))
       return newAcc.forget();
     return nsnull;
   }
 
   nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
   if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
       !content->IsFocusable()) { // For presentation only
     // Only create accessible for role of "presentation" if it is focusable --
@@ -1117,28 +1103,28 @@ nsAccessibilityService::GetOrCreateAcces
       newAcc = CreateHTMLAccessibleByMarkup(weakFrame.GetFrame(), content,
                                             aWeakShell);
 
       if (!newAcc) {
         // Do not create accessible object subtrees for non-rendered table
         // captions. This could not be done in
         // nsTableCaptionFrame::GetAccessible() because the descendants of
         // the table caption would still be created. By setting
-        // *aIsHidden = PR_TRUE we ensure that no descendant accessibles are
-        // created.
+        // *aIsSubtreeHidden = true we ensure that no descendant accessibles
+        // are created.
         nsIFrame* f = weakFrame.GetFrame();
         if (!f) {
           f = aPresShell->GetRealPrimaryFrameFor(content);
         }
         if (f->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
            f->GetRect().IsEmpty()) {
           // XXX This is not the ideal place for this code, but right now there
           // is no better place:
-          if (aIsHidden)
-            *aIsHidden = PR_TRUE;
+          if (aIsSubtreeHidden)
+            *aIsSubtreeHidden = true;
 
           return nsnull;
         }
 
         // Try using frame to do it.
         newAcc = f->CreateAccessible();
       }
     }
@@ -1186,17 +1172,17 @@ nsAccessibilityService::GetOrCreateAcces
       newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell);
     }
     else {  // XUL, SVG, MathML etc.
       // Interesting generic non-HTML container
       newAcc = new nsAccessibleWrap(content, aWeakShell);
     }
   }
 
-  if (InitAccessible(newAcc, roleMapEntry))
+  if (docAcc->BindToDocument(newAcc, roleMapEntry))
     return newAcc.forget();
   return nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService private
 
 PRBool
@@ -1343,32 +1329,39 @@ nsAccessibilityService::GetAreaAccessibl
     return nsnull;
 
   nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(aAreaNode);
   if (!areaElmt)
     return nsnull;
 
   // Try to get image map accessible from the global cache or create it
   // if failed.
-  nsRefPtr<nsAccessible> imageAcc =
-    GetCachedAccessible(aImageFrame->GetContent(), aWeakShell);
-  if (!imageAcc) {
-    imageAcc = CreateHTMLImageAccessible(aImageFrame->GetContent(),
-                                         aImageFrame->PresContext()->PresShell());
+  nsRefPtr<nsAccessible> image = GetCachedAccessible(aImageFrame->GetContent(),
+                                                     aWeakShell);
+  if (!image) {
+    image = CreateHTMLImageAccessible(aImageFrame->GetContent(),
+                                      aImageFrame->PresContext()->PresShell());
 
-    if (!InitAccessible(imageAcc, nsnull))
+    nsDocAccessible* document =
+      GetAccService()->GetDocAccessible(aAreaNode->GetOwnerDoc());
+    if (!document) {
+      NS_NOTREACHED("No document for accessible being created!");
+      return nsnull;
+    }
+
+    if (!document->BindToDocument(image, nsnull))
       return nsnull;
   }
 
   if (aImageAccessible)
-    *aImageAccessible = imageAcc;
+    *aImageAccessible = image;
 
   // Make sure <area> accessible children of the image map are cached so
   // that they should be available in global cache.
-  imageAcc->EnsureChildren();
+  image->EnsureChildren();
 
   return GetCachedAccessible(aAreaNode, aWeakShell);
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
                                                nsIWeakReference* aWeakShell)
 {
@@ -1766,17 +1759,17 @@ nsAccessible*
 nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
  {
 #ifdef MOZ_ACCESSIBILITY_ATK
   nsApplicationAccessible* applicationAcc =
     nsAccessNode::GetApplicationAccessible();
   if (!applicationAcc)
     return nsnull;
 
-  nsNativeRootAccessibleWrap* nativeRootAcc =
+  nsRefPtr<nsNativeRootAccessibleWrap> nativeRootAcc =
      new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible);
   if (!nativeRootAcc)
     return nsnull;
 
   if (applicationAcc->AppendChild(nativeRootAcc))
     return nativeRootAcc;
 #endif
 
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -106,19 +106,19 @@ public:
     CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
 
   virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible);
 
   virtual void ContentRangeInserted(nsIPresShell* aPresShell,
-                                      nsIContent* aContainer,
-                                      nsIContent* aStartChild,
-                                      nsIContent* aEndChild);
+                                    nsIContent* aContainer,
+                                    nsIContent* aStartChild,
+                                    nsIContent* aEndChild);
 
   virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
                               nsIContent* aChild);
 
   virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
 
   virtual void PresShellDestroyed(nsIPresShell* aPresShell);
 
@@ -133,26 +133,26 @@ public:
    * Return true if accessibility service has been shutdown.
    */
   static PRBool IsShutdown() { return gIsShutdown; }
 
   /**
    * Return an accessible for the given DOM node from the cache or create new
    * one.
    *
-   * @param  aNode       [in] the given node
-   * @param  aPresShell  [in] the pres shell of the node
-   * @param  aWeakShell  [in] the weak shell for the pres shell
-   * @param  aIsHidden   [out, optional] indicates whether the node's frame is
-   *                       hidden
+   * @param  aNode             [in] the given node
+   * @param  aPresShell        [in] the pres shell of the node
+   * @param  aWeakShell        [in] the weak shell for the pres shell
+   * @param  aIsSubtreeHidden  [out, optional] indicates whether the node's
+   *                             frame and its subtree is hidden
    */
   already_AddRefed<nsAccessible>
     GetOrCreateAccessible(nsINode* aNode, nsIPresShell* aPresShell,
                           nsIWeakReference* aWeakShell,
-                          PRBool* aIsHidden = nsnull);
+                          bool* aIsSubtreeHidden = nsnull);
 
   /**
    * Return an accessible for the given DOM node.
    */
   nsAccessible* GetAccessible(nsINode* aNode);
 
   /**
    * Return an accessible for a DOM node in the given presshell.
@@ -197,29 +197,16 @@ public:
    * @param aDOMNode    [in] the DOM node to get an accessible for
    */
   inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode)
   {
     return aNode ?
       GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull;
   }
 
-  /**
-   * Initialize an accessible and cache it. The method should be called for
-   * every created accessible.
-   *
-   * @param  aAccessible    [in] accessible to initialize.
-   * @param  aRoleMapEntry  [in] the role map entry role the ARIA role or nsnull
-   *                          if none
-   *
-   * @return true if the accessible was initialized, otherwise false
-   */
-  PRBool InitAccessible(nsAccessible *aAccessible,
-                        nsRoleMapEntry *aRoleMapEntry);
-
 protected:
   /**
    * Return an accessible for the DOM node in the given presentation shell if
    * the accessible already exists, otherwise null.
    *
    * @param  aNode       [in] the DOM node to get an access node for
    * @param  aPresShell  [in] the presentation shell which contains layout info
    *                       for the DOM node
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2616,29 +2616,16 @@ nsAccessible::AppendTextTo(nsAString& aT
   }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode public methods
 
-PRBool
-nsAccessible::Init()
-{
-  if (!nsAccessNodeWrap::Init())
-    return PR_FALSE;
-
-  nsDocAccessible* document =
-    GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
-  NS_ASSERTION(document, "Cannot cache new nsAccessible!");
-
-  return document ? document->CacheAccessible(this) : PR_FALSE;
-}
-
 void
 nsAccessible::Shutdown()
 {
   // Invalidate the child count and pointers to other accessibles, also make
   // sure none of its children point to this parent
   InvalidateChildren();
   if (mParent)
     mParent->RemoveChild(this);
@@ -2907,30 +2894,16 @@ nsAccessible::GetIndexOfEmbeddedChild(ns
       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
     return mEmbeddedObjCollector ?
       mEmbeddedObjCollector->GetIndexAt(aChild) : -1;
   }
 
   return GetIndexOf(aChild);
 }
 
-#ifdef DEBUG
-PRBool
-nsAccessible::IsInCache()
-{
-  nsDocAccessible *docAccessible =
-    GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
-  if (docAccessible)
-    return docAccessible->GetCachedAccessibleByUniqueID(UniqueID()) ? PR_TRUE : PR_FALSE;
-
-  return PR_FALSE;
-}
-#endif
-
-
 ////////////////////////////////////////////////////////////////////////////////
 // HyperLinkAccessible methods
 
 bool
 nsAccessible::IsHyperLink()
 {
   // Every embedded accessible within hypertext accessible implements
   // hyperlink interface.
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -108,17 +108,16 @@ public:
   NS_DECL_NSIACCESSIBLEHYPERLINK
   NS_DECL_NSIACCESSIBLESELECTABLE
   NS_DECL_NSIACCESSIBLEVALUE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID)
 
   //////////////////////////////////////////////////////////////////////////////
   // nsAccessNode
 
-  virtual PRBool Init();
   virtual void Shutdown();
 
   //////////////////////////////////////////////////////////////////////////////
   // Public methods
 
   /**
    * Returns the accessible name specified by ARIA.
    */
@@ -293,23 +292,16 @@ public:
     return mParent ?
       mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull;
   }
   PRUint32 GetCachedChildCount() const { return mChildren.Length(); }
   nsAccessible* GetCachedChildAt(PRUint32 aIndex) const { return mChildren.ElementAt(aIndex); }
   PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; }
   bool IsBoundToParent() const { return mParent; }
 
-#ifdef DEBUG
-  /**
-   * Return true if the access node is cached.
-   */
-  PRBool IsInCache();
-#endif
-
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous methods
 
   /**
    * Handle accessible event, i.e. process it, notifies observers and fires
    * platform specific event.
    */
   virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
@@ -436,17 +428,17 @@ protected:
   /**
    * Cache accessible children.
    */
   virtual void CacheChildren();
 
   /**
    * Set accessible parent and index in parent.
    */
-  void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
+  virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
   void UnbindFromParent();
 
   /**
    * Return sibling accessible at the given offset.
    */
   virtual nsAccessible* GetSiblingAtOffset(PRInt32 aOffset,
                                            nsresult *aError = nsnull);
 
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -202,23 +202,16 @@ nsLinkableAccessible::GetKeyboardShortcu
     return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
 
   return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLinkableAccessible. nsAccessNode
 
-PRBool
-nsLinkableAccessible::Init()
-{
-  CacheActionContent();
-  return nsAccessibleWrap::Init();
-}
-
 void
 nsLinkableAccessible::Shutdown()
 {
   mActionContent = nsnull;
   nsAccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -237,21 +230,29 @@ nsLinkableAccessible::GetAnchorURI(PRUin
         return link->GetAnchorURI(aAnchorIndex);
     }
   }
 
   return nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible
+// nsLinkableAccessible: nsAccessible protected
 
 void
-nsLinkableAccessible::CacheActionContent()
+nsLinkableAccessible::BindToParent(nsAccessible* aParent,
+                                   PRUint32 aIndexInParent)
 {
+  nsAccessibleWrap::BindToParent(aParent, aIndexInParent);
+
+  // Cache action content.
+  mActionContent = nsnull;
+  mIsLink = PR_FALSE;
+  mIsOnclick = PR_FALSE;
+
   nsIContent* walkUpContent = mContent;
   PRBool isOnclick = nsCoreUtils::HasClickListener(walkUpContent);
 
   if (isOnclick) {
     mActionContent = walkUpContent;
     mIsOnclick = PR_TRUE;
     return;
   }
@@ -271,16 +272,19 @@ nsLinkableAccessible::CacheActionContent
     if (isOnclick) {
       mActionContent = walkUpContent;
       mIsOnclick = PR_TRUE;
       return;
     }
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsLinkableAccessible: protected
+
 nsAccessible *
 nsLinkableAccessible::GetActionAccessible() const
 {
   // Return accessible for the action content if it's different from node of
   // this accessible. If the action accessible is not null then it is used to
   // redirect methods calls otherwise we use method implementation from the
   // base class.
   if (!mActionContent || mContent == mActionContent)
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -92,36 +92,35 @@ public:
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetValue(nsAString& _retval);
   NS_IMETHOD TakeFocus();
   NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
 
   // nsAccessNode
-  virtual PRBool Init();
   virtual void Shutdown();
 
   // nsAccessible
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
   // HyperLinkAccessible
   virtual already_AddRefed<nsIURI> GetAnchorURI(PRUint32 aAnchorIndex);
 
 protected:
+  // nsAccessible
+  virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
+
+  // nsLinkableAccessible
+
   /**
    * Return an accessible for cached action node.
    */
   nsAccessible *GetActionAccessible() const;
 
-  /**
-   * Cache action node.
-   */
-  virtual void CacheActionContent();
-
   nsCOMPtr<nsIContent> mActionContent;
   PRPackedBool mIsLink;
   PRPackedBool mIsOnclick;
 };
 
 /**
  * A simple accessible that gets its enumerated role passed into constructor.
  */ 
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -42,17 +42,16 @@
 
 #include "nsAccessNode.h"
 
 #include "nsIDocument.h"
 #include "nsIDOMAbstractView.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentView.h"
-#include "nsIDOMDocumentXBL.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
@@ -801,77 +800,16 @@ nsCoreUtils::GetLanguageFor(nsIContent *
   nsIContent *walkUp = aContent;
   while (walkUp && walkUp != aRootContent &&
          !walkUp->GetAttr(kNameSpaceID_None,
                           nsAccessibilityAtoms::lang, aLanguage))
     walkUp = walkUp->GetParent();
 }
 
 void
-nsCoreUtils::GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
-                                     nsIArray **aRefElements)
-{
-  *aRefElements = nsnull;
-
-  nsAutoString ids;
-  if (!aContent->GetAttr(kNameSpaceID_None, aAttr, ids))
-    return;
-
-  ids.CompressWhitespace(PR_TRUE, PR_TRUE);
-
-  nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(aContent->GetOwnerDoc());
-  NS_ASSERTION(document, "The given node is not in document!");
-  if (!document)
-    return;
-
-  nsCOMPtr<nsIDOMDocumentXBL> xblDocument;
-  if (aContent->IsInAnonymousSubtree())
-    xblDocument = do_QueryInterface(document);
-
-  nsCOMPtr<nsIMutableArray> refElms = do_CreateInstance(NS_ARRAY_CONTRACTID);
-
-  while (!ids.IsEmpty()) {
-    nsAutoString id;
-    PRInt32 idLength = ids.FindChar(' ');
-    NS_ASSERTION(idLength != 0,
-                 "Should not be 0 because of CompressWhitespace() call above");
-
-    if (idLength == kNotFound) {
-      id = ids;
-      ids.Truncate();
-    } else {
-      id = Substring(ids, 0, idLength);
-      ids.Cut(0, idLength + 1);
-    }
-
-    // If content is anonymous subtree then use "anonid" attribute to get
-    // elements, otherwise search elements in DOM by ID attribute.
-    nsCOMPtr<nsIDOMElement> refElement;
-    if (xblDocument) {
-      nsCOMPtr<nsIDOMElement> elm =
-        do_QueryInterface(aContent->GetBindingParent());
-      xblDocument->GetAnonymousElementByAttribute(elm,
-                                                  NS_LITERAL_STRING("anonid"),
-                                                  id,
-                                                  getter_AddRefs(refElement));
-    } else {
-      document->GetElementById(id, getter_AddRefs(refElement));
-    }
-
-    if (!refElement)
-      continue;
-
-    refElms->AppendElement(refElement, PR_FALSE);
-  }
-
-  NS_ADDREF(*aRefElements = refElms);
-  return;
-}
-
-void
 nsCoreUtils::GetElementsHavingIDRefsAttr(nsIContent *aRootContent,
                                          nsIContent *aContent,
                                          nsIAtom *aIDRefsAttr,
                                          nsIArray **aElements)
 {
   *aElements = nsnull;
 
   nsAutoString id;
@@ -1160,8 +1098,79 @@ nsAccessibleDOMStringList::GetLength(PRU
 
 NS_IMETHODIMP
 nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult)
 {
   *aResult = mNames.Contains(aString);
 
   return NS_OK;
 }
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IDRefsIterator
+////////////////////////////////////////////////////////////////////////////////
+
+IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
+  mCurrIdx(0)
+{
+  if (!aContent->IsInDoc() ||
+      !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
+    return;
+
+  if (aContent->IsInAnonymousSubtree()) {
+    mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc());
+    mBindingParent = do_QueryInterface(aContent->GetBindingParent());
+  } else {
+    mDocument = aContent->GetOwnerDoc();
+  }
+}
+
+const nsDependentSubstring
+IDRefsIterator::NextID()
+{
+  for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
+    if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
+      break;
+  }
+
+  if (mCurrIdx >= mIDs.Length())
+    return nsDependentSubstring();
+
+  nsAString::index_type idStartIdx = mCurrIdx;
+  while (++mCurrIdx < mIDs.Length()) {
+    if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
+      break;
+  }
+
+  return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
+}
+
+nsIContent*
+IDRefsIterator::NextElem()
+{
+  while (true) {
+    const nsDependentSubstring id = NextID();
+    if (id.IsEmpty())
+      break;
+
+    if (mXBLDocument) {
+      // If content is anonymous subtree then use "anonid" attribute to get
+      // elements, otherwise search elements in DOM by ID attribute.
+
+      nsCOMPtr<nsIDOMElement> refElm;
+      mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
+                                                   NS_LITERAL_STRING("anonid"),
+                                                   id,
+                                                   getter_AddRefs(refElm));
+      nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
+      if (refContent)
+        return refContent;
+
+    } else {
+      nsIContent* refContent = mDocument->GetElementById(id);
+      if (refContent)
+        return refContent;
+    }
+  }
+
+  return nsnull;
+}
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
 #include "nsAccessibilityAtoms.h"
 
+#include "nsIDOMDocumentXBL.h"
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsIBoxObject.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeColumns.h"
 
 #include "nsIFrame.h"
 #include "nsIDocShellTreeItem.h"
@@ -300,27 +301,16 @@ public:
    * @param aContent     [in] the given node
    * @param aRootContent [in] container of the given node
    * @param aLanguage    [out] language
    */
   static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
                              nsAString& aLanguage);
 
   /**
-   * Return the array of elements the given node is referred to by its
-   * IDRefs attribute.
-   *
-   * @param aContent     [in] the given node
-   * @param aAttr        [in] IDRefs attribute on the given node
-   * @param aRefElements [out] result array of elements
-   */
-  static void GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
-                                      nsIArray **aRefElements);
-
-  /**
    * Return the array of elements having IDRefs that points to the given node.
    *
    * @param  aRootContent  [in] root element to search inside
    * @param  aContent      [in] an element having ID attribute
    * @param  aIDRefsAttr   [in] IDRefs attribute
    * @param  aElements     [out] result array of elements
    */
   static void GetElementsHavingIDRefsAttr(nsIContent *aRootContent,
@@ -510,10 +500,39 @@ public:
   PRBool Add(const nsAString& aName) {
     return mNames.AppendElement(aName) != nsnull;
   }
 
 private:
   nsTArray<nsString> mNames;
 };
 
+/**
+ * Used to iterate through IDs or elements pointed by IDRefs attribute. Note,
+ * any method used to iterate through IDs or elements moves iterator to next
+ * position.
+ */
+class IDRefsIterator
+{
+public:
+  IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr);
+
+  /**
+   * Return next ID.
+   */
+  const nsDependentSubstring NextID();
+
+  /**
+   * Return next element.
+   */
+  nsIContent* NextElem();
+
+private:
+  nsString mIDs;
+  nsAString::index_type mCurrIdx;
+
+  nsIDocument* mDocument;
+  nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
+  nsCOMPtr<nsIDOMElement> mBindingParent;
+};
+
 #endif
 
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -594,41 +594,16 @@ nsDocAccessible::GetCachedAccessible(nsI
   nsAccessible* parent(accessible->GetCachedParent());
   if (parent)
     parent->TestChildCache(accessible);
 #endif
 
   return accessible;
 }
 
-// nsDocAccessible public method
-PRBool
-nsDocAccessible::CacheAccessible(nsAccessible* aAccessible)
-{
-  if (aAccessible->IsPrimaryForNode() &&
-      !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible))
-    return PR_FALSE;
-
-  return mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
-}
-
-// nsDocAccessible public method
-void
-nsDocAccessible::ShutdownAccessible(nsAccessible *aAccessible)
-{
-  // Remove an accessible from node to accessible map if it is presented there.
-  if (aAccessible->IsPrimaryForNode() &&
-      mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
-    mNodeToAccessibleMap.Remove(aAccessible->GetNode());
-
-  void* uniqueID = aAccessible->UniqueID();
-  aAccessible->Shutdown();
-  mAccessibleCache.Remove(uniqueID);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 PRBool
 nsDocAccessible::Init()
 {
   NS_LOG_ACCDOCCREATE_FOR("document initialize", mDocument, this)
 
@@ -1044,18 +1019,31 @@ nsDocAccessible::AttributeChangedImpl(ns
   if (aNameSpaceID == kNameSpaceID_None) {
     // Check for hyphenated aria-foo property?
     if (StringBeginsWith(nsDependentAtomString(aAttribute),
                          NS_LITERAL_STRING("aria-"))) {
       ARIAAttributeChanged(aContent, aAttribute);
     }
   }
 
-  if (aAttribute == nsAccessibilityAtoms::role ||
-      aAttribute == nsAccessibilityAtoms::href ||
+  if (aAttribute == nsAccessibilityAtoms::role) {
+    if (mContent == aContent) {
+      // It is common for js libraries to set the role of the body element after
+      // the doc has loaded. In this case we just update the role map entry. 
+      SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aContent));
+    }
+    else {
+      // Recreate the accessible when role is changed because we might require a
+      // different accessible class for the new role or the accessible may
+      // expose a different sets of interfaces (COM restriction).
+      RecreateAccessible(aContent);
+    }
+  }
+
+  if (aAttribute == nsAccessibilityAtoms::href ||
       aAttribute == nsAccessibilityAtoms::onclick) {
     // Not worth the expense to ensure which namespace these are in
     // It doesn't kill use to recreate the accessible even if the attribute was used
     // in the wrong namespace or an element that doesn't support it
     RecreateAccessible(aContent);
     return;
   }
   
@@ -1340,16 +1328,66 @@ nsDocAccessible::GetCachedAccessibleByUn
     child = childDocument->GetCachedAccessibleByUniqueIDInSubtree(aUniqueID);
     if (child)
       return child;
   }
 
   return nsnull;
 }
 
+bool
+nsDocAccessible::BindToDocument(nsAccessible* aAccessible,
+                                nsRoleMapEntry* aRoleMapEntry)
+{
+  if (!aAccessible)
+    return false;
+
+  // Put into DOM node cache.
+  if (aAccessible->IsPrimaryForNode() &&
+      !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible))
+    return false;
+
+  // Put into unique ID cache.
+  if (!mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible)) {
+    if (aAccessible->IsPrimaryForNode())
+      mNodeToAccessibleMap.Remove(aAccessible->GetNode());
+
+    return false;
+  }
+
+  // Initialize the accessible.
+  if (!aAccessible->Init()) {
+    NS_ERROR("Failed to initialize an accessible!");
+
+    UnbindFromDocument(aAccessible);
+    return false;
+  }
+
+  aAccessible->SetRoleMapEntry(aRoleMapEntry);
+  return true;
+}
+
+void
+nsDocAccessible::UnbindFromDocument(nsAccessible* aAccessible)
+{
+  // Remove an accessible from node-to-accessible map if it exists there.
+  if (aAccessible->IsPrimaryForNode() &&
+      mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
+    mNodeToAccessibleMap.Remove(aAccessible->GetNode());
+
+#ifdef DEBUG
+  NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
+               "Unbinding the unbound accessible!");
+#endif
+
+  void* uniqueID = aAccessible->UniqueID();
+  aAccessible->Shutdown();
+  mAccessibleCache.Remove(uniqueID);
+}
+
 void
 nsDocAccessible::UpdateTree(nsIContent* aContainerNode,
                             nsIContent* aStartNode,
                             nsIContent* aEndNode,
                             PRBool aIsInsert)
 {
   // Content change notification mostly are async, thus we can't detect whether
   // these actions are from user. This information is used to fire or do not
@@ -1756,30 +1794,26 @@ nsDocAccessible::UncacheChildrenInSubtre
   if (aRoot->IsPrimaryForNode() &&
       mNodeToAccessibleMap.Get(aRoot->GetNode()) == aRoot)
     mNodeToAccessibleMap.Remove(aRoot->GetNode());
 }
 
 void
 nsDocAccessible::ShutdownChildrenInSubtree(nsAccessible* aAccessible)
 {
-#ifdef DEBUG
-  nsAccessible* incache = mAccessibleCache.GetWeak(aAccessible->UniqueID());
-#endif
-
   // Traverse through children and shutdown them before this accessible. When
   // child gets shutdown then it removes itself from children array of its
   //parent. Use jdx index to process the cases if child is not attached to the
   // parent and as result doesn't remove itself from its children.
   PRUint32 count = aAccessible->GetCachedChildCount();
   for (PRUint32 idx = 0, jdx = 0; idx < count; idx++) {
     nsAccessible* child = aAccessible->GetCachedChildAt(jdx);
     if (!child->IsBoundToParent()) {
       NS_ERROR("Parent refers to a child, child doesn't refer to parent!");
       jdx++;
     }
 
     ShutdownChildrenInSubtree(child);
   }
 
-  ShutdownAccessible(aAccessible);
+  UnbindFromDocument(aAccessible);
 }
 
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -206,28 +206,28 @@ public:
 
   /**
    * Return the cached accessible by the given unique ID looking through
    * this and nested documents.
    */
   nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID);
 
   /**
-   * Cache the accessible.
-   *
-   * @param  aAccessible  [in] accessible to cache
+   * Initialize the newly created accessible and put it into document caches.
    *
-   * @return true if accessible being cached, otherwise false
+   * @param  aAccessible    [in] created accessible
+   * @param  aRoleMapEntry  [in] the role map entry role the ARIA role or nsnull
+   *                          if none
    */
-  PRBool CacheAccessible(nsAccessible *aAccessible);
+  bool BindToDocument(nsAccessible* aAccessible, nsRoleMapEntry* aRoleMapEntry);
 
   /**
-   * Shutdown the accessible and remove it from document cache.
+   * Remove from document and shutdown the given accessible.
    */
-  void ShutdownAccessible(nsAccessible *aAccessible);
+  void UnbindFromDocument(nsAccessible* aAccessible);
 
   /**
    * Process the event when the queue of pending events is untwisted. Fire
    * accessible events as result of the processing.
    */
   void ProcessPendingEvent(AccEvent* aEvent);
 
   /**
--- a/accessible/src/base/nsRelUtils.cpp
+++ b/accessible/src/base/nsRelUtils.cpp
@@ -129,37 +129,26 @@ nsRelUtils::AddTargetFromIDRefAttr(PRUin
   return AddTargetFromContent(aRelationType, aRelation, refContent);
 }
 
 nsresult
 nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
                                     nsIAccessibleRelation **aRelation,
                                     nsIContent *aContent, nsIAtom *aAttr)
 {
-  nsCOMPtr<nsIArray> refElms;
-  nsCoreUtils::GetElementsByIDRefsAttr(aContent, aAttr, getter_AddRefs(refElms));
-
-  if (!refElms)
-    return NS_OK_NO_RELATION_TARGET;
+  nsresult rv = NS_OK_NO_RELATION_TARGET;
 
-  PRUint32 count = 0;
-  nsresult rv = refElms->GetLength(&count);
-  if (NS_FAILED(rv) || count == 0)
-    return NS_OK_NO_RELATION_TARGET;
-
-  nsCOMPtr<nsIContent> content;
-  for (PRUint32 idx = 0; idx < count; idx++) {
-    content = do_QueryElementAt(refElms, idx, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = AddTargetFromContent(aRelationType, aRelation, content);
+  nsIContent* refElm = nsnull;
+  IDRefsIterator iter(aContent, aAttr);
+  while ((refElm = iter.NextElem())) {
+    rv = AddTargetFromContent(aRelationType, aRelation, refElm);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  return NS_OK;
+  return rv;
 }
 
 nsresult
 nsRelUtils::AddTargetFromNeighbour(PRUint32 aRelationType,
                                    nsIAccessibleRelation **aRelation,
                                    nsIContent *aContent,
                                    nsIAtom *aNeighboutAttr,
                                    nsIAtom *aNeighboutTagName)
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -87,36 +87,24 @@ nsTextEquivUtils::GetTextEquivFromIDRefs
                                          nsAString& aTextEquiv)
 {
   aTextEquiv.Truncate();
 
   nsIContent* content = aAccessible->GetContent();
   if (!content)
     return NS_OK;
 
-  nsCOMPtr<nsIArray> refElms;
-  nsCoreUtils::GetElementsByIDRefsAttr(content, aIDRefsAttr,
-                                       getter_AddRefs(refElms));
-
-  if (!refElms)
-    return NS_OK;
-
-  PRUint32 count = 0;
-  nsresult rv = refElms->GetLength(&count);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIContent> refContent;
-  for (PRUint32 idx = 0; idx < count; idx++) {
-    refContent = do_QueryElementAt(refElms, idx, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
+  nsIContent* refContent = nsnull;
+  IDRefsIterator iter(content, aIDRefsAttr);
+  while ((refContent = iter.NextElem())) {
     if (!aTextEquiv.IsEmpty())
       aTextEquiv += ' ';
 
-    rv = AppendTextEquivFromContent(aAccessible, refContent, &aTextEquiv);
+    nsresult rv = AppendTextEquivFromContent(aAccessible, refContent,
+                                             &aTextEquiv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsTextEquivUtils::AppendTextEquivFromContent(nsAccessible *aInitiatorAcc,
@@ -232,21 +220,16 @@ nsTextEquivUtils::AppendFromAccessibleCh
 
   return rv;
 }
 
 nsresult
 nsTextEquivUtils::AppendFromAccessible(nsAccessible *aAccessible,
                                        nsAString *aString)
 {
-  // Ignore hidden accessible for name computation.
-  nsIFrame* frame = aAccessible->GetFrame();
-  if (!frame || !frame->GetStyleVisibility()->IsVisible())
-    return NS_OK;
-
   //XXX: is it necessary to care the accessible is not a document?
   if (aAccessible->IsContent()) {
     nsresult rv = AppendTextEquivFromTextContent(aAccessible->GetContent(),
                                                  aString);
     if (rv != NS_OK_NO_NAME_CLAUSE_HANDLED)
       return rv;
   }
 
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp
@@ -35,16 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLImageMapAccessible.h"
 
 #include "nsAccUtils.h"
+#include "nsDocAccessible.h"
 
 #include "nsIDOMHTMLCollection.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIFrame.h"
 #include "nsIImageFrame.h"
 #include "nsIImageMap.h"
@@ -109,41 +110,35 @@ nsHTMLImageMapAccessible::CacheChildren(
   if (!mMapElement)
     return;
 
   nsCOMPtr<nsIDOMHTMLCollection> mapAreas;
   mMapElement->GetAreas(getter_AddRefs(mapAreas));
   if (!mapAreas)
     return;
 
+  nsDocAccessible* document = GetDocAccessible();
+
   PRUint32 areaCount = 0;
   mapAreas->GetLength(&areaCount);
 
   for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
     nsCOMPtr<nsIDOMNode> areaNode;
     mapAreas->Item(areaIdx, getter_AddRefs(areaNode));
     if (!areaNode)
       return;
 
     nsCOMPtr<nsIContent> areaContent(do_QueryInterface(areaNode));
-    nsRefPtr<nsAccessible> areaAcc =
+    nsRefPtr<nsAccessible> area =
       new nsHTMLAreaAccessible(areaContent, mWeakShell);
-    if (!areaAcc)
-      return;
 
-    if (!areaAcc->Init()) {
-      areaAcc->Shutdown();
+    if (!document->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)) ||
+        !AppendChild(area)) {
       return;
     }
-
-    // We must respect ARIA on area elements (for the canvas map technique)
-    areaAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(areaContent));
-
-    if (!AppendChild(areaAcc))
-      return;
   }
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLAreaAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -687,31 +687,27 @@ nsHTMLComboboxAccessible::CacheChildren(
 
   nsIFrame *listFrame = comboFrame->GetDropDown();
   if (!listFrame)
     return;
 
   if (!mListAccessible) {
     mListAccessible = 
       new nsHTMLComboboxListAccessible(mParent, mContent, mWeakShell);
-    if (!mListAccessible)
-      return;
 
     // Initialize and put into cache.
-    if (!mListAccessible->Init()) {
-      mListAccessible->Shutdown();
+    if (!GetDocAccessible()->BindToDocument(mListAccessible, nsnull))
       return;
-    }
   }
 
-  AppendChild(mListAccessible);
-
-  // Cache combobox option accessibles so that we build complete accessible tree
-  // for combobox.
-  mListAccessible->EnsureChildren();
+  if (AppendChild(mListAccessible)) {
+    // Cache combobox option accessibles so that we build complete accessible
+    // tree for combobox.
+    mListAccessible->EnsureChildren();
+  }
 }
 
 void
 nsHTMLComboboxAccessible::Shutdown()
 {
   nsAccessibleWrap::Shutdown();
 
   if (mListAccessible) {
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -303,44 +303,37 @@ nsHTMLTableCellAccessible::GetCellIndexe
   return cellLayout->GetCellIndexes(aRowIndex, aColIndex);
 }
 
 nsresult
 nsHTMLTableCellAccessible::GetHeaderCells(PRInt32 aRowOrColumnHeaderCell,
                                           nsIArray **aHeaderCells)
 {
   // Get header cells from @header attribute.
-  nsCOMPtr<nsIArray> headerCellElms;
-  nsCoreUtils::GetElementsByIDRefsAttr(mContent, nsAccessibilityAtoms::headers,
-                                       getter_AddRefs(headerCellElms));
-
-  if (headerCellElms) {
+  IDRefsIterator iter(mContent, nsAccessibilityAtoms::headers);
+  nsIContent* headerCellElm = iter.NextElem();
+  if (headerCellElm) {
     nsresult rv = NS_OK;
     nsCOMPtr<nsIMutableArray> headerCells =
       do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    PRUint32 count = 0;
-    rv = headerCellElms->GetLength(&count);
-    if (NS_SUCCEEDED(rv) && count > 0) {
-      nsCOMPtr<nsIContent> headerCellContent;
-      for (PRUint32 idx = 0; idx < count; idx++) {
-        headerCellContent = do_QueryElementAt(headerCellElms, idx, &rv);
-        nsAccessible *headerCell =
-          GetAccService()->GetAccessibleInWeakShell(headerCellContent, mWeakShell);
+    do {
+      nsAccessible* headerCell =
+        GetAccService()->GetAccessibleInWeakShell(headerCellElm, mWeakShell);
 
-        if (headerCell &&
-            (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells &&
-             headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER ||
-             aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells &&
-             headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER))
-          headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
-                                     PR_FALSE);
+      if (headerCell &&
+          (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells &&
+              headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER ||
+              aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells &&
+              headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) {
+        headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
+                                   PR_FALSE);
       }
-    }
+    } while ((headerCellElm = iter.NextElem()));
 
     NS_ADDREF(*aHeaderCells = headerCells);
     return NS_OK;
   }
 
   // Otherwise calculate header cells from hierarchy (see 11.4.3 "Algorithm to
   // find heading information" of w3c HTML 4.01).
   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -254,18 +254,17 @@ nsHTMLOutputAccessible::GetAttributesInt
 
 nsHTMLLIAccessible::
   nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
 {
   nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
   if (blockFrame && !blockFrame->BulletIsEmptyExternal()) {
     mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell);
-    if (mBulletAccessible)
-      mBulletAccessible->Init();
+    GetDocAccessible()->BindToDocument(mBulletAccessible, nsnull);
   }
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible)
 
 void
 nsHTMLLIAccessible::Shutdown()
 {
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -150,16 +150,19 @@ nsHyperTextAccessible::NativeRole()
 
   // Deal with html landmark elements
   if (tag == nsAccessibilityAtoms::header)
     return nsIAccessibleRole::ROLE_HEADER;
 
   if (tag == nsAccessibilityAtoms::footer)
     return nsIAccessibleRole::ROLE_FOOTER;
 
+  if (tag == nsAccessibilityAtoms::aside)
+    return nsIAccessibleRole::ROLE_NOTE;
+
   // Treat block frames as paragraphs
   nsIFrame *frame = GetFrame();
   if (frame && frame->GetType() == nsAccessibilityAtoms::blockFrame &&
       frame->GetContent()->Tag() != nsAccessibilityAtoms::input) {
     // An html:input @type="file" is the only input that is exposed as a
     // blockframe. It must be exposed as ROLE_TEXT_CONTAINER for JAWS.
     return nsIAccessibleRole::ROLE_PARAGRAPH;
   }
@@ -1216,16 +1219,19 @@ nsHyperTextAccessible::GetAttributesInte
     nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
                            NS_LITERAL_STRING("banner"));
   else if (mContent->Tag() == nsAccessibilityAtoms::footer) 
     nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
                            NS_LITERAL_STRING("contentinfo"));
   else if (mContent->Tag() == nsAccessibilityAtoms::article) 
     nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
                            NS_LITERAL_STRING("main"));
+  else if (mContent->Tag() == nsAccessibilityAtoms::aside) 
+    nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
+                           NS_LITERAL_STRING("note"));
 
   return  NS_OK;
 }
 
 /*
  * Given an offset, the x, y, width, and height values are filled appropriately.
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetCharacterExtents(PRInt32 aOffset, PRInt32 *aX, PRInt32 *aY,
--- a/accessible/src/mac/nsRoleMap.h
+++ b/accessible/src/mac/nsRoleMap.h
@@ -160,10 +160,11 @@ static const NSString* AXRoles [] = {
   NSAccessibilityMenuItemRole,                  // ROLE_COMBOBOX_OPTION
   NSAccessibilityImageRole,                     // ROLE_IMAGE_MAP
   NSAccessibilityRowRole,                       // ROLE_OPTION
   NSAccessibilityRowRole,                       // ROLE_RICH_OPTION
   NSAccessibilityListRole,                      // ROLE_LISTBOX
   NSAccessibilityUnknownRole,                   // ROLE_FLAT_EQUATION
   NSAccessibilityGroupRole,                     // ROLE_GRID_CELL
   NSAccessibilityGroupRole,                     // ROLE_EMBEDDED_OBJECT
+  NSAccessibilityGroupRole,                     // ROLE_NOTE
   @"ROLE_LAST_ENTRY"                            // ROLE_LAST_ENTRY. bogus role that will never be shown (just marks the end of this array)!
 };
--- a/accessible/src/msaa/nsRoleMap.h
+++ b/accessible/src/msaa/nsRoleMap.h
@@ -438,12 +438,15 @@ static const WindowsRoleMapItem gWindows
   { ROLE_SYSTEM_EQUATION, ROLE_SYSTEM_EQUATION },
   
   // nsIAccessibleRole::ROLE_GRID_CELL
   { ROLE_SYSTEM_CELL, ROLE_SYSTEM_CELL },
 
   // nsIAccessibleRole::ROLE_EMBEDDED_OBJECT
   { USE_ROLE_STRING, IA2_ROLE_EMBEDDED_OBJECT },
 
+  // nsIAccessibleRole::ROLE_NOTE
+  { USE_ROLE_STRING, IA2_ROLE_NOTE },
+
   // nsIAccessibleRole::ROLE_LAST_ENTRY
   { ROLE_WINDOWS_LAST_ENTRY, ROLE_WINDOWS_LAST_ENTRY }
 };
 
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXULColorPickerAccessible.h"
 
 #include "nsAccUtils.h"
 #include "nsAccTreeWalker.h"
 #include "nsCoreUtils.h"
+#include "nsDocAccessible.h"
 
 #include "nsIDOMElement.h"
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULColorPickerTileAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -166,10 +167,13 @@ nsXULColorPickerAccessible::CacheChildre
   while ((child = walker.GetNextChild())) {
     PRUint32 role = child->Role();
 
     // Get an accessbile for menupopup or panel elements.
     if (role == nsIAccessibleRole::ROLE_ALERT) {
       AppendChild(child);
       return;
     }
+
+    // Unbind rejected accessibles from the document.
+    GetDocAccessible()->UnbindFromDocument(child);
   }
 }
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXULFormControlAccessible.h"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
 #include "nsAccTreeWalker.h"
 #include "nsCoreUtils.h"
+#include "nsDocAccessible.h"
 #include "nsRelUtils.h"
 
 // NOTE: alphabetically ordered
 #include "nsHTMLFormControlAccessible.h"
 #include "nsXULMenuAccessible.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMXULButtonElement.h"
@@ -217,16 +218,20 @@ nsXULButtonAccessible::CacheChildren()
       // Get an accessbile for menupopup or panel elements.
       menupopupAccessible.swap(child);
 
     } else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
       // Button type="menu-button" contains a real button. Get an accessible
       // for it. Ignore dropmarker button what is placed as a last child.
       buttonAccessible.swap(child);
       break;
+
+    } else {
+      // Unbind rejected accessible from document.
+      GetDocAccessible()->UnbindFromDocument(child);
     }
   }
 
   if (!menupopupAccessible)
     return;
 
   AppendChild(menupopupAccessible);
   if (buttonAccessible)
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -467,61 +467,58 @@ nsXULTreeAccessible::GetTreeItemAccessib
     return nsnull;
 
   PRInt32 rowCount = 0;
   nsresult rv = mTreeView->GetRowCount(&rowCount);
   if (NS_FAILED(rv) || aRow >= rowCount)
     return nsnull;
 
   void *key = reinterpret_cast<void*>(aRow);
-  nsRefPtr<nsAccessible> accessible = mAccessibleCache.GetWeak(key);
-
-  if (!accessible) {
-    accessible = CreateTreeItemAccessible(aRow);
-    if (!accessible)
-      return nsnull;
+  nsAccessible* cachedTreeItem = mAccessibleCache.GetWeak(key);
+  if (cachedTreeItem)
+    return cachedTreeItem;
 
-    if (!accessible->Init()) {
-      accessible->Shutdown();
-      return nsnull;
+  nsRefPtr<nsAccessible> treeItem = CreateTreeItemAccessible(aRow);
+  if (treeItem) {
+    if (mAccessibleCache.Put(key, treeItem)) {
+      if (GetDocAccessible()->BindToDocument(treeItem, nsnull))
+        return treeItem;
+
+      mAccessibleCache.Remove(key);
     }
-
-    if (!mAccessibleCache.Put(key, accessible))
-      return nsnull;
   }
 
-  return accessible;
+  return nsnull;
 }
 
 void
 nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
 {
   if (IsDefunct())
     return;
 
   // Do not invalidate the cache if rows have been inserted.
   if (aCount > 0)
     return;
 
+  nsDocAccessible* document = GetDocAccessible();
+
   // Fire destroy event for removed tree items and delete them from caches.
   for (PRInt32 rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) {
 
     void* key = reinterpret_cast<void*>(rowIdx);
-    nsAccessible *accessible = mAccessibleCache.GetWeak(key);
+    nsAccessible* treeItem = mAccessibleCache.GetWeak(key);
 
-    if (accessible) {
+    if (treeItem) {
       nsRefPtr<AccEvent> event =
-        new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible);
+        new AccEvent(nsIAccessibleEvent::EVENT_HIDE, treeItem);
       nsEventShell::FireEvent(event);
 
-      // Shutdown and remove accessible from document cache and tree cache.
-      nsDocAccessible *docAccessible = GetDocAccessible();
-      if (docAccessible)
-        docAccessible->ShutdownAccessible(accessible);
-
+      // Unbind from document, shutdown and remove from tree cache.
+      document->UnbindFromDocument(treeItem);
       mAccessibleCache.Remove(key);
     }
   }
 
   // We dealt with removed tree items already however we may keep tree items
   // having row indexes greater than row count. We should remove these dead tree
   // items silently from caches.
   PRInt32 newRowCount = 0;
@@ -529,24 +526,21 @@ nsXULTreeAccessible::InvalidateCache(PRI
   if (NS_FAILED(rv))
     return;
 
   PRInt32 oldRowCount = newRowCount - aCount;
 
   for (PRInt32 rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) {
 
     void *key = reinterpret_cast<void*>(rowIdx);
-    nsAccessible *accessible = mAccessibleCache.GetWeak(key);
+    nsAccessible* treeItem = mAccessibleCache.GetWeak(key);
 
-    if (accessible) {
-      // Shutdown and remove accessible from document cache and tree cache.
-      nsDocAccessible *docAccessible = GetDocAccessible();
-      if (docAccessible)
-        docAccessible->ShutdownAccessible(accessible);
-
+    if (treeItem) {
+      // Unbind from document, shutdown and remove from tree cache.
+      document->UnbindFromDocument(treeItem);
       mAccessibleCache.Remove(key);
     }
   }
 }
 
 void
 nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
                                          PRInt32 aStartCol, PRInt32 aEndCol)
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXULTreeGridAccessibleWrap.h"
 
 #include "nsAccCache.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
+#include "nsDocAccessible.h"
 #include "nsEventShell.h"
 
 #include "nsITreeSelection.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -724,35 +725,33 @@ nsXULTreeGridRowAccessible::GetChildCoun
 // nsXULTreeGridRowAccessible: nsXULTreeItemAccessibleBase implementation
 
 nsAccessible*
 nsXULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn)
 {
   NS_PRECONDITION(aColumn, "No tree column!");
 
   void* key = static_cast<void*>(aColumn);
-  nsRefPtr<nsAccessible> accessible = mAccessibleCache.GetWeak(key);
+  nsAccessible* cachedCell = mAccessibleCache.GetWeak(key);
+  if (cachedCell)
+    return cachedCell;
 
-  if (!accessible) {
-    accessible =
-      new nsXULTreeGridCellAccessibleWrap(mContent, mWeakShell, this, mTree,
-                                          mTreeView, mRow, aColumn);
-    if (!accessible)
-      return nsnull;
+  nsRefPtr<nsAccessible> cell =
+    new nsXULTreeGridCellAccessibleWrap(mContent, mWeakShell, this, mTree,
+                                        mTreeView, mRow, aColumn);
+  if (cell) {
+    if (mAccessibleCache.Put(key, cell)) {
+      if (GetDocAccessible()->BindToDocument(cell, nsnull))
+        return cell;
 
-    if (!accessible->Init()) {
-      accessible->Shutdown();
-      return nsnull;
+      mAccessibleCache.Remove(key);
     }
-
-    if (!mAccessibleCache.Put(key, accessible))
-      return nsnull;
   }
 
-  return accessible;
+  return nsnull;
 }
 
 void
 nsXULTreeGridRowAccessible::RowInvalidated(PRInt32 aStartColIdx,
                                            PRInt32 aEndColIdx)
 {
   nsCOMPtr<nsITreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -46,16 +46,17 @@ DIRS	= \
   actions \
   attributes \
   events \
   hyperlink \
   relations \
   selectable \
   states \
   table \
+  text \
   tree \
   treeupdate \
   $(null)
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
@@ -116,14 +117,15 @@ include $(topsrcdir)/config/rules.mk
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
 		test_text_caret.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		test_value.html \
 		test_value.xul \
 		testTextboxes.js \
+		text.js \
 		treeview.css \
 		treeview.js \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -315,37 +315,51 @@ function ensureAccessibleTree(aAccOrElmO
  *                                      fields
  */
 function testAccessibleTree(aAccOrElmOrID, aAccTree)
 {
   var acc = getAccessible(aAccOrElmOrID);
   if (!acc)
     return;
 
-  for (var prop in aAccTree) {
+  var accTree = aAccTree;
+
+  // Support of simplified accessible tree object.
+  var key = Object.keys(accTree)[0];
+  var roleName = "ROLE_" + key;
+  if (roleName in nsIAccessibleRole) {
+    accTree = {
+      role: nsIAccessibleRole[roleName],
+      children: accTree[key]
+    };
+  }
+
+  // Test accessible properties.
+  for (var prop in accTree) {
     var msg = "Wrong value of property '" + prop + "' for " + prettyName(acc) + ".";
     if (prop == "role") {
-      is(roleToString(acc[prop]), roleToString(aAccTree[prop]), msg);
+      is(roleToString(acc[prop]), roleToString(accTree[prop]), msg);
 
     } else if (prop == "states") {
-      var statesObj = aAccTree[prop];
+      var statesObj = accTree[prop];
       testStates(acc, statesObj.states, statesObj.extraStates,
                  statesObj.absentStates, statesObj.absentExtraStates);
 
     } else if (prop != "children") {
-      is(acc[prop], aAccTree[prop], msg);
+      is(acc[prop], accTree[prop], msg);
     }
   }
 
-  if ("children" in aAccTree && aAccTree["children"] instanceof Array) {
+  // Test children.
+  if ("children" in accTree && accTree["children"] instanceof Array) {
     var children = acc.children;
-    is(children.length, aAccTree.children.length,
+    is(children.length, accTree.children.length,
        "Different amount of expected children of " + prettyName(acc) + ".");
 
-    if (aAccTree.children.length == children.length) {
+    if (accTree.children.length == children.length) {
       var childCount = children.length;
 
       // nsIAccessible::firstChild
       var expectedFirstChild = childCount > 0 ?
         children.queryElementAt(0, nsIAccessible) : null;
       var firstChild = null;
       try { firstChild = acc.firstChild; } catch (e) {}
       is(firstChild, expectedFirstChild,
@@ -385,17 +399,17 @@ function testAccessibleTree(aAccOrElmOrI
         var expectedPrevSibling = (i > 0) ?
           children.queryElementAt(i - 1, nsIAccessible) : null;
         var prevSibling = null;
         try { prevSibling = child.previousSibling; } catch (e) {}
         is(prevSibling, expectedPrevSibling,
            "Wrong previous sibling of " + prettyName(child));
 
         // Go down through subtree
-        testAccessibleTree(child, aAccTree.children[i]);
+        testAccessibleTree(child, accTree.children[i]);
       }
     }
   }
 }
 
 /**
  * Return true if accessible for the given node is in cache.
  */
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -288,23 +288,36 @@
 
       // Show/hide events by changing of display style of accessible DOM node
       // from 'inline' to 'none', 'none' to 'inline'.
       var id = "link1";
       getAccessible(id); // ensure accessible is created
       gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
       gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
 
+      // Show/hide events by changing of visibility style of accessible DOM node
+      // from 'visible' to 'hidden', 'hidden' to 'visible'.
+      var id = "link2";
+      getAccessible(id);
+      gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
+      gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
+
       // Show/hide events by changing of display style of accessible DOM node
       // from 'inline' to 'block', 'block' to 'inline'.
       var id = "link3";
       getAccessible(id); // ensure accessible is created
       gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
       gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
 
+      // Show/hide events by changing of visibility style of accessible DOM node
+      // from 'collapse' to 'visible', 'visible' to 'collapse'.
+      var id = "link4";
+      gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
+      gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
+
       // Show/hide events by adding new accessible DOM node and removing old one.
       var id = "link5";
       gQueue.push(new cloneAndAppendToDOM(id));
       gQueue.push(new removeFromDOM(id));
 
       // No show/hide events by adding new not accessible DOM node and removing
       // old one, no reorder event for their parent.
       var id = "child1";
@@ -338,16 +351,20 @@
       getAccessible("link6"); // ensure accessible is created
       gQueue.push(new cloneAndReplaceInDOM("link6"));
 
       // Show/hide events by changing class name on the parent node.
       gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
       gQueue.push(new changeClass("container2", "link7", "displayNone",
                                   kHideEvents));
 
+      gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
+      gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
+                                  kHideEvents));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -362,16 +379,21 @@
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=472662"
      title="no reorder event when html:link display property is changed from 'none' to 'inline'">
     Mozilla Bug 472662
   </a><br>
   <a target="_blank"
      title="Rework accessible tree update code"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
     Mozilla Bug 570275
+  </a><br>
+  <a target="_blank"
+     title="Develop a way to handle visibility style"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=606125">
+    Mozilla Bug 606125
   </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -32,16 +32,17 @@ const ROLE_INTERNAL_FRAME = nsIAccessibl
 const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
 const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
 const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
 const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
 const ROLE_LISTITEM = nsIAccessibleRole.ROLE_LISTITEM;
 const ROLE_MENUITEM = nsIAccessibleRole.ROLE_MENUITEM;
 const ROLE_MENUPOPUP = nsIAccessibleRole.ROLE_MENUPOPUP;
 const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
+const ROLE_NOTE = nsIAccessibleRole.ROLE_NOTE;
 const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
 const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
 const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
 const ROLE_PAGETAB = nsIAccessibleRole.ROLE_PAGETAB;
 const ROLE_PAGETABLIST = nsIAccessibleRole.ROLE_PAGETABLIST;
 const ROLE_PANE = nsIAccessibleRole.ROLE_PANE;
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
--- a/accessible/tests/mochitest/test_aria_roles.html
+++ b/accessible/tests/mochitest/test_aria_roles.html
@@ -66,29 +66,36 @@ https://bugzilla.mozilla.org/show_bug.cg
                             "sectionhead"];
       for (a in abstract_roles)
         testRole(abstract_roles[a], ROLE_SECTION);
 
       // misc roles
       testRole("scrollbar", ROLE_SCROLLBAR);
       testRole("dir", ROLE_LIST);
 
+      // test document role map update
+      var testDoc = getAccessible(document, [nsIAccessibleDocument]);
+      testRole(testDoc, ROLE_DOCUMENT);
+      document.body.setAttribute("role", "application");
+      testRole(testDoc, ROLE_APPLICATION);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 469688</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 520188</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 529289</a>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 607219</a>
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   
   <!-- "live" roles -->
   <table role="log" id="log_table">
--- a/accessible/tests/mochitest/test_elm_landmarks.html
+++ b/accessible/tests/mochitest/test_elm_landmarks.html
@@ -20,29 +20,32 @@
   <script type="application/javascript">
 
     function doTest()
     {
       testRole("nav", ROLE_SECTION);
       testRole("header", ROLE_HEADER);
       testRole("footer", ROLE_FOOTER);
       testRole("article", ROLE_SECTION);
+      testRole("aside", ROLE_NOTE);
 
       // Some AT may look for this
       testAttrs("nav", {"xml-roles" : "navigation"}, true);
       testAttrs("header", {"xml-roles" : "banner"}, true);
       testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
       testAttrs("article", {"xml-roles" : "main"}, true);
+      testAttrs("aside", {"xml-roles" : "note"}, true);
       testAttrs("document", {"xml-roles" : "document"}, true); // ARIA override
 
       // And some AT may look for this
       testAttrs("nav", {"tag" : "NAV"}, true);
       testAttrs("header", {"tag" : "HEADER"}, true);
       testAttrs("footer", {"tag" : "FOOTER"}, true);
       testAttrs("article", {"tag" : "ARTICLE"}, true);
+      testAttrs("aside", {"tag" : "ASIDE"}, true);
       testAttrs("document", {"tag" : "ARTICLE"}, true); // no override expected
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
@@ -56,13 +59,14 @@
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <nav id="nav">a nav</nav>
   <header id="header">a header</header>
   <footer id="footer">a footer</footer>
   <article id="article">an article</article>
+  <aside id="aside">by the way I am an aside</aside>
 
   <article id="document" role="document">a document</article>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text.js
@@ -0,0 +1,180 @@
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+const BOUNDARY_CHAR = nsIAccessibleText.BOUNDARY_CHAR;
+const BOUNDARY_WORD_START = nsIAccessibleText.BOUNDARY_WORD_START;
+const BOUNDARY_WORD_END = nsIAccessibleText.BOUNDARY_WORD_END;
+const BOUNDARY_LINE_START = nsIAccessibleText.BOUNDARY_LINE_START;
+const BOUNDARY_LINE_END = nsIAccessibleText.BOUNDARY_LINE_END;
+const BOUNDARY_ATTRIBUTE_RANGE = nsIAccessibleText.BOUNDARY_ATTRIBUTE_RANGE;
+
+const kTodo = 1;
+const kOk = 2;
+
+function testText(aIDs, aStartOffset, aEndOffset, aText)
+{
+  for (var i = 0; i < aIDs.length; i++)
+  {
+    var acc = getAccessible(aIDs[i], nsIAccessibleText);
+    try {
+      is(acc.getText(aStartOffset, aEndOffset), aText,
+         "getText: wrong text between start and end offsets '" + aStartOffset +
+         "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'");
+    } catch (e) {
+      ok(false,
+         "getText fails between start and end offsets '" + aStartOffset +
+         "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'");
+    }
+  }
+}
+
+/**
+ * Test getTextAtOffset function over different elements
+ *
+ * @param aOffset         [in] the offset to get the text at
+ * @param aBoundaryType   [in] Boundary type for text to be retrieved
+ * @param aText           [in] expected return text for getTextAtOffset
+ * @param aStartOffset    [in] expected return start offset for getTextAtOffset
+ * @param aEndOffset      [in] expected return end offset for getTextAtOffset
+ * @param ...             [in] list of tuples made of:
+ *                              element identifier
+ *                              kTodo or kOk for returned text
+ *                              kTodo or kOk for returned start offset
+ *                              kTodo or kOk for returned offset result
+ *          
+ */
+function testTextAtOffset(aOffset, aBoundaryType, aText,
+                          aStartOffset, aEndOffset)
+{
+  for (var i = 5; i < arguments.length; i = i + 4) {
+    var ID = arguments[i];
+    var acc = getAccessible(ID, nsIAccessibleText);
+    var toDoFlag1 = arguments[i + 1];
+    var toDoFlag2 = arguments[i + 2];
+    var toDoFlag3 = arguments[i + 3];
+
+    testTextHelper(ID, aOffset, aBoundaryType,
+                   aText, aStartOffset, aEndOffset,
+                   toDoFlag1, toDoFlag2, toDoFlag3,
+                   acc.getTextAtOffset, "getTextAtOffset ");
+  }
+}
+
+/**
+ * Test getTextAfterOffset function over different elements
+ *
+ * @param aOffset         [in] the offset to get the text after
+ * @param aBoundaryType   [in] Boundary type for text to be retrieved
+ * @param aText           [in] expected return text for getTextAfterOffset
+ * @param aStartOffset    [in] expected return start offset for getTextAfterOffset
+ * @param aEndOffset      [in] expected return end offset for getTextAfterOffset
+ * @param ...             [in] list of tuples made of:
+ *                              element identifier
+ *                              kTodo or kOk for returned text
+ *                              kTodo or kOk for returned start offset
+ *                              kTodo or kOk for returned offset result
+ *          
+ */
+function testTextAfterOffset(aOffset, aBoundaryType,
+                             aText, aStartOffset, aEndOffset)
+{
+  for (var i = 5; i < arguments.length; i = i + 4) {
+    var ID = arguments[i];
+    var acc = getAccessible(ID, nsIAccessibleText);
+    var toDoFlag1 = arguments[i + 1];
+    var toDoFlag2 = arguments[i + 2];
+    var toDoFlag3 = arguments[i + 3];
+
+    testTextHelper(ID, aOffset, aBoundaryType,
+                   aText, aStartOffset, aEndOffset,
+                   toDoFlag1, toDoFlag2, toDoFlag3, 
+                   acc.getTextAfterOffset, "getTextAfterOffset ");
+  }
+}
+
+/**
+ * Test getTextBeforeOffset function over different elements
+ *
+ * @param aOffset         [in] the offset to get the text before
+ * @param aBoundaryType   [in] Boundary type for text to be retrieved
+ * @param aText           [in] expected return text for getTextBeforeOffset
+ * @param aStartOffset    [in] expected return start offset for getTextBeforeOffset
+ * @param aEndOffset      [in] expected return end offset for getTextBeforeOffset
+ * @param ...             [in] list of tuples made of:
+ *                              element identifier
+ *                              kTodo or kOk for returned text
+ *                              kTodo or kOk for returned start offset
+ *                              kTodo or kOk for returned offset result
+ *          
+ */
+function testTextBeforeOffset(aOffset, aBoundaryType,
+                              aText, aStartOffset, aEndOffset)
+{
+  for (var i = 5; i < arguments.length; i = i + 4) {
+    var ID = arguments[i];
+    var acc = getAccessible(ID, nsIAccessibleText);
+    var toDoFlag1 = arguments[i + 1];
+    var toDoFlag2 = arguments[i + 2];
+    var toDoFlag3 = arguments[i + 3];
+
+    testTextHelper(ID, aOffset, aBoundaryType,
+                   aText, aStartOffset, aEndOffset,
+                   toDoFlag1, toDoFlag2, toDoFlag3,
+                   acc.getTextBeforeOffset, "getTextBeforeOffset ");
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+function testTextHelper(aID, aOffset, aBoundaryType,
+                        aText, aStartOffset, aEndOffset,
+                        aToDoFlag1, aToDoFlag2, aToDoFlag3,
+                        aTextFunc, aTextFuncName)
+{
+  var exceptionFlag = aToDoFlag1 == undefined ||
+                      aToDoFlag2 == undefined ||
+                      aToDoFlag3 == undefined;
+  try {
+    var startOffsetObj = {}, endOffsetObj = {};
+    var text = aTextFunc(aOffset, aBoundaryType,
+                         startOffsetObj, endOffsetObj);
+    
+    var isFunc1 = (aToDoFlag1 == kTodo) ? todo_is : is;
+    var isFunc2 = (aToDoFlag2 == kTodo) ? todo_is : is;
+    var isFunc3 = (aToDoFlag3 == kTodo) ? todo_is : is;
+
+    var startMsg = aTextFuncName + "(" + boundaryToString(aBoundaryType) + "): ";
+
+    var endMsg = ", id: '" + prettyName(aID) + "';";
+    
+    isFunc1(text, aText,
+            startMsg + "wrong text, offset: " + aOffset + endMsg);
+    isFunc2(startOffsetObj.value, aStartOffset,
+            startMsg + "wrong start offset, offset: " + aOffset + endMsg);
+    isFunc3(endOffsetObj.value, aEndOffset,
+            startMsg + "wrong end offset, offset: " + aOffset + endMsg);
+    
+  } catch (e) {
+    var okFunc = exceptionFlag ? todo : ok;
+    okFunc(false, startMsg + "failed at offset " + aOffset + endMsg);
+  }
+}
+
+function boundaryToString(aBoundaryType)
+{
+  switch (aBoundaryType) {
+    case BOUNDARY_CHAR:
+      return "char";
+    case BOUNDARY_WORD_START:
+      return "word start";
+    case BOUNDARY_WORD_END:
+      return "word end";
+    case BOUNDARY_LINE_START:
+      return "line start";
+    case BOUNDARY_LINE_END:
+      return "line end";
+    case BOUNDARY_ATTRIBUTE_RANGE:
+      return "attr range";
+  }
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Fernando Herrera <fherrera@onirica.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/text
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+		test_singleline.html \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text/test_singleline.html
@@ -0,0 +1,574 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>nsIAccessibleText getText related function tests for html:input,html:div and html:textarea</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="../text.js"></script>
+  <script type="application/javascript">
+    
+    function doTest()
+    {
+      var IDs = ["input", "div", "textarea"];
+  
+      // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
+      //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+
+      ////////////////////////////////////////////////////////////////////////
+      // getText
+
+      testText(IDs, 0, 1, "h");
+      testText(IDs, 1, 3, "el");
+      testText(IDs, 14, 15, "d");
+      testText(IDs, 0, 15, "hello my friend");
+
+      ////////////////////////////////////////////////////////////////////////
+      // getTextAfterOffset
+
+      // BOUNDARY_CHAR
+      testTextAfterOffset(0, BOUNDARY_CHAR, "e", 1, 2,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(1, BOUNDARY_CHAR, "l", 2, 3,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(14, BOUNDARY_CHAR, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(15, BOUNDARY_CHAR, "", 15, 15,
+			  "input", kOk, kTodo, kTodo,
+			  "div", kOk, kTodo, kTodo,
+			  "editable", kOk, kTodo, kTodo,
+			  "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_WORD_START
+      testTextAfterOffset(0, BOUNDARY_WORD_START, "my ", 6, 9,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(1, BOUNDARY_WORD_START, "my ", 6, 9,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(5, BOUNDARY_WORD_START, "my ", 6, 9,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(6, BOUNDARY_WORD_START, "friend", 9, 15,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(7, BOUNDARY_WORD_START, "friend", 9, 15,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(8, BOUNDARY_WORD_START, "friend", 9, 15,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(9, BOUNDARY_WORD_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(11, BOUNDARY_WORD_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(14, BOUNDARY_WORD_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(15, BOUNDARY_WORD_START, "", 15, 15,
+                          "input", kOk, kTodo, kTodo,
+                          "div", kOk, kTodo, kTodo,
+                          "editable", kOk, kTodo, kTodo,
+                          "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_WORD_END
+      testTextAfterOffset(0, BOUNDARY_WORD_END, " my", 5, 8,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(1, BOUNDARY_WORD_END, " my", 5, 8,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(5, BOUNDARY_WORD_END, " my", 5, 8,
+                          "input", kOk, kOk, kOk,
+                          "div", kOk, kOk, kOk,
+                          "editable", kOk, kOk, kOk,
+                          "textarea", kOk, kOk, kOk);
+      testTextAfterOffset(6, BOUNDARY_WORD_END, " friend", 8, 15,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(7, BOUNDARY_WORD_END, " friend", 8, 15,
+                          "input", kTodo, kTodo, kTodo,
+                          "div", kTodo, kTodo, kTodo,
+                          "editable", kTodo, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(8, BOUNDARY_WORD_END, " friend", 8, 15,
+                          "input", kOk, kOk, kOk,
+                          "div", kOk, kOk, kOk,
+                          "editable", kOk, kOk, kOk,
+                          "textarea", kOk, kOk, kOk);
+      testTextAfterOffset(9, BOUNDARY_WORD_END, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(11, BOUNDARY_WORD_END, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(14, BOUNDARY_WORD_END, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(15, BOUNDARY_WORD_END, "", 15, 15,
+                          "input", kOk, kTodo, kTodo,
+                          "div", kOk, kTodo, kTodo,
+                          "editable", kOk, kTodo, kTodo,
+                          "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_LINE_START
+      testTextAfterOffset(0, BOUNDARY_LINE_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(1, BOUNDARY_LINE_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(14, BOUNDARY_LINE_START, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kTodo);
+      testTextAfterOffset(15, BOUNDARY_LINE_START, "", 15, 15,
+                          "input", undefined, undefined, undefined,
+                          "div", undefined, undefined, undefined,
+                          "editable", undefined, undefined, undefined,
+                          "textarea", kTodo, undefined, kTodo);
+
+      // BOUNDARY_LINE_END
+      testTextAfterOffset(0, BOUNDARY_LINE_END, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(1, BOUNDARY_LINE_END, "", 15, 15,
+                          "input", kTodo, kTodo, kOk,
+                          "div", kTodo, kTodo, kOk,
+                          "editable", kTodo, kTodo, kOk,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(14, BOUNDARY_LINE_END, "", 15, 15,
+                          "input", kOk, kTodo, kTodo,
+                          "div", kOk, kTodo, kTodo,
+                          "editable", kOk, kTodo, kTodo,
+                          "textarea", kTodo, kTodo, kOk);
+      testTextAfterOffset(15, BOUNDARY_LINE_END, "", 15, 15,
+                          "input", kOk, kTodo, kTodo,
+                          "div", kOk, kTodo, kTodo,
+                          "editable", kOk, kTodo, kTodo,
+                          "textarea", kOk, kTodo, kTodo);
+
+      ////////////////////////////////////////////////////////////////////////
+      // getTextBeforeOffset
+
+      // BOUNDARY_CHAR
+      testTextBeforeOffset(0, BOUNDARY_CHAR, "", 0, 0, 
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(1, BOUNDARY_CHAR, "h", 0, 1,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(14, BOUNDARY_CHAR, "n", 13, 14,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(15, BOUNDARY_CHAR, "d", 14, 15,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_WORD_START
+      testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(5, BOUNDARY_WORD_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(8, BOUNDARY_WORD_START, "hello ", 0, 6,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(14, BOUNDARY_WORD_START, "my ", 6, 9,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(15, BOUNDARY_WORD_START, "my ", 6, 9,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+
+      // BOUNDARY_WORD_END
+      testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(5, BOUNDARY_WORD_END, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello ", 0, 6,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello ", 0, 6,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(8, BOUNDARY_WORD_END, "hello ", 0, 6,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(9, BOUNDARY_WORD_END, " my", 5, 8,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(10, BOUNDARY_WORD_END, " my", 5, 8,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(14, BOUNDARY_WORD_END, " my", 5, 8,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(15, BOUNDARY_WORD_END, " my", 5, 8,
+                           "input", kTodo, kTodo, kTodo,
+                           "div", kTodo, kTodo, kTodo,
+                           "editable", kTodo, kTodo, kTodo,
+                           "textarea", kTodo, kTodo, kTodo);
+
+      // BOUNDARY_LINE_START
+      testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(14, BOUNDARY_LINE_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(15, BOUNDARY_LINE_START, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_LINE_END
+      testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0,
+                           "input", kTodo, kOk, kTodo,
+                           "div", kTodo, kOk, kTodo,
+                           "editable", kTodo, kOk, kTodo,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(14, BOUNDARY_LINE_END, "", 0, 0,
+                           "input", kOk, kOk, kOk,
+                           "div", kOk, kOk, kOk,
+                           "editable", kOk, kOk, kOk,
+                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(15, BOUNDARY_LINE_END, "", 0, 0,
+                           "input", kOk, kOk, kOk,
+                           "div", kOk, kOk, kOk,
+                           "editable", kOk, kOk, kOk,
+                           "textarea", kOk, kOk, kOk);
+
+      ////////////////////////////////////////////////////////////////////////
+      // getTextAtOffset
+
+      // BOUNDARY_CHAR
+      testTextAtOffset(0, BOUNDARY_CHAR, "h", 0, 1,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(1, BOUNDARY_CHAR, "e", 1, 2,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(14, BOUNDARY_CHAR, "d", 14, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(15, BOUNDARY_CHAR, "", 15, 15,
+                        "input", kOk, kTodo, kTodo,
+                        "div", kOk, kTodo, kTodo,
+                        "editable", kOk, kTodo, kTodo,
+                        "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_WORD_START
+      testTextAtOffset(0, BOUNDARY_WORD_START, "hello ", 0, 6,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(1, BOUNDARY_WORD_START, "hello ", 0, 6,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(5, BOUNDARY_WORD_START, "hello ", 0, 6,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(6, BOUNDARY_WORD_START, "my ", 6, 9,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(7, BOUNDARY_WORD_START, "my ", 6, 9,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(8, BOUNDARY_WORD_START, "my ", 6, 9,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(9, BOUNDARY_WORD_START, "friend", 9, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(10, BOUNDARY_WORD_START, "friend", 9, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(14, BOUNDARY_WORD_START, "friend", 9, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(15, BOUNDARY_WORD_START, "friend", 9, 15,
+                       "input", kTodo, kTodo, kTodo,
+                       "div", kTodo, kTodo, kTodo,
+                       "editable", kTodo, kTodo, kTodo,
+                       "textarea", kTodo, kTodo, kTodo);
+
+      // BOUNDARY_WORD_END
+      testTextAtOffset(0, BOUNDARY_WORD_END, "hello", 0, 5,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(1, BOUNDARY_WORD_END, "hello", 0, 5,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(5, BOUNDARY_WORD_END, "hello", 0, 5,
+                       "input", kTodo, kTodo, kTodo,
+                       "div", kTodo, kTodo, kTodo,
+                       "editable", kTodo, kTodo, kTodo,
+                       "textarea", kTodo, kTodo, kTodo);
+      testTextAtOffset(6, BOUNDARY_WORD_END, " my", 5, 8,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(7, BOUNDARY_WORD_END, " my", 5, 8,
+                        "input", kOk, kOk, kOk,
+                        "div", kOk, kOk, kOk,
+                        "editable", kOk, kOk, kOk,
+                        "textarea", kOk, kOk, kOk);
+      testTextAtOffset(8, BOUNDARY_WORD_END, " my", 5, 8,
+                       "input", kTodo, kTodo, kTodo,
+                       "div", kTodo, kTodo, kTodo,
+                       "editable", kTodo, kTodo, kTodo,
+                       "textarea", kTodo, kTodo, kTodo);
+      testTextAtOffset(9, BOUNDARY_WORD_END, " friend", 8, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(10, BOUNDARY_WORD_END, " friend", 8, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(14, BOUNDARY_WORD_END, " friend", 8, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(15, BOUNDARY_WORD_END, " friend", 8, 15,
+                        "input", kTodo, kTodo, kTodo,
+                        "div", kTodo, kTodo, kTodo,
+                        "editable", kTodo, kTodo, kTodo,
+                        "textarea", kTodo, kTodo, kTodo);
+
+      // BOUNDARY_LINE_START
+      testTextAtOffset(0, BOUNDARY_LINE_START, "hello my friend", 0, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kTodo, kOk, kTodo);
+      testTextAtOffset(1, BOUNDARY_LINE_START, "hello my friend", 0, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+                       "textarea", kTodo, kOk, kTodo);
+      testTextAtOffset(14, BOUNDARY_LINE_START, "hello my friend", 0, 15,
+                       "input", kOk, kOk, kOk,
+                       "div", kOk, kOk, kOk,
+                       "editable", kOk, kOk, kOk,
+			       "textarea", kTodo, kOk, kTodo);
+      testTextAtOffset(15, BOUNDARY_LINE_START, "hello my friend", 0, 15,
+		       "input", kOk, kOk, kOk,
+		       "div", kOk, kOk, kOk,
+		       "editable", kOk, kOk, kOk,
+		       "textarea", kTodo, kOk, kTodo);
+
+      // BOUNDARY_LINE_END
+      testTextAtOffset(0, BOUNDARY_LINE_END, "hello my friend", 0, 15,
+		       "input", kOk, kOk, kOk,
+		       "div", kOk, kOk, kOk,
+		       "editable", kOk, kOk, kOk,
+		       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(1, BOUNDARY_LINE_END, "hello my friend", 0, 15,
+		       "input", kOk, kOk, kOk,
+		       "div", kOk, kOk, kOk,
+		       "editable", kOk, kOk, kOk,
+		       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(14, BOUNDARY_LINE_END, "hello my friend", 0, 15,
+		       "input", kTodo, kOk, kTodo,
+		       "div", kTodo, kOk, kTodo,
+		       "editable", kTodo, kOk, kTodo,
+		       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(15, BOUNDARY_LINE_END, "hello my friend", 0, 15,
+		       "input", kTodo, kOk, kTodo,
+		       "div", kTodo, kOk, kTodo,
+		       "editable", kTodo, kOk, kTodo,
+		       "textarea", kTodo, kOk, kTodo);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="nsIAccessibleText getText related function tests for html:input,html:div and html:textarea"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=452769">Mozilla Bug 452769</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <input id="input" value="hello my friend"/>
+  <div id="div">hello my friend</div>
+  <div id="editable" contenteditable="true">hello my friend</div>
+  <textarea id="textarea">hello my friend</textarea>
+
+</body>
+</html>
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul
@@ -66,19 +66,16 @@
     }
 
     function testAccTree()
     {
       var tabsAccTree = {
         role: ROLE_PAGETABLIST,
         children: [
           {
-            role: ROLE_PUSHBUTTON // tab scroll up button
-          },
-          {
             role: ROLE_PAGETAB,
             children: [
               {
                 role: ROLE_PUSHBUTTON
               }
             ]
           },
           {
@@ -86,19 +83,16 @@
             children: [
               {
                 role: ROLE_PUSHBUTTON
               }
             ]
           },
           {
             role: ROLE_PUSHBUTTON
-          },
-          {
-            role: ROLE_PUSHBUTTON // tab scroll down button
           }
         ]
       };
       testAccessibleTree(getNode("tabbrowser").tabContainer, tabsAccTree);
 
       var tabboxAccTree = {
         role: ROLE_PANE,
         children: [
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -41,17 +41,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/treeupdate
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
+		test_ariadialog.html \
 		test_doc.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_recreation.html \
-		test_tableinsubtree.html \
+		test_textleaf.html \
+		test_visibility.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
rename from accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
rename to accessible/tests/mochitest/treeupdate/test_ariadialog.html
--- a/accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariadialog.html
@@ -29,44 +29,34 @@
       this.node = getNode(aID);
 
       this.eventSeq = [
         new invokerChecker(EVENT_SHOW, this.node)
       ];
 
       this.invoke = function showARIADialog_invoke()
       {
-        this.node.style.display = "block";
+        getNode("dialog").style.display = "block";
+        getNode("table").style.visibility = "visible";
+        getNode("a").textContent = "link";
         getNode("input").value = "hello";
-        getNode("cell").textContent = "cell1";
         getNode("input").focus();
       }
 
       this.finalCheck = function showARIADialog_finalCheck()
       {
         var tree = {
           role: ROLE_DIALOG,
           children: [
             {
-              role: ROLE_TABLE,
-              children: [
-                {
-                  role: ROLE_ROW,
-                  children: [
-                    {
-                      role: ROLE_CELL,
-                      children: [ { role: ROLE_TEXT_LEAF } ]
-                    },
-                    {
-                      role: ROLE_CELL,
-                      children: [ { role: ROLE_ENTRY } ]
-                    }
-                  ]
-                }
-              ]
+              role: ROLE_PUSHBUTTON,
+              children: [ { role: ROLE_TEXT_LEAF } ]
+            },
+            {
+              role: ROLE_ENTRY
             }
           ]
         };
         testAccessibleTree(aID, tree);
       }
 
       this.getID = function showARIADialog_getID()
       {
@@ -105,16 +95,26 @@
   </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="dialog" role="dialog" style="display: none;">
-    <table>
-      <tr><td id="cell"></td><td><input id="input"></td>
+    <table id="table" role="presentation"
+           style="display: block; position: fixed; top: 88px; left: 312.5px; z-index: 10010; visibility: hidden;">
+      <tbody>
+        <tr>
+          <td role="presentation">
+            <div role="presentation">
+              <a id="a" role="button">text</a>
+            </div>
+            <input id="input">
+          </td>
+        </tr>
+      </tbody>
     </table>
   </div>
 
   <div id="eventdump"></div>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_textleaf.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Test accessible recreation</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="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function textLeafUpdate(aID, aIsTextLeafLinkable)
+    {
+      this.node = getNode(aID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.node.parentNode)
+      ];
+
+      this.finalCheck = function textLeafUpdate_finalCheck()
+      {
+        var textLeaf = getAccessible(this.node).firstChild;
+        is(textLeaf.numActions, (aIsTextLeafLinkable ? 1 : 0),
+           "Wrong action numbers!");
+      }
+    }
+
+    function setOnClickAttr(aID)
+    {
+      this.__proto__ = new textLeafUpdate(aID, true);
+
+      this.invoke = function setOnClickAttr_invoke()
+      {
+        this.node.setAttribute("onclick", "alert(3);");
+      }
+
+      this.getID = function setOnClickAttr_getID()
+      {
+        return "make " + prettyName(aID) + " linkable";
+      }
+    }
+
+    function removeOnClickAttr(aID)
+    {
+      this.__proto__ = new textLeafUpdate(aID, false);
+
+      this.invoke = function removeOnClickAttr_invoke()
+      {
+        this.node.removeAttribute("onclick");
+      }
+
+      this.getID = function removeOnClickAttr_getID()
+      {
+        return "unmake " + prettyName(aID) + " linkable";
+      }
+    }
+
+    function setOnClickNRoleAttrs(aID)
+    {
+      this.__proto__ = new textLeafUpdate(aID, true);
+
+      this.invoke = function setOnClickAttr_invoke()
+      {
+        this.node.setAttribute("role", "link");
+        this.node.setAttribute("onclick", "alert(3);");
+      }
+
+      this.getID = function setOnClickAttr_getID()
+      {
+        return "make " + prettyName(aID) + " linkable";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      // adds onclick on element, text leaf should inherit its action
+      gQueue.push(new setOnClickAttr("div"));
+
+      // remove onclick attribute, text leaf shouldn't have any action
+      gQueue.push(new removeOnClickAttr("div"));
+
+      // set onclick attribute making span accessible, it's inserted into tree
+      // and adopts text leaf accessible, text leaf should have an action
+      gQueue.push(new setOnClickNRoleAttrs("span"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Clean up the code of accessible initialization and binding to the tree"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=545465">
+    Mozilla Bug 545465
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="container">
+    <div id="div">div</div>
+    <span id="span">span</span>
+  </div>
+
+  <div id="eventdump"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_visibility.html
@@ -0,0 +1,439 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Style visibility tree update test</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="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    /**
+     * Hide parent while child stays visible.
+     */
+    function test1(aContainerID, aParentID, aChildID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode(aParentID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [
+            { SECTION: [
+              { SECTION: [
+                { TEXT_LEAF: [] }
+              ] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aParentID).style.visibility = "hidden";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [
+            { SECTION: [
+              { TEXT_LEAF: [] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "hide parent while child stays visible";
+      }
+    }
+
+    /**
+     * Hide grand parent while its children stay visible.
+     */
+    function test2(aContainerID, aGrandParentID, aChildID, aChild2ID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode(aGrandParentID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // grand parent
+              { SECTION: [
+                { SECTION: [ // child
+                  { TEXT_LEAF: [] }
+                ] },
+                { SECTION: [ // child2
+                  { TEXT_LEAF: [] }
+                ] }
+              ] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aGrandParentID).style.visibility = "hidden";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // child
+              { TEXT_LEAF: [] }
+            ] },
+            { SECTION: [ // child2
+              { TEXT_LEAF: [] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "hide grand parent while its children stay visible";
+      }
+    }
+
+    /**
+     * Change container style, hide parents while their children stay visible.
+     */
+    function test3(aContainerID, aParentID, aParent2ID, aChildID, aChild2ID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode(aParentID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_HIDE, getNode(aParent2ID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // parent
+              { SECTION: [ // child
+                { TEXT_LEAF: [] }
+              ] }
+            ] },
+            { SECTION: [ // parent2
+              { SECTION: [ // child2
+                { TEXT_LEAF: [] }
+              ] },
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aContainerID).style.color = "red";
+        getNode(aParentID).style.visibility = "hidden";
+        getNode(aParent2ID).style.visibility = "hidden";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // child
+              { TEXT_LEAF: [] }
+            ] },
+            { SECTION: [ // child2
+              { TEXT_LEAF: [] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "change container style, hide parents while their children stay visible";
+      }
+    }
+
+    /**
+     * Change container style and make visible child inside the table.
+     */
+    function test4(aContainerID, aChildID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_REORDER, getNode(aChildID).parentNode)
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [
+            { TABLE: [
+              { ROW: [
+                { CELL: [ ] }
+              ] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aContainerID).style.color = "red";
+        getNode(aChildID).style.visibility = "visible";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [
+            { TABLE: [
+              { ROW: [
+                { CELL: [
+                  { SECTION: [
+                    { TEXT_LEAF: [] }
+                  ] }
+              ] }
+            ] }
+          ] }
+        ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "change container style, make visible child insdie the table";
+      }
+    }
+
+    /**
+     * Hide subcontainer while child inside the table stays visible.
+     */
+    function test5(aContainerID, aSubContainerID, aChildID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode(aSubContainerID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // subcontainer
+              { TABLE: [
+                { ROW: [
+                  { CELL: [
+                    { SECTION: [ // child
+                      { TEXT_LEAF: [] }
+                    ] }
+                  ] }
+                ] }
+              ] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+
+        getNode(aSubContainerID).style.visibility = "hidden";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // child
+              { TEXT_LEAF: [] }
+            ] }
+          ] };
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "hide subcontainer while child inside the table stays visible";
+      }
+    }
+
+    /**
+     * Hide subcontainer while its child and child inside the nested table stays visible.
+     */
+    function test6(aContainerID, aSubContainerID, aChildID, aChild2ID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode(aSubContainerID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChildID)),
+        new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
+        new invokerChecker(EVENT_REORDER, getNode(aContainerID))
+      ];
+
+      this.invoke = function invoke()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // subcontainer
+              { TABLE: [
+                { ROW: [
+                  { CELL: [
+                    { TABLE: [ // nested table
+                      { ROW: [
+                        { CELL: [
+                          { SECTION: [ // child
+                            { TEXT_LEAF: [] } ]} ]} ]} ]} ]} ]} ]},
+              { SECTION: [ // child2
+                { TEXT_LEAF: [] } ]} ]} ]};
+
+        testAccessibleTree(aContainerID, tree);
+
+        // invoke
+        getNode(aSubContainerID).style.visibility = "hidden";
+      }
+
+      this.finalCheck = function finalCheck()
+      {
+        var tree =
+          { SECTION: [ // container
+            { SECTION: [ // child
+              { TEXT_LEAF: [] } ]},
+            { SECTION: [ // child2
+              { TEXT_LEAF: [] } ]} ]};
+
+        testAccessibleTree(aContainerID, tree);
+      }
+
+      this.getID = function getID()
+      {
+        return "hide subcontainer while its child and child inside the nested table stays visible";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new test1("t1_container", "t1_parent", "t1_child"));
+      gQueue.push(new test2("t2_container", "t2_grandparent", "t2_child", "t2_child2"));
+      gQueue.push(new test3("t3_container", "t3_parent", "t3_parent2", "t3_child", "t3_child2"));
+      gQueue.push(new test4("t4_container", "t4_child"));
+      gQueue.push(new test5("t5_container", "t5_subcontainer", "t5_child"));
+      gQueue.push(new test6("t6_container", "t6_subcontainer", "t6_child", "t6_child2"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Develop a way to handle visibility style"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=606125">
+    Mozilla Bug 606125
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <!-- hide parent while child stays visible -->
+  <div id="t1_container">
+    <div id="t1_parent">
+      <div id="t1_child" style="visibility: visible">text</div>
+    </div>
+  </div>
+
+  <!-- hide grandparent while its children stay visible -->
+  <div id="t2_container">
+    <div id="t2_grandparent">
+      <div>
+        <div id="t2_child" style="visibility: visible">text</div>
+        <div id="t2_child2" style="visibility: visible">text</div>
+      </div>
+    </div>
+  </div>
+
+  <!-- change container style, hide parents while their children stay visible -->
+  <div id="t3_container">
+    <div id="t3_parent">
+      <div id="t3_child" style="visibility: visible">text</div>
+    </div>
+    <div id="t3_parent2">
+      <div id="t3_child2" style="visibility: visible">text</div>
+    </div>
+  </div>
+
+  <!-- change container style, show child inside the table -->
+  <div id="t4_container">
+    <table>
+      <tr>
+        <td>
+          <div id="t4_child" style="visibility: hidden;">text</div>
+        </td>
+      </tr>
+    </table>
+  </div>
+
+  <!-- hide subcontainer while child inside the table stays visible -->
+  <div id="t5_container">
+    <div id="t5_subcontainer">
+      <table>
+        <tr>
+          <td>
+            <div id="t5_child" style="visibility: visible;">text</div>
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+
+  <!-- hide subcontainer while its child and child inside the nested table stays visible -->
+  <div id="t6_container">
+    <div id="t6_subcontainer">
+      <table>
+        <tr>
+          <td>
+            <table>
+              <tr>
+                <td>
+                  <div id="t6_child" style="visibility: visible;">text</div>
+                </td>
+              </tr>
+            </table>
+          </td>
+        </tr>
+      </table>
+      <div id="t6_child2" style="visibility: visible">text</div>
+    </div>
+  </div>
+
+  <div id="eventdump"></div>
+</body>
+</html>
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -88,16 +88,17 @@ ifneq (,$(filter OS2 WINCE WINNT,$(OS_AR
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 else
 PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 endif
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
+LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 
 ifdef BUILD_STATIC_LIBS
 ifdef _MSC_VER
 STATIC_COMPONENTS_LINKER_PATH = -LIBPATH:$(DEPTH)/staticlib
 else
 STATIC_COMPONENTS_LINKER_PATH = -L$(DEPTH)/staticlib
 endif
 LIBS += $(DEPTH)/toolkit/xre/$(LIB_PREFIX)xulapp_s.$(LIB_SUFFIX)
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -470,31 +470,16 @@ pref("privacy.cpd.siteSettings",        
 // 4 - Today
 pref("privacy.sanitize.timeSpan", 1);
 pref("privacy.sanitize.sanitizeOnShutdown", false);
 
 pref("privacy.sanitize.migrateFx3Prefs",    false);
 
 pref("network.proxy.share_proxy_settings",  false); // use the same proxy settings for all protocols
 
-// l12n and i18n
-pref("intl.accept_languages", "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.static", "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.more1",  "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.more2",  "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.more3",  "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.more4",  "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.more5",  "chrome://global/locale/intl.properties");
-pref("intl.charsetmenu.browser.unicode",  "UTF-8, UTF-16LE, UTF-16BE, UTF-32, UTF-32LE, UTF-32BE");
-pref("intl.charset.detector", "chrome://global/locale/intl.properties");
-pref("intl.charset.default",  "chrome://global-platform/locale/intl.properties");
-pref("font.language.group", "chrome://global/locale/intl.properties");
-pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
-pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/intl.properties");
-
 // simple gestures support
 pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate");
 pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate");
 pref("browser.gesture.swipe.up", "Browser:HideTabView");
 pref("browser.gesture.swipe.down", "Browser:ShowTabView");
 #ifdef XP_MACOSX
 pref("browser.gesture.pinch.latched", true);
 pref("browser.gesture.pinch.threshold", 150);
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -1,17 +1,15 @@
 <!DOCTYPE window [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
 %brandDTD;
 <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
 %browserDTD;
 <!ENTITY % baseMenuDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd" >
 %baseMenuDTD;
-<!ENTITY % globalRegionDTD SYSTEM "chrome://global-region/locale/region.dtd">
-%globalRegionDTD;
 <!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetOverlay.dtd" >
 %charsetDTD;
 <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
 %textcontextDTD;
 <!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd">
   %customizeToolbarDTD;
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -35,78 +35,95 @@
 #
 # ***** END LICENSE BLOCK *****
 
 let TabView = {
   _deck: null,
   _window: null,
   _sessionstore: null,
   _visibilityID: "tabview-visibility",
-  
+
   // ----------
   get windowTitle() {
     delete this.windowTitle;
     let brandBundle = document.getElementById("bundle_brand");
     let brandShortName = brandBundle.getString("brandShortName");
     let title = gNavigatorBundle.getFormattedString("tabView2.title", [brandShortName]);
     return this.windowTitle = title;
   },
 
   // ----------
-  init: function TabView_init() {    
+  init: function TabView_init() {
     // ___ keys    
     this._setBrowserKeyHandlers();
 
     // ___ visibility
     this._sessionstore =
       Cc["@mozilla.org/browser/sessionstore;1"].
         getService(Ci.nsISessionStore);
 
     let data = this._sessionstore.getWindowValue(window, this._visibilityID);
-    if (data && data == "true")
+    if (data && data == "true") {
       this.show();
+    } else {
+      let self = this;
+      // if a tab is changed from hidden to unhidden and the iframe is not 
+      // initialized, load the iframe and setup the tab.
+      this._tabShowEventListener = function (event) {
+        if (!self._window)
+          self._initFrame(function() {
+            self._window.UI.onTabSelect(gBrowser.selectedTab);
+          });
+      };
+      gBrowser.tabContainer.addEventListener(
+        "TabShow", this._tabShowEventListener, true);
+    }
   },
 
   // ----------
   // Creates the frame and calls the callback once it's loaded. 
   // If the frame already exists, calls the callback immediately. 
   _initFrame: function TabView__initFrame(callback) {
     if (this._window) {
       if (typeof callback == "function")
         callback();
     } else {
       // ___ find the deck
       this._deck = document.getElementById("tab-view-deck");
-      
+
       // ___ create the frame
       let iframe = document.createElement("iframe");
       iframe.id = "tab-view";
       iframe.setAttribute("transparent", "true");
       iframe.flex = 1;
-              
+
       if (typeof callback == "function")
         iframe.addEventListener("DOMContentLoaded", callback, false);
-      
+
       iframe.setAttribute("src", "chrome://browser/content/tabview.html");
       this._deck.appendChild(iframe);
       this._window = iframe.contentWindow;
 
       // ___ visibility storage handler
       let self = this;
       function observer(subject, topic, data) {
         if (topic == "quit-application-requested") {
           let data = (self.isVisible() ? "true" : "false");
           self._sessionstore.setWindowValue(window, self._visibilityID, data);
         }
       }
-      
       Services.obs.addObserver(observer, "quit-application-requested", false);
+
+      if (this._tabShowEventListener) {
+        gBrowser.tabContainer.removeEventListener(
+          "TabShow", this._tabShowEventListener, true);
+      }
     }
   },
-  
+
   // ----------
   getContentWindow: function TabView_getContentWindow() {
     return this._window;
   },
 
   // ----------
   isVisible: function() {
     return (this._deck ? this._deck.selectedIndex == 1 : false);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -162,39 +162,39 @@ toolbar[mode="icons"] > #reload-button[d
 
 html|*.urlbar-input {
   direction: ltr;
 }
 
 /* over-link in location bar */
 
 .urlbar-over-link-layer[overlinkstate="fade-in"],
-.urlbar-textbox-container:not([overlinkstate]) {
+.urlbar-textbox-container[overlinkstate="fade-out"] {
   -moz-transition-property: color;
   -moz-transition-duration: 150ms;
   -moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
 }
 
 .urlbar-textbox-container[overlinkstate="fade-in"],
-.urlbar-over-link-layer:not([overlinkstate]) {
+.urlbar-over-link-layer[overlinkstate="fade-out"] {
   -moz-transition-property: color;
   -moz-transition-duration: 150ms;
   -moz-transition-timing-function: linear;
   color: transparent;
 }
 
 .urlbar-over-link-box[overlinkstate="fade-in"],
-.urlbar-textbox-container-children:not([overlinkstate]) {
+.urlbar-textbox-container-children[overlinkstate="fade-out"] {
   -moz-transition-property: opacity;
   -moz-transition-duration: 150ms;
   opacity: 1;
 }
 
 .urlbar-textbox-container-children[overlinkstate="fade-in"],
-.urlbar-over-link-box:not([overlinkstate]) {
+.urlbar-over-link-box[overlinkstate="fade-out"] {
   -moz-transition-property: opacity;
   -moz-transition-duration: 150ms;
   opacity: 0;
 }
 
 .urlbar-textbox-container[overlinkstate="showing"] {
   color: transparent;
 }
@@ -202,16 +202,24 @@ html|*.urlbar-input {
 .urlbar-over-link-box[overlinkstate="showing"] {
   opacity: 1;
 }
 
 .urlbar-textbox-container-children[overlinkstate="showing"] {
   opacity: 0;
 }
 
+.urlbar-over-link-layer:not([overlinkstate]) {
+  color: transparent;
+}
+
+.urlbar-over-link-box:not([overlinkstate]) {
+  opacity: 0;
+}
+
 /* For results that are actions, their description text is shown instead of
    the URL - this needs to follow the locale's direction, unlike URLs. */
 richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
   direction: rtl;
 }
 
 #urlbar:not([actiontype]) > #urlbar-display {
   display: none;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1373,16 +1373,17 @@ function delayedStartup(isLoadingBlank, 
   Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
   Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
   Services.obs.addObserver(gFormSubmitObserver, "invalidformsubmit", false);
 
   BrowserOffline.init();
   OfflineApps.init();
   IndexedDBPromptHelper.init();
   gFormSubmitObserver.init();
+  AddonManager.addAddonListener(AddonsMgrListener);
 
   gBrowser.addEventListener("pageshow", function(evt) { setTimeout(pageShowEventHandlers, 0, evt); }, true);
 
   // Ensure login manager is up and running.
   Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
 
   if (mustLoadSidebar) {
     let sidebar = document.getElementById("sidebar");
@@ -1636,16 +1637,17 @@ function BrowserShutdown()
   } catch (ex) {
     Components.utils.reportError(ex);
   }
 
   BrowserOffline.uninit();
   OfflineApps.uninit();
   gPrivateBrowsingUI.uninit();
   IndexedDBPromptHelper.uninit();
+  AddonManager.removeAddonListener(AddonsMgrListener);
 
   var enumerator = Services.wm.getEnumerator(null);
   enumerator.getNext();
   if (!enumerator.hasMoreElements()) {
     document.persist("sidebar-box", "sidebarcommand");
     document.persist("sidebar-box", "width");
     document.persist("sidebar-box", "src");
     document.persist("sidebar-title", "value");
@@ -2801,22 +2803,23 @@ function FillInHTMLTooltip(tipElement)
   var SVGTitleText = null;
 #ifdef MOZ_SVG
   var lookingForSVGTitle = true;
 #else
   var lookingForSVGTitle = false;
 #endif // MOZ_SVG
   var direction = tipElement.ownerDocument.dir;
 
-  // If the element is invalid per HTML5 Forms specifications,
-  // show the constraint validation error message instead of @tooltip.
-  if (tipElement instanceof HTMLInputElement ||
-      tipElement instanceof HTMLTextAreaElement ||
-      tipElement instanceof HTMLSelectElement ||
-      tipElement instanceof HTMLButtonElement) {
+  // If the element is invalid per HTML5 Forms specifications and has no title,
+  // show the constraint validation error message.
+  if ((tipElement instanceof HTMLInputElement ||
+       tipElement instanceof HTMLTextAreaElement ||
+       tipElement instanceof HTMLSelectElement ||
+       tipElement instanceof HTMLButtonElement) &&
+      !tipElement.hasAttribute('title')) {
     // If the element is barred from constraint validation or valid,
     // the validation message will be the empty string.
     titleText = tipElement.validationMessage;
   }
 
   while (!titleText && !XLinkTitleText && !SVGTitleText && tipElement) {
     if (tipElement.nodeType == Node.ELEMENT_NODE) {
       titleText = tipElement.getAttribute("title");
@@ -3426,16 +3429,22 @@ function BrowserCustomizeToolbar()
   if (splitter)
     splitter.parentNode.removeChild(splitter);
 
   CombinedStopReload.uninit();
 
   PlacesToolbarHelper.customizeStart();
   BookmarksMenuButton.customizeStart();
 
+  let addonBar = document.getElementById("addon-bar");
+  if (addonBar.collapsed) {
+    addonBar.wasCollapsed = addonBar.collapsed;
+    addonBar.collapsed = false;
+  }
+
   var customizeURL = "chrome://global/content/customizeToolbar.xul";
   gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
 
   if (gCustomizeSheet) {
     var sheetFrame = document.getElementById("customizeToolbarSheetIFrame");
     var panel = document.getElementById("customizeToolbarSheetPopup");
     sheetFrame.hidden = false;
     sheetFrame.toolbox = gNavToolbox;
@@ -3484,16 +3493,22 @@ function BrowserToolboxCustomizeDone(aTo
 #ifndef XP_MACOSX
     updateEditUIVisibility();
 #endif
   }
 
   PlacesToolbarHelper.customizeDone();
   BookmarksMenuButton.customizeDone();
 
+  let addonBar = document.getElementById("addon-bar");
+  if (addonBar.wasCollapsed === true) {
+    addonBar.collapsed = true;
+    delete addonBar.wasCollapsed;
+  }
+
   // The url bar splitter state is dependent on whether stop/reload
   // and the location bar are combined, so we need this ordering
   CombinedStopReload.init();
   UpdateUrlbarSearchSplitterState();
 
   // Update the urlbar
   if (gURLBar) {
     URLBarSetURI();
@@ -3974,24 +3989,26 @@ var XULBrowserWindow = {
   setJSDefaultStatus: function (status) {
     this.jsDefaultStatus = status;
   },
 
   setDefaultStatus: function (status) {
     this.defaultStatus = status;
   },
 
-  setOverLink: function (link) {
-    // Encode bidirectional formatting characters.
-    // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
-    link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
+  setOverLink: function (url, anchorElt) {
+    if (gURLBar) {
+      // Encode bidirectional formatting characters.
+      // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
+      url = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
                         encodeURIComponent);
-    gURLBar.setOverLink(link);
-  },
-  
+      gURLBar.setOverLink(url);
+    }
+  },
+
   // Called before links are navigated to to allow us to retarget them if needed.
   onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
     // Don't modify non-default targets or targets that aren't in top-level app
     // tab docshells (isAppTab will be false for app tab subframes).
     if (originalTarget != "" || !isAppTab)
       return originalTarget;
 
     let docURI = linkNode.ownerDocument.documentURIObject;
@@ -4178,17 +4195,19 @@ var XULBrowserWindow = {
     }
 
     // Disable menu entries for images, enable otherwise
     if (content.document && mimeTypeIsTextBased(content.document.contentType))
       this.isImage.removeAttribute('disabled');
     else
       this.isImage.setAttribute('disabled', 'true');
 
+    this.hideOverLinkImmediately = true;
     this.setOverLink("", null);
+    this.hideOverLinkImmediately = false;
 
     // We should probably not do this if the value has changed since the user
     // searched
     // Update urlbar only if a new page was loaded on the primary content area
     // Do not update urlbar if there was a subframe navigation
 
     var browser = gBrowser.selectedBrowser;
     if (aWebProgress.DOMWindow == content) {
@@ -5162,17 +5181,25 @@ function handleLinkClick(event, href, li
   openLinkIn(href, where, { fromContent: true,
                             referrerURI: doc.documentURIObject,
                             charset: doc.characterSet });
   event.preventDefault();
   return true;
 }
 
 function middleMousePaste(event) {
-  var url = getShortcutOrURI(readFromClipboard());
+  let clipboard = readFromClipboard();
+  if (!clipboard)
+    return;
+
+  // Strip embedded newlines and surrounding whitespace, to match the URL
+  // bar's behavior (stripsurroundingwhitespace)
+  clipboard.replace(/\s*\n\s*/g, "");
+
+  let url = getShortcutOrURI(clipboard);
   try {
     makeURI(url);
   } catch (ex) {
     // Not a valid URI.
     return;
   }
 
   try {
@@ -6589,20 +6616,25 @@ var FeedHandler = {
    * The click handler for the Feed icon in the toolbar. Opens the
    * subscription page if user is not given a choice of feeds.
    * (Otherwise the list of available feeds will be presented to the
    * user in a popup menu.)
    */
   onFeedButtonClick: function(event) {
     event.stopPropagation();
 
-    if (event.target.hasAttribute("feed") &&
-        event.eventPhase == Event.AT_TARGET &&
+    let feeds = gBrowser.selectedBrowser.feeds || [];
+    // If there are multiple feeds, the menu will open, so no need to do
+    // anything. If there are no feeds, nothing to do either.
+    if (feeds.length != 1)
+      return;
+
+    if (event.eventPhase == Event.AT_TARGET &&
         (event.button == 0 || event.button == 1)) {
-        this.subscribeToFeed(null, event);
+      this.subscribeToFeed(feeds[0].href, event);
     }
   },
 
  /** Called when the user clicks on the Subscribe to This Page... menu item.
    * Builds a menu of unique feeds associated with the page, and if there
    * is only one, shows the feed inline in the browser window.
    * @param   menuPopup
    *          The feed list menupopup to be populated.
@@ -6621,22 +6653,18 @@ var FeedHandler = {
       // refuses to work past this point.
       menuPopup.parentNode.removeAttribute("open");
       return false;
     }
 
     while (menuPopup.firstChild)
       menuPopup.removeChild(menuPopup.firstChild);
 
-    if (feeds.length == 1) {
-      var feedButton = document.getElementById("feed-button");
-      if (feedButton)
-        feedButton.setAttribute("feed", feeds[0].href);
+    if (feeds.length <= 1)
       return false;
-    }
 
     // Build the menu showing the available feed choices for viewing.
     for (var i = 0; i < feeds.length; ++i) {
       var feedInfo = feeds[i];
       var menuItem = document.createElement("menuitem");
       var baseTitle = feedInfo.title || feedInfo.href;
       var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
       menuItem.setAttribute("class", "feed-menuitem");
@@ -6699,65 +6727,63 @@ var FeedHandler = {
     return this._feedMenupopup = document.getElementById("multipleFeedsMenuState");
   },
 
   /**
    * Update the browser UI to show whether or not feeds are available when
    * a page is loaded or the user switches tabs to a page that has feeds.
    */
   updateFeeds: function() {
-    var feedButton = document.getElementById("feed-button");
+    clearTimeout(this._updateFeedTimeout);
 
     var feeds = gBrowser.selectedBrowser.feeds;
-    if (!feeds || feeds.length == 0) {
-      if (feedButton) {
-        feedButton.disabled = true;
-        feedButton.removeAttribute("feed");
-      }
+    var haveFeeds = feeds && feeds.length > 0;
+
+    var feedButton = document.getElementById("feed-button");
+    if (feedButton)
+      feedButton.disabled = !haveFeeds;
+
+    if (!haveFeeds) {
       this._feedMenuitem.setAttribute("disabled", "true");
+      this._feedMenuitem.removeAttribute("hidden");
       this._feedMenupopup.setAttribute("hidden", "true");
-      this._feedMenuitem.removeAttribute("hidden");
+      return;
+    }
+
+    if (feeds.length > 1) {
+      this._feedMenuitem.setAttribute("hidden", "true");
+      this._feedMenupopup.removeAttribute("hidden");
     } else {
-      if (feedButton)
-        feedButton.disabled = false;
-
-      if (feeds.length > 1) {
-        this._feedMenuitem.setAttribute("hidden", "true");
-        this._feedMenupopup.removeAttribute("hidden");
-        if (feedButton)
-          feedButton.removeAttribute("feed");
-      } else {
-        if (feedButton)
-          feedButton.setAttribute("feed", feeds[0].href);
-
-        this._feedMenuitem.setAttribute("feed", feeds[0].href);
-        this._feedMenuitem.removeAttribute("disabled");
-        this._feedMenuitem.removeAttribute("hidden");
-        this._feedMenupopup.setAttribute("hidden", "true");
-      }
+      this._feedMenuitem.setAttribute("feed", feeds[0].href);
+      this._feedMenuitem.removeAttribute("disabled");
+      this._feedMenuitem.removeAttribute("hidden");
+      this._feedMenupopup.setAttribute("hidden", "true");
     }
   },
 
   addFeed: function(link, targetDoc) {
     // find which tab this is for, and set the attribute on the browser
     var browserForLink = gBrowser.getBrowserForDocument(targetDoc);
     if (!browserForLink) {
       // ignore feeds loaded in subframes (see bug 305472)
       return;
     }
 
     if (!browserForLink.feeds)
       browserForLink.feeds = [];
 
     browserForLink.feeds.push({ href: link.href, title: link.title });
 
+    // If this addition was for the current browser, update the UI. For
+    // background browsers, we'll update on tab switch.
     if (browserForLink == gBrowser.selectedBrowser) {
-      var feedButton = document.getElementById("feed-button");
-      if (feedButton)
-        feedButton.collapsed = false;
+      // Batch updates to avoid updating the UI for multiple onLinkAdded events
+      // fired within 100ms of each other.
+      clearTimeout(this._updateFeedTimeout);
+      this._updateFeedTimeout = setTimeout(this.updateFeeds.bind(this), 100);
     }
   }
 };
 
 /**
  * Re-open a closed tab.
  * @param aIndex
  *        The index of the tab (via nsSessionStore.getClosedTabData)
@@ -8025,8 +8051,38 @@ function duplicateTabIn(aTab, where, his
       loadInBackground = !loadInBackground;
       // fall through
     case "tab":
       if (!loadInBackground)
         gBrowser.selectedTab = newTab;
       break;
   }
 }
+
+/*
+ * When addons are installed/uninstalled, check and see if the number of items
+ * on the add-on bar changed:
+ * - If an add-on was installed, incrementing the count, show the bar.
+ * - If an add-on was uninstalled, and no more items are left, hide the bar.
+ */
+let AddonsMgrListener = {
+  get addonBar() document.getElementById("addon-bar"),
+  get statusBar() document.getElementById("status-bar"),
+  getAddonBarItemCount: function() {
+    // Take into account the contents of the status bar shim for the count.
+    return this.addonBar.childNodes.length - 1 +
+           this.statusBar.childNodes.length;
+  },
+  onInstalling: function(aAddon) {
+    this.lastAddonBarCount = this.getAddonBarItemCount();
+  },
+  onInstalled: function(aAddon) {
+    if (this.getAddonBarItemCount() > this.lastAddonBarCount)
+      setToolbarVisibility(this.addonBar, true);
+  },
+  onUninstalling: function(aAddon) {
+    this.lastAddonBarCount = this.getAddonBarItemCount();
+  },
+  onUninstalled: function(aAddon) {
+    if (this.lastAddonBarCount > 0 && this.getAddonBarItemCount() == 0)
+      setToolbarVisibility(this.addonBar, false);
+  }
+};
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -31,16 +31,17 @@
 #   Dean Tessman <dean_tessman@hotmail.com>
 #   Johnathan Nightingale <johnath@mozilla.com>
 #   Dão Gottwald <dao@mozilla.com>
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
 #   Robert Strong <robert.bugzilla@gmail.com>
 #   Rob Campbell <rcampbell@mozilla.com>
 #   Patrick Walton <pcwalton@mozilla.com>
 #   David Dahl <ddahl@mozilla.com>
+#   Frank Yan <fyan@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -48,16 +49,17 @@
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
+<?xml-stylesheet href="chrome://global/skin/webConsole.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
 
 # All DTD information is stored in a separate file so that it can be shared by
 # hiddenWindow.xul.
@@ -108,19 +110,16 @@
 #include browser-sets.inc
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
-                tbattr="tabbrowser-multiple"
-                oncommand="gBrowser.reloadAllTabs();"/>
       <menuseparator/>
       <menuitem id="context_pinTab" label="&pinAppTab.label;"
                 accesskey="&pinAppTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_unpinTab" label="&unpinAppTab.label;" hidden="true"
                 accesskey="&unpinAppTab.accesskey;"
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
       <menu id="context_tabViewMenu" label="&moveToGroup.label;"
@@ -132,23 +131,26 @@
                     oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
         </menupopup>
       </menu>
       <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
                 accesskey="&moveToNewWindow.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
       <menuseparator/>
+      <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
+                tbattr="tabbrowser-multiple"
+                oncommand="gBrowser.reloadAllTabs();"/>
       <menuitem id="context_bookmarkAllTabs"
                 label="&bookmarkAllTabs.label;"
                 accesskey="&bookmarkAllTabs.accesskey;"
                 command="Browser:BookmarkAllTabs"/>
-      <menuseparator/>
       <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
                 oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
+      <menuseparator/>
       <menuitem id="context_undoCloseTab"
                 label="&undoCloseTab.label;"
                 accesskey="&undoCloseTab.accesskey;"
                 observes="History:UndoCloseTab"/>
       <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
                 oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/>
     </menupopup>
 
@@ -326,17 +328,18 @@
                                  updateEditUIVisibility();
                                return gContextMenu.shouldDisplay;"
                onpopuphiding="if (event.target == this) { gContextMenu = null; updateEditUIVisibility(); }">
 #include browser-context.inc
     </menupopup>
 
     <menupopup id="placesContext"/>
 
-    <panel id="notification-popup" type="arrow" position="after_start" noautofocus="true" hidden="true"/>
+    <panel id="notification-popup" type="arrow" position="after_start"
+           noautofocus="true" hidden="true" orient="vertical"/>
 
     <!-- Popup for site identity information -->
     <panel id="identity-popup" position="after_start" hidden="true" noautofocus="true"
            onpopupshown="document.getElementById('identity-popup-more-info-button').focus();"
            level="top">
       <hbox id="identity-popup-container" align="top">
         <image id="identity-popup-icon"/>
         <vbox id="identity-popup-content-box">
@@ -427,26 +430,26 @@
     </panel>
 
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
   </popupset>
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 <vbox id="titlebar">
   <hbox id="titlebar-content">
-    <hbox id="appmenu-button-container" align="start">
+    <hbox id="appmenu-button-container">
       <button id="appmenu-button"
               type="menu"
               label="&brandShortName;"
               style="-moz-user-focus: ignore;">
 #include browser-appmenu.inc
       </button>
     </hbox>
     <spacer id="titlebar-spacer" flex="1"/>
-    <hbox id="titlebar-buttonbox">
+    <hbox id="titlebar-buttonbox" align="start">
       <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
       <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
       <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
     </hbox>
   </hbox>
 </vbox>
 #endif
 
--- a/browser/base/content/syncSetup.js
+++ b/browser/base/content/syncSetup.js
@@ -757,65 +757,78 @@ var gSyncSetup = {
   _handleChoice: function () {
     let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
     document.getElementById("chosenActionDeck").selectedIndex = desc;
     switch (desc) {
       case 1:
         if (this._case1Setup)
           break;
 
-        // history
-        let db = Weave.Svc.History.DBConnection;
+        let places_db = Weave.Svc.History.DBConnection;
+        if (Weave.Engines.get("history").enabled) {
+          let daysOfHistory = 0;
+          let stm = places_db.createStatement(
+            "SELECT ROUND(( " +
+              "strftime('%s','now','localtime','utc') - " +
+              "( " +
+                "SELECT visit_date FROM moz_historyvisits " +
+                "UNION ALL " +
+                "SELECT visit_date FROM moz_historyvisits_temp " +
+                "ORDER BY visit_date ASC LIMIT 1 " +
+                ")/1000000 " +
+              ")/86400) AS daysOfHistory ");
 
-        let daysOfHistory = 0;
-        let stm = db.createStatement(
-          "SELECT ROUND(( " +
-            "strftime('%s','now','localtime','utc') - " +
-            "( " +
-              "SELECT visit_date FROM moz_historyvisits " +
-              "UNION ALL " +
-              "SELECT visit_date FROM moz_historyvisits_temp " +
-              "ORDER BY visit_date ASC LIMIT 1 " +
-              ")/1000000 " +
-            ")/86400) AS daysOfHistory ");
-
-        if (stm.step())
-          daysOfHistory = stm.getInt32(0);
-        // Support %S for historical reasons (see bug 600141)
-        document.getElementById("historyCount").value =
-          PluralForm.get(daysOfHistory,
-                         this._stringBundle.GetStringFromName("historyDaysCount.label"))
-                    .replace("%S", daysOfHistory)
-                    .replace("#1", daysOfHistory);
+          if (stm.step())
+            daysOfHistory = stm.getInt32(0);
+          // Support %S for historical reasons (see bug 600141)
+          document.getElementById("historyCount").value =
+            PluralForm.get(daysOfHistory,
+                           this._stringBundle.GetStringFromName("historyDaysCount.label"))
+                      .replace("%S", daysOfHistory)
+                      .replace("#1", daysOfHistory);
+        } else {
+          document.getElementById("historyCount").hidden = true;
+        }
 
-        // bookmarks
-        let bookmarks = 0;
-        stm = db.createStatement(
-          "SELECT count(*) AS bookmarks " +
-          "FROM moz_bookmarks b " +
-          "LEFT JOIN moz_bookmarks t ON " +
-          "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
-        stm.params.tag = Weave.Svc.Bookmark.tagsFolder;
-        if (stm.executeStep())
-          bookmarks = stm.row.bookmarks;
-        // Support %S for historical reasons (see bug 600141)
-        document.getElementById("bookmarkCount").value =
-          PluralForm.get(bookmarks,
-                         this._stringBundle.GetStringFromName("bookmarksCount.label"))
-                    .replace("%S", bookmarks)
-                    .replace("#1", bookmarks);
+        if (Weave.Engines.get("bookmarks").enabled) {
+          let bookmarks = 0;
+          let stm = places_db.createStatement(
+            "SELECT count(*) AS bookmarks " +
+            "FROM moz_bookmarks b " +
+            "LEFT JOIN moz_bookmarks t ON " +
+            "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
+          stm.params.tag = Weave.Svc.Bookmark.tagsFolder;
+          if (stm.executeStep())
+            bookmarks = stm.row.bookmarks;
+          // Support %S for historical reasons (see bug 600141)
+          document.getElementById("bookmarkCount").value =
+            PluralForm.get(bookmarks,
+                           this._stringBundle.GetStringFromName("bookmarksCount.label"))
+                      .replace("%S", bookmarks)
+                      .replace("#1", bookmarks);
+        } else {
+          document.getElementById("bookmarkCount").hidden = true;
+        }
 
-        // passwords
-        let logins = Weave.Svc.Login.getAllLogins({});
-        // Support %S for historical reasons (see bug 600141)
-        document.getElementById("passwordCount").value =
-          PluralForm.get(logins.length,
-                         this._stringBundle.GetStringFromName("passwordsCount.label"))
-                    .replace("%S", logins.length)
-                    .replace("#1", logins.length);
+        if (Weave.Engines.get("passwords").enabled) {
+          let logins = Weave.Svc.Login.getAllLogins({});
+          // Support %S for historical reasons (see bug 600141)
+          document.getElementById("passwordCount").value =
+            PluralForm.get(logins.length,
+                           this._stringBundle.GetStringFromName("passwordsCount.label"))
+                      .replace("%S", logins.length)
+                      .replace("#1", logins.length);
+        } else {
+          document.getElementById("passwordCount").hidden = true;
+        }
+
+        if (!Weave.Engines.get("prefs").enabled) {
+          document.getElementById("prefsWipe").hidden = true;
+        }
+
         this._case1Setup = true;
         break;
       case 2:
         if (this._case2Setup)
           break;
         let count = 0;
         function appendNode(label) {
           let box = document.getElementById("clientList");
--- a/browser/base/content/syncSetup.xul
+++ b/browser/base/content/syncSetup.xul
@@ -475,44 +475,38 @@
       <deck id="chosenActionDeck">
         <vbox id="chosenActionMerge" class="confirm">
           <description class="normal">
             &confirm.merge.label;
           </description>
         </vbox>
         <vbox id="chosenActionWipeClient" class="confirm">
           <description class="normal">
-            &confirm.client.label;
+            &confirm.client2.label;
           </description>
           <separator class="thin"/>
           <vbox id="dataList">
             <label class="data indent" id="bookmarkCount"/>
             <label class="data indent" id="historyCount"/>
             <label class="data indent" id="passwordCount"/>
+            <label class="data indent" id="prefsWipe"
+                   value="&engine.prefs.label;"/>
           </vbox>
           <separator class="thin"/>
           <description class="normal">
             &confirm.client.moreinfo.label;
           </description>
-          <separator class="thin"/>
-          <description class="warning">
-            &confirm.client.warning.label;
-          </description>
         </vbox>
         <vbox id="chosenActionWipeServer" class="confirm">
           <description class="normal">
-            &confirm.server.label;
+            &confirm.server2.label;
           </description>
           <separator class="thin"/>
           <vbox id="clientList">
           </vbox>
-          <separator class="thin"/>
-          <description class="warning">
-            &confirm.server.warning.label;
-          </description>
         </vbox>
       </deck>
   </wizardpage>
 
   <wizardpage label="&setup.successPage.title;" 
               id="successfulSetup"
               onextra1="gSyncSetup.onSyncOptions()"
               onpageshow="gSyncSetup.onPageShow()">
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2740,16 +2740,18 @@
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           switch (aEvent.type) {
             case "resize":
+              if (aEvent.target != window)
+                break;
               var width = this.mTabstrip.boxObject.width;
               if (width != this.mTabstripWidth) {
                 this.adjustTabstrip();
                 this._fillTrailingGap();
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
               break;
--- a/browser/base/content/tabview/drag.js
+++ b/browser/base/content/tabview/drag.js
@@ -96,25 +96,26 @@ function Drag(item, event, isResizing, i
 
 Drag.prototype = {
   // ----------
   // Function: snapBounds
   // Adjusts the given bounds according to the currently active trenches. Used by <Drag.snap>
   //
   // Parameters:
   //   bounds             - (<Rect>) bounds
-  //   stationaryCorner   - which corner is stationary? by default, the top left.
+  //   stationaryCorner   - which corner is stationary? by default, the top left in LTR mode,
+  //                        and top right in RTL mode.
   //                        "topleft", "bottomleft", "topright", "bottomright"
   //   assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
   //   keepProportional   - (boolean) if assumeConstantSize is false, whether we should resize
   //                        proportionally or not
   //   checkItemStatus    - (boolean) make sure this is a valid item which should be snapped
   snapBounds: function Drag_snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, checkItemStatus) {
     if (!stationaryCorner)
-      stationaryCorner = 'topleft';
+      stationaryCorner = UI.rtl ? 'topright' : 'topleft';
     var update = false; // need to update
     var updateX = false;
     var updateY = false;
     var newRect;
     var snappedTrenches = {};
 
     // OH SNAP!
 
@@ -159,17 +160,18 @@ Drag.prototype = {
 
   // ----------
   // Function: snap
   // Called when a drag or mousemove occurs. Set the bounds based on the mouse move first, then
   // call snap and it will adjust the item's bounds if appropriate. Also triggers the display of
   // trenches that it snapped to.
   //
   // Parameters:
-  //   stationaryCorner   - which corner is stationary? by default, the top left.
+  //   stationaryCorner   - which corner is stationary? by default, the top left in LTR mode,
+  //                        and top right in RTL mode.
   //                        "topleft", "bottomleft", "topright", "bottomright"
   //   assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
   //   keepProportional   - (boolean) if assumeConstantSize is false, whether we should resize
   //                        proportionally or not
   snap: function Drag_snap(stationaryCorner, assumeConstantSize, keepProportional) {
     var bounds = this.item.getBounds();
     bounds = this.snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, true);
     if (bounds) {
@@ -182,32 +184,33 @@ Drag.prototype = {
   // --------
   // Function: snapToEdge
   // Returns a version of the bounds snapped to the edge if it is close enough. If not,
   // returns false. If <Keys.meta> is true, this function will simply enforce the
   // window edges.
   //
   // Parameters:
   //   rect - (<Rect>) current bounds of the object
-  //   stationaryCorner   - which corner is stationary? by default, the top left.
+  //   stationaryCorner   - which corner is stationary? by default, the top left in LTR mode,
+  //                        and top right in RTL mode.
   //                        "topleft", "bottomleft", "topright", "bottomright"
   //   assumeConstantSize - (boolean) whether the rect's dimensions are sacred or not
   //   keepProportional   - (boolean) if we are allowed to change the rect's size, whether the
   //                                  dimensions should scaled proportionally or not.
   snapToEdge: function Drag_snapToEdge(rect, stationaryCorner, assumeConstantSize, keepProportional) {
 
     var swb = this.safeWindowBounds;
     var update = false;
     var updateX = false;
     var updateY = false;
     var snappedTrenches = {};
 
     var snapRadius = (Keys.meta ? 0 : Trenches.defaultRadius);
     if (rect.left < swb.left + snapRadius ) {
-      if (stationaryCorner.indexOf('right') > -1)
+      if (stationaryCorner.indexOf('right') > -1 && !assumeConstantSize)
         rect.width = rect.right - swb.left;
       rect.left = swb.left;
       update = true;
       updateX = true;
       snappedTrenches.left = 'edge';
     }
 
     if (rect.right > swb.right - snapRadius) {
@@ -220,17 +223,17 @@ Drag.prototype = {
       } else if (!updateX || !Trenches.preferLeft) {
         rect.left = swb.right - rect.width;
         update = true;
       }
       snappedTrenches.right = 'edge';
       delete snappedTrenches.left;
     }
     if (rect.top < swb.top + snapRadius) {
-      if (stationaryCorner.indexOf('bottom') > -1)
+      if (stationaryCorner.indexOf('bottom') > -1 && !assumeConstantSize)
         rect.height = rect.bottom - swb.top;
       rect.top = swb.top;
       update = true;
       updateY = true;
       snappedTrenches.top = 'edge';
     }
     if (rect.bottom > swb.bottom - snapRadius) {
       if (updateY || !assumeConstantSize) {
@@ -253,17 +256,17 @@ Drag.prototype = {
     }
     return false;
   },
 
   // ----------
   // Function: drag
   // Called in response to an <Item> draggable "drag" event.
   drag: function Drag_drag(event) {
-    this.snap('topleft', true);
+    this.snap(UI.rtl ? 'topright' : 'topleft', true);
 
     if (this.parent && this.parent.expanded) {
       var distance = this.startPosition.distance(new Point(event.clientX, event.clientY));
       if (distance > 100) {
         this.parent.remove(this.item);
         this.parent.collapse();
       }
     }
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -170,26 +170,27 @@ function GroupItem(listOfEls, options) {
   this.$titleShield = iQ('.title-shield', this.$titlebar);
   this.setTitle(options.title || this.defaultName);
 
   var titleUnfocus = function(immediately) {
     self.$titleShield.show();
     if (!self.getTitle()) {
       self.$title
         .addClass("defaultName")
-        .val(self.defaultName);
+        .val(self.defaultName)
+        .css({"background-image":null, "-moz-padding-start":null});
     } else {
-      self.$title.css({"background":"none"});
+      self.$title.css({"background-image":"none"});
       if (immediately) {
         self.$title.css({
-            "padding-left": "1px"
+            "-moz-padding-start": "1px"
           });
       } else {
         self.$title.animate({
-            "padding-left": "1px"
+            "-moz-padding-start": "1px"
           }, {
             duration: 200,
             easing: "tabviewBounce"
           });
       }
     }
   };
 
@@ -403,17 +404,18 @@ GroupItem.prototype = Utils.extend(new I
   },
 
   // ----------
   // Function: adjustTitleSize
   // Used to adjust the width of the title box depending on groupItem width and title size.
   adjustTitleSize: function GroupItem_adjustTitleSize() {
     Utils.assert(this.bounds, 'bounds needs to have been set');
     let closeButton = iQ('.close', this.container);
-    var w = Math.min(this.bounds.width - parseInt(closeButton.width()) - parseInt(closeButton.css('right')),
+    var dimension = UI.rtl ? 'left' : 'right';
+    var w = Math.min(this.bounds.width - parseInt(closeButton.width()) - parseInt(closeButton.css(dimension)),
                      Math.max(150, this.getTitle().length * 6));
     // The * 6 multiplier calculation is assuming that characters in the title
     // are approximately 6 pixels wide. Bug 586545
     var css = {width: w};
     this.$title.css(css);
     this.$titleShield.css(css);
   },
 
@@ -1081,23 +1083,26 @@ GroupItem.prototype = Utils.extend(new I
         // yDensity = (the distance of the bottom of the last tab to the top of the content area)
         // / (the total available content height)
         this.yDensity = (rects[rects.length - 1].bottom - bb.top) / (bb.height);
 
         // xDensity = (the distance from the left of the content area to the right of the rightmost
         // tab) / (the total available content width)
 
         // first, find the right of the rightmost tab! luckily, they're in order.
-        // TODO: does this change for rtl?
         var rightMostRight = 0;
-        for each (var rect in rects) {
-          if (rect.right > rightMostRight)
-            rightMostRight = rect.right;
-          else
-            break;
+        if (UI.rtl) {
+          rightMostRight = rects[0].right;
+        } else {
+          for each (var rect in rects) {
+            if (rect.right > rightMostRight)
+              rightMostRight = rect.right;
+            else
+              break;
+          }
         }
         this.xDensity = (rightMostRight - bb.left) / (bb.width);
 
         this._isStacked = false;
       } else
         this._stackArrange(bb, options);
     }
 
@@ -1172,17 +1177,17 @@ GroupItem.prototype = Utils.extend(new I
 
     children.forEach(function(child, index) {
       if (!child.locked.bounds) {
         child.setZ(zIndex);
         zIndex--;
 
         child.addClass("stacked");
         child.setBounds(box, !animate);
-        child.setRotation(self._randRotate(maxRotation, index));
+        child.setRotation((UI.rtl ? -1 : 1) * self._randRotate(maxRotation, index));
       }
     });
 
     self._isStacked = true;
   },
 
   // ----------
   // Function: _randRotate
@@ -1366,18 +1371,18 @@ 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) {
-    this.resizeOptions.minWidth = 90;
-    this.resizeOptions.minHeight = 90;
+    this.resizeOptions.minWidth = 110;
+    this.resizeOptions.minHeight = 125;
 
     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
@@ -222,18 +222,17 @@ Item.prototype = {
       minWidth: 90,
       minHeight: 90,
       start: function(e,ui) {
         if (this.isAGroupItem)
           GroupItems.setActiveGroupItem(this);
         resizeInfo = new Drag(this, e, true); // true = isResizing
       },
       resize: function(e,ui) {
-        // TODO: maybe the stationaryCorner should be topright for rtl langs?
-        resizeInfo.snap('topleft', false, self.keepProportional);
+        resizeInfo.snap(UI.rtl ? 'topright' : 'topleft', false, self.keepProportional);
       },
       stop: function() {
         self.setUserSize();
         self.pushAway();
         resizeInfo.stop();
         resizeInfo = null;
       }
     };
@@ -764,17 +763,26 @@ Item.prototype = {
         var self = this;
         var startMouse;
         var startSize;
 
         // ___ mousemove
         var handleMouseMove = function(e) {
           var mouse = new Point(e.pageX, e.pageY);
           var box = self.getBounds();
-          box.width = Math.max(self.resizeOptions.minWidth || 0, startSize.x + (mouse.x - startMouse.x));
+          if (UI.rtl) {
+            var minWidth = (self.resizeOptions.minWidth || 0);
+            var oldWidth = box.width;
+            if (minWidth != oldWidth || mouse.x < startMouse.x) {
+              box.width = Math.max(minWidth, startSize.x - (mouse.x - startMouse.x));
+              box.left -= box.width - oldWidth;
+            }
+          } else {
+            box.width = Math.max(self.resizeOptions.minWidth || 0, startSize.x + (mouse.x - startMouse.x));
+          }
           box.height = Math.max(self.resizeOptions.minHeight || 0, startSize.y + (mouse.y - startMouse.y));
 
           if (self.resizeOptions.aspectRatio) {
             if (startAspect < 1)
               box.height = box.width * startAspect;
             else
               box.width = box.height / startAspect;
           }
@@ -955,35 +963,40 @@ let Items = {
     if (rows == 1) {
       tabWidth = Math.min(tabWidth, (bounds.height - 2 * itemMargin) / tabAspect);
       tabHeight = tabWidth * tabAspect;
     }
     
     if (options.return == 'widthAndColumns')
       return {childWidth: tabWidth, columns: columns};
 
-    var box = new Rect(bounds.left, bounds.top, tabWidth, tabHeight);
+    let initialOffset = 0;
+    if (UI.rtl) {
+      initialOffset = bounds.width - tabWidth - padding;
+    }
+    var box = new Rect(bounds.left + initialOffset, bounds.top, tabWidth, tabHeight);
+
     var column = 0;
 
     for (let a = 0; a < count; a++) {
       rects.push(new Rect(box));
       if (items && a < items.length) {
         let item = items[a];
         if (!item.locked.bounds) {
           item.setBounds(box, immediately);
           item.setRotation(0);
           if (options.z)
             item.setZ(options.z);
         }
       }
 
-      box.left += box.width + padding;
+      box.left += (UI.rtl ? -1 : 1) * (box.width + padding);
       column++;
       if (column == columns) {
-        box.left = bounds.left;
+        box.left = bounds.left + initialOffset;
         box.top += (box.height * yScale) + padding;
         column = 0;
       }
     }
 
     return rects;
   },
 
--- a/browser/base/content/tabview/modules/AllTabs.jsm
+++ b/browser/base/content/tabview/modules/AllTabs.jsm
@@ -54,17 +54,17 @@ let AllTabs = {
     }));
   },
 
   /**
    * Attach a callback for a given tab event.
    *
    * @param eventName
    *        Name of the corresponding Tab* Event; one of "attrModified",
-   *        "close", "move", "open", "select".
+   *        "close", "move", "open", "select", "pinned", "unpinned".
    * @param callback
    *        Callback that gets called with the tab as the first argument and
    *        the event as the second argument.
    * @usage AllTabs.register("change", function handleChange(tab, event) {});
    */
   register: function register(eventName, callback) {
     // Either add additional callbacks or create the first entry
     let listeners = eventListeners[eventName];
@@ -74,17 +74,17 @@ let AllTabs = {
       eventListeners[eventName] = [callback];
   },
 
   /**
    * Remove a callback for a given tab event.
    *
    * @param eventName
    *        Name of the corresponding Tab* Event; one of "attrModified",
-   *        "close", "move", "open", "select".
+   *        "close", "move", "open", "select", "pinned", "unpinned".
    * @param callback
    *        The callback given for the original AllTabs.register call.
    * @usage AllTabs.unregister("close", handleClose);
    */
   unregister: function unregister(eventName, callback) {
     // Nothing to remove for this event
     let listeners = eventListeners[eventName];
     if (!listeners)
@@ -102,17 +102,17 @@ let AllTabs = {
 __defineGetter__("browserWindows", function browserWindows() {
   let browserWindows = [];
   let windows = Services.wm.getEnumerator("navigator:browser");
   while (windows.hasMoreElements())
     browserWindows.push(windows.getNext());
   return browserWindows;
 });
 
-let events = ["attrModified", "close", "move", "open", "select"];
+let events = ["attrModified", "close", "move", "open", "select", "pinned", "unpinned"];
 let eventListeners = {};
 
 function registerBrowserWindow(browserWindow) {
   events.forEach(function(eventName) {
     let tabEvent = "Tab" + eventName[0].toUpperCase() + eventName.slice(1);
     browserWindow.addEventListener(tabEvent, function(event) {
       // Make sure we've gotten listeners before trying to call
       let listeners = eventListeners[eventName];
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -377,35 +377,43 @@ TabItem.prototype = Utils.extend(new Ite
       }
 
       if (css.width) {
         TabItems.update(this.tab);
 
         let widthRange, proportion;
 
         if (this.inStack()) {
-          $fav.css({top:0, left:0});
+          if (UI.rtl) {
+            $fav.css({top:0, right:0});
+          } else {
+            $fav.css({top:0, left:0});
+          }
           widthRange = new Range(70, 90);
           proportion = widthRange.proportion(css.width); // between 0 and 1
         } else {
-          $fav.css({top:4,left:4});
+          if (UI.rtl) {
+            $fav.css({top:4, right:2});
+          } else {
+            $fav.css({top:4, left:4});
+          }
           widthRange = new Range(40, 45);
           proportion = widthRange.proportion(css.width); // between 0 and 1
         }
 
         if (proportion <= .1)
           $close.hide();
         else
           $close.show().css({opacity:proportion});
 
         var pad = 1 + 5 * proportion;
         var alphaRange = new Range(0.1,0.2);
         $fav.css({
-         "padding-left": pad + "px",
-         "padding-right": pad + 2 + "px",
+         "-moz-padding-start": pad + "px",
+         "-moz-padding-end": pad + 2 + "px",
          "padding-top": pad + "px",
          "padding-bottom": pad + "px",
          "border-color": "rgba(0,0,0,"+ alphaRange.scale(proportion) +")",
         });
       }
 
       this._hasBeenDrawn = true;
     }
--- a/browser/base/content/tabview/tabview.css
+++ b/browser/base/content/tabview/tabview.css
@@ -202,36 +202,56 @@ body {
 
 #search{
   position: absolute;
   top: 0px;
   left: 0px;
   z-index: 1000;  
 }
 
+html[dir=rtl] #search {
+  left: auto;
+  right: 0;
+}
+
 #searchbox{
   position: absolute;
   right: 20px;
   top: 20px;
   z-index: 1050;
 }
 
+html[dir=rtl] #searchbox {
+  right: auto;
+  left: 20px;
+}
+
 #actions{
   position: absolute;
   top: 100px;
   right: 0px;
   z-index:10;
 }
 
+html[dir=rtl] #actions {
+  right: auto;
+  left: 0;
+}
+
 #actions #searchbutton{
   position: relative;
   top: 0;
   left: 0;
 }
 
+html[dir=rtl] #actions #searchbutton {
+  left: auto;
+  right: 0;
+}
+
 #otherresults{
   position: absolute;
   opacity: 0;
   overflow: hidden;
 }
 
 .onTop{
   z-index: 1010 !important;
--- a/browser/base/content/tabview/trench.js
+++ b/browser/base/content/tabview/trench.js
@@ -472,17 +472,17 @@ var Trenches = {
   defaultRadius: 10,
   disabled: false,
 
   // ---------
   // Variables: snapping preferences; used to break ties in snapping.
   //   preferTop - (boolean) prefer snapping to the top to the bottom
   //   preferLeft - (boolean) prefer snapping to the left to the right
   preferTop: true,
-  preferLeft: true,
+  get preferLeft() { return !UI.rtl; },
 
   trenches: [],
 
   // ---------
   // Function: getById
   // Return the specified <Trench>.
   //
   // Parameters:
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -101,16 +101,19 @@ let UI = {
 
   // ----------
   // Function: init
   // Must be called after the object is created.
   init: function UI_init() {
     try {
       let self = this;
 
+      // initialize the direction of the page
+      this._initPageDirection();
+
       // ___ storage
       Storage.init();
       let data = Storage.readUIData(gWindow);
       this._storageSanity(data);
       this._pageBounds = data.pageBounds;
 
       // ___ hook into the browser
       gWindow.addEventListener("tabviewshow", function() {
@@ -239,35 +242,45 @@ let UI = {
 
     this._removeTabActionHandlers();
     this._currentTab = null;
     this._pageBounds = null;
     this._reorderTabItemsOnShow = null;
     this._reorderTabsOnHide = null;
     this._frameInitialized = false;
   },
-  
+
+  // Property: rtl
+  // Returns true if we are in RTL mode, false otherwise
+  rtl: false,
+
   // Function: reset
   // Resets the Panorama view to have just one group with all tabs
   // and, if firstTime == true, add the welcome video/tab
   reset: function UI_reset(firstTime) {
     let padding = Trenches.defaultRadius;
     let welcomeWidth = 300;
     let pageBounds = Items.getPageBounds();
     pageBounds.inset(padding, padding);
 
     let $actions = iQ("#actions");
-    if ($actions)
+    if ($actions) {
       pageBounds.width -= $actions.width();
+      if (UI.rtl)
+        pageBounds.left += $actions.width() - padding;
+    }
 
     // ___ make a fresh groupItem
     let box = new Rect(pageBounds);
     box.width = Math.min(box.width * 0.667,
                          pageBounds.width - (welcomeWidth + padding));
     box.height = box.height * 0.667;
+    if (UI.rtl) {
+      box.left = pageBounds.left + welcomeWidth + 2 * padding;
+    }
 
     GroupItems.groupItems.forEach(function(group) {
       group.close();
     });
     
     let options = {
       bounds: box,
       immediately: true
@@ -286,17 +299,17 @@ let UI = {
       let url = gPrefBranch.getCharPref("welcome_url");
       let newTab = gBrowser.loadOneTab(url, {inBackground: true});
       let newTabItem = newTab.tabItem;
       let parent = newTabItem.parent;
       Utils.assert(parent, "should have a parent");
 
       newTabItem.parent.remove(newTabItem);
       let aspect = TabItems.tabHeight / TabItems.tabWidth;
-      let welcomeBounds = new Rect(box.right + padding, box.top,
+      let welcomeBounds = new Rect(UI.rtl ? pageBounds.left : box.right, box.top,
                                    welcomeWidth, welcomeWidth * aspect);
       newTabItem.setBounds(welcomeBounds, true);
       GroupItems.setActiveGroupItem(groupItem);
     }
   },
 
   // Function: blurAll
   // Blurs any currently focused element
@@ -346,25 +359,39 @@ let UI = {
 
   // ----------
   // Function: _isTabViewVisible
   // Returns true if the TabView UI is currently shown.
   _isTabViewVisible: function UI__isTabViewVisible() {
     return gTabViewDeck.selectedIndex == 1;
   },
 
+  // ---------
+  // Function: _initPageDirection
+  // Initializes the page base direction
+  _initPageDirection: function UI__initPageDirection() {
+    let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
+                    getService(Ci.nsIXULChromeRegistry);
+    let dir = chromeReg.isLocaleRTL("global");
+    document.documentElement.setAttribute("dir", dir ? "rtl" : "ltr");
+    this.rtl = dir;
+  },
+
   // ----------
   // Function: showTabView
   // Shows TabView and hides the main browser UI.
   // Parameters:
   //   zoomOut - true for zoom out animation, false for nothing.
   showTabView: function UI_showTabView(zoomOut) {
     if (this._isTabViewVisible())
       return;
 
+    // initialize the direction of the page
+    this._initPageDirection();
+
     var self = this;
     var currentTab = this._currentTab;
     var item = null;
 
     this._reorderTabItemsOnShow.forEach(function(groupItem) {
       groupItem.reorderTabItemsBasedOnTabOrder();
     });
     this._reorderTabItemsOnShow = [];
@@ -614,41 +641,37 @@ let UI = {
     // TabSelect
     this._eventListeners.select = function(tab) {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
       self.onTabSelect(tab);
     };
 
+    // TabPinned
+    this._eventListeners.pinned = function(tab) {
+      if (tab.ownerDocument.defaultView != gWindow)
+        return;
+
+      TabItems.handleTabPin(tab);
+      GroupItems.addAppTab(tab);
+    };
+
+    // TabUnpinned
+    this._eventListeners.unpinned = function(tab) {
+      if (tab.ownerDocument.defaultView != gWindow)
+        return;
+
+      TabItems.handleTabUnpin(tab);
+      GroupItems.removeAppTab(tab);
+    };
+
     // Actually register the above handlers
     for (let name in this._eventListeners)
       AllTabs.register(name, this._eventListeners[name]);
-
-    // Start watching for tab pin events, and set up our uninit for same.
-    function handleTabPin(event) {
-      TabItems.handleTabPin(event.originalTarget);
-      GroupItems.addAppTab(event.originalTarget);
-    }
-
-    gBrowser.tabContainer.addEventListener("TabPinned", handleTabPin, false);
-    this._cleanupFunctions.push(function() {
-      gBrowser.tabContainer.removeEventListener("TabPinned", handleTabPin, false);
-    });
-
-    // Start watching for tab unpin events, and set up our uninit for same.
-    function handleTabUnpin(event) {
-      TabItems.handleTabUnpin(event.originalTarget);
-      GroupItems.removeAppTab(event.originalTarget);
-    }
-
-    gBrowser.tabContainer.addEventListener("TabUnpinned", handleTabUnpin, false);
-    this._cleanupFunctions.push(function() {
-      gBrowser.tabContainer.removeEventListener("TabUnpinned", handleTabUnpin, false);
-    });
   },
 
   // ----------
   // Function: _removeTabActionHandlers
   // Removes handlers to handle tab actions.
   _removeTabActionHandlers: function UI__removeTabActionHandlers() {
     for (let name in this._eventListeners)
       AllTabs.unregister(name, this._eventListeners[name]);
@@ -1071,17 +1094,17 @@ let UI = {
     var scale = Math.min(hScale, wScale);
     var self = this;
     var pairs = [];
     items.forEach(function(item) {
       if (item.locked.bounds)
         return;
 
       var bounds = item.getBounds();
-      bounds.left += newPageBounds.left - self._pageBounds.left;
+      bounds.left += (UI.rtl ? -1 : 1) * (newPageBounds.left - self._pageBounds.left);
       bounds.left *= scale;
       bounds.width *= scale;
 
       bounds.top += newPageBounds.top - self._pageBounds.top;
       bounds.top *= scale;
       bounds.height *= scale;
 
       pairs.push({
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -155,16 +155,18 @@ endif
                  browser_bug581947.js \
                  browser_bug585785.js \
                  browser_bug585830.js \
                  browser_bug592338.js \
                  browser_bug594131.js \
                  browser_bug595507.js \
                  browser_bug596687.js \
                  browser_bug597218.js \
+                 browser_bug598923.js \
+                 browser_bug599325.js \
                  browser_bug609700.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
                  browser_gestureSupport.js \
                  browser_getshortcutoruri.js \
                  browser_hide_removing.js \
--- a/browser/base/content/test/browser_bug581947.js
+++ b/browser/base/content/test/browser_bug581947.js
@@ -17,16 +17,20 @@ function check(aElementName, aBarred, aT
   if (aBarred) {
     ok(!FillInHTMLTooltip(e),
        "No tooltip should be shown when the element is barred from constraint validation");
   } else {
     ok(FillInHTMLTooltip(e),
        "A tooltip should be shown when the element isn't valid");
   }
 
+  e.setAttribute('title', '');
+  ok (!FillInHTMLTooltip(e),
+      "No tooltip should be shown if the title attribute is set");
+
   content.removeChild(e);
 }
 
 function todo_check(aElementName, aBarred) {
   let doc = gBrowser.contentDocument;
   let tooltip = document.getElementById("aHTMLTooltip");
   let content = doc.getElementById('content');
 
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug598923.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test:
+// * if add-on is installed to the add-on bar, the bar is made visible.
+// * if add-on is uninstalled from the add-on bar, and no more add-ons there,
+//   the bar is hidden.
+
+function test() {
+  let aml = AddonsMgrListener;
+  ok(aml, "AddonsMgrListener exists");
+  // check is hidden
+  is(aml.addonBar.collapsed, true, "aob is hidden");
+  // aob gets the count
+  AddonsMgrListener.onInstalling();
+  // add an item
+  let element = document.createElement("toolbaritem");
+  aml.addonBar.appendChild(element);
+  // aob checks the count, makes visible
+  AddonsMgrListener.onInstalled();
+  // check is visible
+  is(aml.addonBar.collapsed, false, "aob is visible");
+  // aob gets the count
+  AddonsMgrListener.onUninstalling();
+  // remove an item
+  aml.addonBar.removeChild(element);
+  // aob checks the count, makes hidden
+  AddonsMgrListener.onUninstalled();
+  // check is hidden
+  is(aml.addonBar.collapsed, true, "aob is hidden");
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug599325.js
@@ -0,0 +1,63 @@
+function test() {
+  waitForExplicitFinish();
+  
+  // test the main (normal) browser window
+  testCustomize(window, testChromeless);
+}
+
+function testChromeless() {
+  // test a chromeless window
+  var newWin = openDialog("chrome://browser/content/", "_blank",
+                      "chrome,dialog=no,toolbar=no", "about:blank");
+  ok(newWin, "got new window");
+
+  function runWindowTest() {
+    function finalize() {
+      newWin.removeEventListener("load", runWindowTest, false);
+      newWin.close();
+      finish();
+    }
+    testCustomize(newWin, finalize);
+  }
+
+  newWin.addEventListener("load", runWindowTest, false);
+}
+
+function testCustomize(aWindow, aCallback) {
+  var addonBar = aWindow.document.getElementById("addon-bar");
+  ok(addonBar, "got addon bar");
+  is(addonBar.collapsed, true, "addon bar initially disabled");
+
+  // Launch toolbar customization
+  // ctEl is either iframe that contains the customize sheet, or the dialog
+  var ctEl = aWindow.BrowserCustomizeToolbar();
+
+  is(addonBar.collapsed, false,
+     "file menu is not collapsed during toolbar customization");
+
+  aWindow.gNavToolbox.addEventListener("beforecustomization", function () {
+    aWindow.gNavToolbox.removeEventListener("beforecustomization", arguments.callee, false);
+    executeSoon(ctInit);
+  }, false);
+
+  function ctInit() {
+    // Close toolbar customization
+    closeToolbarCustomization(aWindow, ctEl);
+
+    is(addonBar.getAttribute("collapsed"), "true",
+       "addon bar is collapsed after toolbar customization");
+
+    if (aCallback)
+      aCallback();
+  }
+}
+
+function closeToolbarCustomization(aWindow, aCTWindow) {
+  // Force the cleanup code to be run now instead of onunload.
+  // This also hides the sheet on Mac.
+  aCTWindow.finishToolbarCustomization();
+
+  // On windows and linux, need to explicitly close the window.
+  if (!gCustomizeSheet)
+    aCTWindow.close();
+}
--- a/browser/base/content/test/browser_visibleTabs.js
+++ b/browser/base/content/test/browser_visibleTabs.js
@@ -55,16 +55,23 @@ function test() {
   is(gBrowser.selectedTab, origTab, "sanity check that we're on the original tab");
   gBrowser.showOnlyTheseTabs([testTab]);
   is(gBrowser.visibleTabs.length, 3, "all 3 tabs are still visible");
 
   // Select the test tab and only show that (and pinned)
   gBrowser.selectedTab = testTab;
   gBrowser.showOnlyTheseTabs([testTab]);
 
+  // if the tabview frame is initialized, we need to move the orignal tab to
+  // another group; otherwise, selecting a tab would make all three tabs in 
+  // the same group to display.
+  let tabViewWindow = TabView.getContentWindow();
+  if (tabViewWindow)
+    tabViewWindow.GroupItems.moveTabToGroupItem(origTab, null);
+
   visible = gBrowser.visibleTabs;
   is(visible.length, 2, "2 tabs should be visible including the pinned");
   is(visible[0], pinned, "first is pinned");
   is(visible[1], testTab, "next is the test tab");
   is(gBrowser.tabs.length, 3, "3 tabs should still be open");
 
   gBrowser.selectTabAtIndex(0);
   is(gBrowser.selectedTab, pinned, "first tab is pinned");
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -39,41 +39,45 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/base/content/test/tabview
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
+                 browser_tabview_alltabs.js \
                  browser_tabview_apptabs.js \
                  browser_tabview_bug580412.js \
                  browser_tabview_bug587043.js \
                  browser_tabview_bug587990.js \
+                 browser_tabview_bug589324.js \
                  browser_tabview_bug590606.js \
                  browser_tabview_bug591706.js \
                  browser_tabview_bug594176.js \
                  browser_tabview_bug595191.js \
                  browser_tabview_bug595518.js \
                  browser_tabview_bug595521.js \
                  browser_tabview_bug595804.js \
                  browser_tabview_bug595930.js \
                  browser_tabview_bug595943.js \
                  browser_tabview_bug598600.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_orphaned_tabs.js \
                  browser_tabview_privatebrowsing.js \
+                 browser_tabview_rtl.js \
                  browser_tabview_search.js \
                  browser_tabview_snapping.js \
                  browser_tabview_startup_transitions.js \
                  browser_tabview_undo_group.js \
                  browser_tabview_firstrun_pref.js \
+                 dummy_page.html \
                  head.js \
                  search1.html \
                  search2.html \
                  $(NULL)
 
 # compartments: test disabled
 #                 browser_tabview_multiwindow_search.js \
 
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_alltabs.js
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a test for bug 595395.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Raymond Lee <raymond@appcoast.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+Cu.import("resource:///modules/tabview/AllTabs.jsm");
+
+function test() {
+  waitForExplicitFinish();
+
+  let newTab = gBrowser.addTab();
+
+  // TabPinned
+  let pinned = function(tab) {
+    is(tab, newTab, "The tabs are the same after the tab is pinned");
+    ok(tab.pinned, "The tab gets pinned");
+
+    gBrowser.unpinTab(tab);
+  };
+
+  // TabUnpinned
+  let unpinned = function(tab) {
+    AllTabs.unregister("pinned", pinned);
+    AllTabs.unregister("unpinned", unpinned);
+
+    is(tab, newTab, "The tabs are the same after the tab is unpinned");
+    ok(!tab.pinned, "The tab gets unpinned");
+
+    // clean up and finish
+    gBrowser.removeTab(tab);
+    finish();
+  };
+
+  AllTabs.register("pinned", pinned);
+  AllTabs.register("unpinned", unpinned);
+
+  ok(!newTab.pinned, "The tab is not pinned");
+  gBrowser.pinTab(newTab);
+}
+
--- a/browser/base/content/test/tabview/browser_tabview_bug580412.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug580412.js
@@ -54,31 +54,31 @@ function onTabViewWindowLoaded() {
   ok(TabView.isVisible(), "Tab View is visible");
   is(contentWindow.GroupItems.groupItems.length, 1, "There is only one group");
   let currentActiveGroup = contentWindow.GroupItems.getActiveGroupItem();
 
 //  is(currentActiveGroup.getBounds.bottom(), 40,
 //    "There's currently 40 px between the first group and second group");
 
   let endGame = function() {
+    contentWindow.UI.reset();
     let onTabViewHidden = function() {
       window.removeEventListener("tabviewhidden", onTabViewHidden, false);
       ok(!TabView.isVisible(), "TabView is shown");
       finish();
     };
     window.addEventListener("tabviewhidden", onTabViewHidden, false);
 
     ok(TabView.isVisible(), "TabView is shown");
     
     gBrowser.selectedTab = originalTab;
     TabView.hide();
   }
   
   let part1 = function() {
-//    contentWindow.UI.reset();
     // move down 20 so we're far enough away from the top.
     checkSnap(currentActiveGroup, 0, 20, contentWindow, function(snapped){
       ok(!snapped,"Move away from the edge");
 
       // Just pick it up and drop it.
       checkSnap(currentActiveGroup, 0, 0, contentWindow, function(snapped){
         ok(!snapped,"Just pick it up and drop it");
         
@@ -88,17 +88,19 @@ function onTabViewWindowLoaded() {
           checkSnap(currentActiveGroup, 0, 5, contentWindow, function(snapped){
             ok(!snapped,"Moving five pixels: shouldn't snap");
             endGame();
           });
         });
       });
     });
   }
-  
+
+  currentActiveGroup.setPosition(40, 40, true);
+  currentActiveGroup.arrange({animate: false});
   part1();
 }
 
 function simulateDragDrop(tabItem, offsetX, offsetY, contentWindow) {
   // enter drag mode
   let dataTransfer;
 
   EventUtils.synthesizeMouse(
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug589324.js
@@ -0,0 +1,127 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is bug 589324 test.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Raymond Lee <raymond@appcoast.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  const DUMMY_PAGE_URL = "http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html";
+  const DUMMY_PAGE_URL_2 = "http://mochi.test:8888/";
+
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+  waitForExplicitFinish();
+
+  // open a new window and setup the window state.
+  let newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
+  newWin.addEventListener("load", function(event) {
+    this.removeEventListener("load", arguments.callee, false);
+
+    let newState = {
+      windows: [{
+        tabs: [{
+          entries: [{ url: DUMMY_PAGE_URL }],
+          hidden: true,
+          attributes: {},
+          extData: {
+            "tabview-tab":
+              '{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
+              '"userSize":null,"url":"' + DUMMY_PAGE_URL + '","groupID":1,' + 
+              '"imageData":null,"title":null}'
+          }
+        },{
+          entries: [{ url: DUMMY_PAGE_URL_2 }],
+          hidden: false,
+          attributes: {},
+          extData: {
+            "tabview-tab": 
+              '{"bounds":{"left":315,"top":29,"width":111,"height":84},' + 
+              '"userSize":null,"url":"' + DUMMY_PAGE_URL_2 + '","groupID":2,' + 
+              '"imageData":null,"title":null}'
+          },
+        }],
+        selected:2,
+        _closedTabs: [],
+        extData: {
+          "tabview-groups": '{"nextID":3,"activeGroupId":2}',
+          "tabview-group": 
+            '{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},' + 
+            '"userSize":null,"locked":{},"title":"","id":1},' + 
+            '"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},' + 
+            '"userSize":null,"locked":{},"title":"","id":2}}',
+          "tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":788,"height":548}}'
+        }, sizemode:"normal"
+      }]
+    };
+    ss.setWindowState(newWin, JSON.stringify(newState), true);
+
+    let firstTab = newWin.gBrowser.tabs[0];
+    let secondTab = newWin.gBrowser.tabs[1];
+
+    // wait until the first tab is fully loaded
+    let browser = newWin.gBrowser.getBrowserForTab(firstTab);
+    let onLoad = function() {
+      browser.removeEventListener("load", onLoad, true);
+
+      is(browser.currentURI.spec, DUMMY_PAGE_URL, 
+         "The url of first tab url is dummy_page.html");
+
+      // check the hidden state of both tabs.
+      ok(firstTab.hidden, "The first tab is hidden");
+      ok(!secondTab.hidden, "The second tab is not hidden");
+      is(secondTab, newWin.gBrowser.selectedTab, "The second tab is selected");
+
+      // when the second tab is hidden, the iframe should be initialized and 
+      // the first tab should be visible.
+      let onTabHide = function() {
+        newWin.gBrowser.tabContainer.addEventListener("TabHide", onTabHide, true);
+
+        ok(newWin.TabView.getContentWindow(), "");
+
+        ok(!firstTab.hidden, "The first tab is not hidden");
+        is(firstTab, newWin.gBrowser.selectedTab, "The first tab is selected");
+        ok(secondTab.hidden, "The second tab is hidden");
+
+        // clean up and finish
+        newWin.close();
+
+        finish();
+      };
+      newWin.gBrowser.tabContainer.addEventListener("TabHide", onTabHide, true);
+
+      // switch to another tab
+      newWin.switchToTabHavingURI(DUMMY_PAGE_URL);
+    }
+    browser.addEventListener("load", onLoad, true);
+  }, false);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_rtl.js
@@ -0,0 +1,96 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is tabview RTL support test.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let tabViewShownCount = 0;
+
+// ----------
+function test() {
+  waitForExplicitFinish();
+
+  // verify initial state
+  ok(!TabView.isVisible(), "Tab View starts hidden");
+
+  // use the Tab View button to launch it for the first time
+  window.addEventListener("tabviewshown", onTabViewLoadedAndShown("ltr"), false);
+  toggleTabView();
+}
+
+function toggleTabView() {
+  let button = document.getElementById("tabview-button");
+  ok(button, "Tab View button exists");
+  button.doCommand();
+}
+
+// ----------
+function onTabViewLoadedAndShown(dir) {
+  return function() {
+    window.removeEventListener("tabviewshown", arguments.callee, false);
+    ok(TabView.isVisible(), "Tab View is visible.");
+
+    let contentWindow = document.getElementById("tab-view").contentWindow;
+    let contentDocument = contentWindow.document;
+    is(contentDocument.documentElement.getAttribute("dir"), dir,
+       "The direction should be set to " + dir.toUpperCase());
+
+    // kick off the series
+    window.addEventListener("tabviewhidden", onTabViewHidden(dir), false);
+    TabView.toggle();
+  };
+}
+
+// ---------- 
+function onTabViewHidden(dir) {
+  return function() {
+    window.removeEventListener("tabviewhidden", arguments.callee, false);
+    ok(!TabView.isVisible(), "Tab View is hidden.");
+
+    if (dir == "ltr") {
+      // Switch to RTL mode
+      Services.prefs.setCharPref("intl.uidirection.en-US", "rtl");
+
+      // use the Tab View button to launch it for the second time
+      window.addEventListener("tabviewshown", onTabViewLoadedAndShown("rtl"), false);
+      toggleTabView();
+    } else {
+      // Switch to LTR mode
+      Services.prefs.clearUserPref("intl.uidirection.en-US");
+
+      finish();
+    }
+  };
+}
+
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/dummy_page.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<title>This is a dummy test page</title>
+</head>
+<body>
+<p>This is a dummy test page</p>
+</body>
+</html>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -195,16 +195,17 @@
 
       <!--
         onBeforeValueSet is called by the base-binding's .value setter.
         It should return the value that the setter should use.
       -->
       <method name="onBeforeValueSet">
         <parameter name="aValue"/>
         <body><![CDATA[
+          this._hideOverLink();
           this._value = aValue;
           var returnValue = aValue;
           var action = this._parseActionUrl(aValue);
           if (action) {
             returnValue = action.param;
             this.setAttribute("actiontype", action.type);
           } else {
             this.removeAttribute("actiontype");
@@ -637,54 +638,96 @@
 
       <field name="_overLinkDelayTimer"><![CDATA[
         null
       ]]></field>
 
       <method name="setOverLink">
         <parameter name="aURL"/>
         <body><![CDATA[
-          // If the over-link is already scheduled to appear or hide, cancel it.
-          if (this._overLinkDelayTimer) {
-            clearTimeout(this._overLinkDelayTimer);
-            this._overLinkDelayTimer = null;
+          this._cancelOverLinkDelayTimer();
+
+          // Hide the over-link immediately if necessary.
+          if (!aURL && (XULBrowserWindow.hideOverLinkImmediately ||
+                        this._hideOverLinkImmediately)) {
+            this._setOverLinkState(null);
+            return;
           }
 
-          // Hide the over-link if aURL is falsey or if the URL bar is focused.
-          if (!aURL || this.focused) {
+          // If aURL is falsey, fade it out after a delay.  This happens on
+          // mouseout for example.
+          if (!aURL) {
             this._overLinkDelayTimer = setTimeout(function overLinkOut(self) {
               self._overLinkDelayTimer = null;
-              let style = window.getComputedStyle(self._overLinkBox, null);
-              self._overLinkTransitioning = style.opacity != 0;
-              self.removeAttribute("overlinkstate");
+              self._setOverLinkState("fade-out");
             }, this._overLinkOutDelay, this);
             return;
           }
 
           // If it's in transition, update and show it immediately.
           if (this._overLinkTransitioning) {
             this._updateOverLink(aURL);
-            this._overLinkTransitioning = false;
-            this.setAttribute("overlinkstate", "showing");
+            this._setOverLinkState("showing");
             return;
           }
 
           // Delay the update if it's hidden or shown.  We delay when shown in
           // part for performance reasons: otherwise mousing over the bookmarks
           // menu for example is very laggy.
           this._overLinkDelayTimer = setTimeout(function overLinkIn(self) {
             self._overLinkDelayTimer = null;
             self._updateOverLink(aURL);
-            let style = window.getComputedStyle(self._overLinkBox, null);
-            self._overLinkTransitioning = style.opacity != 1;
-            self.setAttribute("overlinkstate", "fade-in");
+            self._setOverLinkState("fade-in");
           }, this._overLinkInDelay, this);
         ]]></body>
       </method>
 
+      <method name="_hideOverLink">
+        <body><![CDATA[
+          this._hideOverLinkImmediately = true;
+          this.setOverLink("");
+          this._hideOverLinkImmediately = false;
+        ]]></body>
+      </method>
+
+      <method name="_cancelOverLinkDelayTimer">
+        <body><![CDATA[
+          if (this._overLinkDelayTimer) {
+            clearTimeout(this._overLinkDelayTimer);
+            this._overLinkDelayTimer = null;
+          }
+        ]]></body>
+      </method>
+
+      <method name="_setOverLinkState">
+        <parameter name="aVal"/>
+        <body><![CDATA[
+          switch (aVal) {
+          case "fade-in":
+            var style = window.getComputedStyle(this._overLinkBox);
+            this._overLinkTransitioning = style.opacity != 1;
+            this.setAttribute("overlinkstate", aVal);
+            break;
+          case "fade-out":
+            style = window.getComputedStyle(this._overLinkBox);
+            this._overLinkTransitioning = style.opacity != 0;
+            this.setAttribute("overlinkstate", aVal);
+            break;
+          case "showing":
+            this._overLinkTransitioning = false;
+            this.setAttribute("overlinkstate", aVal);
+            break;
+          default:
+            this._overLinkTransitioning = false;
+            this.removeAttribute("overlinkstate");
+            break;
+          }
+        ]]></body>
+      </method>
+
       <method name="_updateOverLink">
         <parameter name="aURL"/>
         <body><![CDATA[
           // Get the width of the bar before we go modifying it.
           var barWidth = this._stack.boxObject.width;
 
           // Determine the pre-path and path of the over-link.  Include the
           // path's leading slash in the pre-path so that if the path is
@@ -756,18 +799,18 @@
         dt.setData("text/unicode", urlString);
         dt.setData("text/html", htmlString);
 
         dt.effectAllowed = "copyLink";
         event.stopPropagation();
       ]]></handler>
 
       <handler event="focus" phase="capturing"><![CDATA[
+        this._hideOverLink();
         this._hideURLTooltip();
-        this.setOverLink(null);
       ]]></handler>
 
       <handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>
       <handler event="drop" phase="capturing" action="this.onDrop(event, this);"/>
       <handler event="select"><![CDATA[
         if (!Cc["@mozilla.org/widget/clipboard;1"]
                .getService(Ci.nsIClipboard)
                .supportsSelectionClipboard())
--- a/browser/branding/nightly/pref/firefox-branding.js
+++ b/browser/branding/nightly/pref/firefox-branding.js
@@ -9,16 +9,17 @@ pref("app.update.interval", 28800);
 pref("app.update.download.backgroundInterval", 60);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://nightly.mozilla.org/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
 
-// Release notes URL
+// Release notes and vendor URLs
 pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
+pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
 
 // Search codes belong only in builds with official branding
 pref("browser.search.param.yahoo-fr", "");
 pref("browser.search.param.yahoo-fr-cjkt", ""); // now unused
 pref("browser.search.param.yahoo-fr-ja", "");
 pref("browser.search.param.yahoo-f-CN", "");
--- a/browser/branding/unofficial/pref/firefox-branding.js
+++ b/browser/branding/unofficial/pref/firefox-branding.js
@@ -9,16 +9,17 @@ pref("app.update.interval", 28800);
 pref("app.update.download.backgroundInterval", 60);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.mozilla.org/products/%APP%/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
 
-// Release notes URL
+// Release notes and vendor URLs
 pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
+pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
 
 // Search codes belong only in builds with official branding
 pref("browser.search.param.yahoo-fr", "");
 pref("browser.search.param.yahoo-fr-cjkt", ""); // now unused
 pref("browser.search.param.yahoo-fr-ja", "");
 pref("browser.search.param.yahoo-f-CN", "");
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -562,16 +562,17 @@ PlacesViewBase.prototype = {
   },
 
   nodeHistoryDetailsChanged: function() { },
   nodeTagsChanged: function() { },
   nodeDateAddedChanged: function() { },
   nodeLastModifiedChanged: function() { },
   nodeKeywordChanged: function() { },
   sortingChanged: function() { },
+  batching: function() { },
   // Replaced by containerStateChanged.
   containerOpened: function() { },
   containerClosed: function() { },
 
   nodeInserted:
   function PVB_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
     let parentElt = aParentPlacesNode._DOMElement;
     if (!parentElt)
@@ -653,18 +654,19 @@ PlacesViewBase.prototype = {
 
     delete this._viewElt._placesView;
   },
 
   get isRTL() {
     if ("_isRTL" in this)
       return this._isRTL;
 
-    return this._isRTL = document.defaultView.getComputedStyle(this, "")
-                                 .direction == "rtl"
+    return this._isRTL = document.defaultView
+                                 .getComputedStyle(this.viewElt, "")
+                                 .direction == "rtl";
   },
 
   /**
    * Adds an "Open All in Tabs" menuitem to the bottom of the popup.
    * @param aPopup
    *        a Places popup.
    */
   _mayAddCommandsItems: function PVB__mayAddCommandsItems(aPopup) {
@@ -1030,17 +1032,17 @@ PlacesToolbar.prototype = {
 
   updateChevron: function PT_updateChevron() {
     // If the chevron is collapsed there's nothing to update.
     if (this._chevron.collapsed)
       return;
 
     // XXX (bug 508816) Scrollbox does not handle correctly RTL mode.
     // This workarounds the issue scrolling the box to the right.
-    if (this._isRTL)
+    if (this.isRTL)
       this._rootElt.scrollLeft = this._rootElt.scrollWidth;
 
     // Update the chevron on a timer.  This will avoid repeated work when
     // lot of changes happen in a small timeframe.
     if (this._updateChevronTimer)
       this._updateChevronTimer.cancel();
 
     this._updateChevronTimer = this._setTimer(100);
@@ -1049,18 +1051,19 @@ PlacesToolbar.prototype = {
   _updateChevronTimerCallback: function PT__updateChevronTimerCallback() {
     let scrollRect = this._rootElt.getBoundingClientRect();
     let childOverflowed = false;
     for (let i = 0; i < this._rootElt.childNodes.length; i++) {
       let child = this._rootElt.childNodes[i];
       // Once a child overflows, all the next ones will.
       if (!childOverflowed) {
         let childRect = child.getBoundingClientRect();
-        childOverflowed = this._isRTL ? (childRect.left < scrollRect.left)
-                                      : (childRect.right > scrollRect.right);
+        childOverflowed = this.isRTL ? (childRect.left < scrollRect.left)
+                                     : (childRect.right > scrollRect.right);
+                                      
       }
       child.style.visibility = childOverflowed ? "hidden" : "visible";
     }
 
     // We rebuild the chevron on popupShowing, so if it is open
     // we must update it.
     if (this._chevron.open)
       this._updateChevronPopupNodesVisibility();
@@ -1255,26 +1258,26 @@ PlacesToolbar.prototype = {
       let eltRect = elt.getBoundingClientRect();
       let eltIndex = Array.indexOf(this._rootElt.childNodes, elt);
       if (PlacesUtils.nodeIsFolder(elt._placesNode) &&
           !PlacesUtils.nodeIsReadOnly(elt._placesNode)) {
         // This is a folder.
         // If we are in the middle of it, drop inside it.
         // Otherwise, drop before it, with regards to RTL mode.
         let threshold = eltRect.width * 0.25;
-        if (this._isRTL ? (aEvent.clientX > eltRect.right - threshold)
-                        : (aEvent.clientX < eltRect.left + threshold)) {
+        if (this.isRTL ? (aEvent.clientX > eltRect.right - threshold)
+                       : (aEvent.clientX < eltRect.left + threshold)) {
           // Drop before this folder.
           dropPoint.ip =
             new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
                                eltIndex, Ci.nsITreeView.DROP_BEFORE);
           dropPoint.beforeIndex = eltIndex;
         }
-        else if (this._isRTL ? (aEvent.clientX > eltRect.left + threshold)
-                             : (aEvent.clientX < eltRect.right - threshold)) {
+        else if (this.isRTL ? (aEvent.clientX > eltRect.left + threshold)
+                            : (aEvent.clientX < eltRect.right - threshold)) {
           // Drop inside this folder.
           dropPoint.ip =
             new InsertionPoint(PlacesUtils.getConcreteItemId(elt._placesNode),
                                -1, Ci.nsITreeView.DROP_ON,
                                PlacesUtils.nodeIsTagQuery(elt._placesNode));
           dropPoint.beforeIndex = eltIndex;
           dropPoint.folderElt = elt;
         }
@@ -1289,18 +1292,18 @@ PlacesToolbar.prototype = {
                                beforeIndex, Ci.nsITreeView.DROP_BEFORE);
           dropPoint.beforeIndex = beforeIndex;
         }
       }
       else {
         // This is a non-folder node or a read-only folder.
         // Drop before it with regards to RTL mode.
         let threshold = eltRect.width * 0.5;
-        if (this._isRTL ? (aEvent.clientX > eltRect.left + threshold)
-                        : (aEvent.clientX < eltRect.left + threshold)) {
+        if (this.isRTL ? (aEvent.clientX > eltRect.left + threshold)
+                       : (aEvent.clientX < eltRect.left + threshold)) {
           // Drop before this bookmark.
           dropPoint.ip =
             new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
                                eltIndex, Ci.nsITreeView.DROP_BEFORE);
           dropPoint.beforeIndex = eltIndex;
         }
         else {
           // Drop after this bookmark.
@@ -1474,17 +1477,17 @@ PlacesToolbar.prototype = {
       this._dropIndicator.collapsed = true;
     }
     else {
       // Dragging over a normal toolbarbutton,
       // show indicator bar and move it to the appropriate drop point.
       let ind = this._dropIndicator;
       let halfInd = ind.clientWidth / 2;
       let translateX;
-      if (this._isRTL) {
+      if (this.isRTL) {
         halfInd = Math.ceil(halfInd);
         translateX = 0 - this._rootElt.getBoundingClientRect().right - halfInd;
         if (this._rootElt.firstChild) {
           if (dropPoint.beforeIndex == -1)
             translateX += this._rootElt.lastChild.getBoundingClientRect().left;
           else {
             translateX += this._rootElt.childNodes[dropPoint.beforeIndex]
                               .getBoundingClientRect().right;
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -1007,16 +1007,34 @@ PlacesTreeView.prototype = {
     let colCount = columns.count;
     let column = this._findColumnByType(desiredColumn);
     if (column) {
       let sortDir = desiredIsDescending ? "descending" : "ascending";
       column.element.setAttribute("sortDirection", sortDir);
     }
   },
 
+  _inBatchMode: false,
+  batching: function PTV__batching(aToggleMode) {
+    if (aToggleMode) {
+      this._inBatchMode = true;
+      if (this.selection) {
+        this.selection.selectEventsSuppressed = true;
+      }
+      this._tree.beginUpdateBatch();
+    }
+    else if (this._inBatchMode){
+      this._inBatchMode = false;
+      if (this.selection) {
+        this.selection.selectEventsSuppressed = false;
+      }
+      this._tree.endUpdateBatch();
+    }
+  },
+
   get result() this._result,
   set result(val) {
     if (this._result) {
       this._result.removeObserver(this);
       this._rootNode.containerOpen = false;
     }
 
     this._result = val;
--- a/browser/components/places/tests/browser/Makefile.in
+++ b/browser/components/places/tests/browser/Makefile.in
@@ -52,17 +52,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_410196_paste_into_tags.js \
 	browser_457473_no_copy_guid.js \
 	browser_sort_in_library.js \
 	browser_library_open_leak.js \
 	browser_library_panel_leak.js \
 	browser_library_search.js \
 	browser_history_sidebar_search.js \
 	browser_bookmarksProperties.js \
-	browser_forgetthissite_single.js \
+	$(warning browser_forgetthissite_single.js temporarily disabled because of very frequent oranges, see bug 551540) \
 	browser_library_left_pane_commands.js \
 	browser_drag_bookmarks_on_toolbar.js \
 	browser_library_middleclick.js \
 	browser_library_views_liveupdate.js \
 	browser_views_liveupdate.js \
 	browser_sidebarpanels_click.js \
 	sidebarpanels_click_test_page.html \
 	browser_library_infoBox.js \
--- a/browser/components/places/tests/browser/browser_library_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_library_views_liveupdate.js
@@ -249,17 +249,17 @@ var bookmarksObserver = {
         var uriString = PlacesUtils.bookmarks.getBookmarkURI(aItemId).spec;
         var isQuery = uriString.substr(0, 6) == "place:";
         if (isQuery) {
           isnot(node, null, "Found new Places node in left pane");
           ok(index >= 0, "Node is at index " + index);
           break;
         }
         // Fallback to separator case if this is not a query.
-      case type == PlacesUtils.bookmarks.TYPE_SEPARATOR:
+      case PlacesUtils.bookmarks.TYPE_SEPARATOR:
         is(node, null, "New Places node not added in left pane");
         break;
       default:
         isnot(node, null, "Found new Places node in left pane");
         ok(index >= 0, "Node is at index " + index);
     }
   },
 
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -89,16 +89,19 @@ const STATE_RESTORE_FINISHED = 3;
 function PrivateBrowsingService() {
   this._obs = Cc["@mozilla.org/observer-service;1"].
               getService(Ci.nsIObserverService);
   this._obs.addObserver(this, "profile-after-change", true);
   this._obs.addObserver(this, "quit-application-granted", true);
   this._obs.addObserver(this, "private-browsing", true);
   this._obs.addObserver(this, "command-line-startup", true);
   this._obs.addObserver(this, "sessionstore-browser-state-restored", true);
+
+  // List of nsIXULWindows we are going to be closing during the transition
+  this._windowsToClose = [];
 }
 
 PrivateBrowsingService.prototype = {
   // Preferences Service
   get _prefs() {
     let prefs = Cc["@mozilla.org/preferences-service;1"].
                 getService(Ci.nsIPrefBranch);
     this.__defineGetter__("_prefs", function() prefs);
@@ -121,19 +124,16 @@ PrivateBrowsingService.prototype = {
   _currentStatus: STATE_IDLE,
 
   // Whether the private browsing mode has been started automatically (ie. always-on)
   _autoStarted: false,
 
   // List of view source window URIs for restoring later
   _viewSrcURLs: [],
 
-  // List of nsIXULWindows we are going to be closing during the transition
-  _windowsToClose: [],
-
   // Whether private browsing has been turned on from the command line
   _lastChangedByCommandLine: false,
 
   // XPCOM registration
   classID: Components.ID("{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingService, 
                                          Ci.nsIObserver,
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1454,23 +1454,16 @@ SessionStoreService.prototype = {
       return tabData;
     else if (browser.__SS_data && browser.__SS_data._tabStillLoading) {
       // use the data to be restored when the tab hasn't been completely loaded
       tabData = browser.__SS_data;
       if (aTab.pinned)
         tabData.pinned = true;
       else
         delete tabData.pinned;
-      if (browser.userTypedValue) {
-        tabData.userTypedValue = browser.userTypedValue;
-        tabData.userTypedClear = browser.userTypedClear;
-      } else {
-        delete tabData.userTypedValue;
-        delete tabData.userTypedClear;
-      }
       return tabData;
     }
     
     var history = null;
     try {
       history = browser.sessionHistory;
     }
     catch (ex) { } // this could happen if we catch a tab during (de)initialization
--- a/browser/components/sessionstore/test/browser/browser_579868.js
+++ b/browser/components/sessionstore/test/browser/browser_579868.js
@@ -34,38 +34,34 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 function test() {
   let tab1 = gBrowser.addTab("about:robots");
   let tab2 = gBrowser.addTab("about:credits");
   tab1.addEventListener("load", mainPart, true);
   waitForExplicitFinish();
-  
+
   function mainPart() {
     // Tell the session storer that the tab is pinned
-    // and that userTypedValue is "Hello World!"
     let newTabState = '{"entries":[{"url":"about:robots"}],"pinned":true,"userTypedValue":"Hello World!"}';
     let ss = Cc["@mozilla.org/browser/sessionstore;1"]
                .getService(Ci.nsISessionStore);
     ss.setTabState(tab1, newTabState);
 
-    // Undo pinning and userTypedValue
+    // Undo pinning
     gBrowser.unpinTab(tab1);
-    tab1.linkedBrowser.userTypedValue = null;
 
     is(tab1.linkedBrowser.__SS_data._tabStillLoading, true, 
        "_tabStillLoading should be true.");
-    
+
     // Close and restore tab
     gBrowser.removeTab(tab1);
     let savedState = JSON.parse(ss.getClosedTabData(window))[0].state;
     isnot(savedState.pinned, true, "Pinned should not be true");
-    isnot(savedState.userTypedValue, "Hello World!",
-          "userTypedValue should not be Hello World!");
     tab1 = ss.undoCloseTab(window, 0);
 
     isnot(tab1.pinned, true, "Should not be pinned");
     gBrowser.removeTab(tab1);
     gBrowser.removeTab(tab2);
     finish();
   }
 }
--- a/browser/components/sessionstore/test/browser/browser_586068-cascaded_restore.js
+++ b/browser/components/sessionstore/test/browser/browser_586068-cascaded_restore.js
@@ -64,20 +64,30 @@ let tests = [test_cascade, test_select, 
 function runNextTest() {
   // Reset the pref
   try {
     Services.prefs.clearUserPref("browser.sessionstore.max_concurrent_tabs");
   } catch (e) {}
 
   // set an empty state & run the next test, or finish
   if (tests.length) {
+    // Enumerate windows and close everything but our primary window. We can't
+    // use waitForFocus() because apparently it's buggy. See bug 599253.
+    var windowsEnum = Services.wm.getEnumerator("navigator:browser");
+    while (windowsEnum.hasMoreElements()) {
+      var currentWindow = windowsEnum.getNext();
+      if (currentWindow != window) {
+        currentWindow.close();
+      }
+    }
+
     ss.setBrowserState(JSON.stringify({ windows: [{ tabs: [{ url: 'about:blank' }] }] }));
-    let test = tests.shift();
-    info("running " + test.name);
-    executeSoon(test);
+    let currentTest = tests.shift();
+    info("running " + currentTest.name);
+    executeSoon(currentTest);
   }
   else {
     ss.setBrowserState(stateBackup);
     executeSoon(finish);
   }
 }
 
 
--- a/browser/components/test/browser/browser_bug538331.js
+++ b/browser/components/test/browser/browser_bug538331.js
@@ -124,16 +124,56 @@ function test()
 
   if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
     gOriginalOverrideURL = gPrefService.getCharPref(PREF_OVERRIDE_URL);
   }
 
   testDefaultArgs();
 }
 
+var gWindowCatcher = {
+  windowsOpen: 0,
+  finishCalled: false,
+  start: function() {
+    Services.ww.registerNotification(this);
+  },
+
+  finish: function(aFunc) {
+    Services.ww.unregisterNotification(this);
+    this.finishFunc = aFunc;
+    if (this.windowsOpen > 0)
+      return;
+
+    this.finishFunc();
+  },
+
+  closeWindow: function (win) {
+    info("window catcher closing window: " + win.document.documentURI);
+    win.close();
+    this.windowsOpen--;
+    if (this.finishFunc) {
+      this.finish(this.finishFunc);
+    }
+  },
+
+  windowLoad: function (win) {
+    executeSoon(this.closeWindow.bind(this, win));
+  },
+
+  observe: function(subject, topic, data) {
+    if (topic != "domwindowopened")
+      return;
+
+    this.windowsOpen++;
+    let win = subject.QueryInterface(Ci.nsIDOMWindow);
+    info("window catcher caught window opening: " + win.document.documentURI);
+    win.addEventListener("load", this.windowLoad.bind(this, win), false);
+  }
+};
+
 function finish_test()
 {
   // Reset browser.startup.homepage_override.mstone to the original value or
   // clear it if it didn't exist.
   if (gOriginalMStone) {
     gPrefService.setCharPref(PREF_MSTONE, gOriginalMStone);
   } else if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
     gPrefService.clearUserPref(PREF_MSTONE);
@@ -254,16 +294,20 @@ const BG_NOTIFY_TESTS = [
 
 // Test showing a notification after an update
 // _showUpdateNotification in nsBrowserGlue.js
 function testShowNotification()
 {
   let gTestBrowser = gBrowser.selectedBrowser;
   let notifyBox = gBrowser.getNotificationBox(gTestBrowser);
 
+  // Catches any windows opened by these tests (e.g. alert windows) and closes
+  // them
+  gWindowCatcher.start();
+
   for (let i = 0; i < BG_NOTIFY_TESTS.length; i++) {
     let test = BG_NOTIFY_TESTS[i];
     ok(true, "Test showNotification " + (i + 1) + ": " + test.description);
 
     if (test.actions) {
       let actionsXML = " actions=\"" + test.actions + "\"";
       if (test.notificationText) {
         actionsXML += " notificationText=\"" + test.notificationText + "\"";
@@ -305,24 +349,28 @@ function testShowNotification()
             is(accessKey, test.notificationButtonAccessKey, "Update " +
                "notification box button should have the accesskey " +
                "provided by the update");
           }
         }
         // The last test opens an url and verifies the url from the updates.xml
         // is correct.
         if (i == (BG_NOTIFY_TESTS.length - 1)) {
-          button.click();
-          gBrowser.selectedBrowser.addEventListener("load", testNotificationURL, true);
+          // Wait for any windows caught by the windowcatcher to close
+          gWindowCatcher.finish(function () {
+            button.click();
+            gBrowser.selectedBrowser.addEventListener("load", testNotificationURL, true);
+          });
+        } else {
+          notifyBox.removeAllNotifications(true);
         }
       } else if (i == (BG_NOTIFY_TESTS.length - 1)) {
         // If updateBox is null the test has already reported errors so bail
         finish_test();
       }
-      notifyBox.removeAllNotifications(true);
     } else {
       ok(!updateBox, "Update notification box should not have been displayed");
     }
 
     let prefHasUserValue = gPrefService.prefHasUserValue(PREF_POSTUPDATE);
     is(prefHasUserValue, false, "preference " + PREF_POSTUPDATE +
        " shouldn't have a user value");
   }
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -266,16 +266,18 @@
 @BINPATH@/components/xpcom_xpti.xpt
 @BINPATH@/components/xpconnect.xpt
 @BINPATH@/components/xulapp.xpt
 @BINPATH@/components/xuldoc.xpt
 @BINPATH@/components/xultmpl.xpt
 @BINPATH@/components/zipwriter.xpt
 
 ; JavaScript components
+@BINPATH@/components/ConsoleAPI.manifest
+@BINPATH@/components/ConsoleAPI.js
 @BINPATH@/components/FeedProcessor.manifest
 @BINPATH@/components/FeedProcessor.js
 @BINPATH@/components/BrowserFeeds.manifest
 @BINPATH@/components/FeedConverter.js
 @BINPATH@/components/FeedWriter.js
 @BINPATH@/components/fuelApplication.manifest
 @BINPATH@/components/fuelApplication.js
 @BINPATH@/components/WebContentConverter.js
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -364,16 +364,18 @@ Section "-Application" APP_IDX
   ; These need special handling on uninstall since they may be overwritten by
   ; an install into a different location.
   StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
   ${WriteRegStr2} $TmpVal "$0" "" "$INSTDIR\${FileMainEXE}" 0
   ${WriteRegStr2} $TmpVal "$0" "Path" "$INSTDIR" 0
 
   StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
   ${CreateRegKey} "$TmpVal" "$0" 0
+  StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe"
+  ${CreateRegKey} "$TmpVal" "$0" 0
 
   ${If} $TmpVal == "HKLM"
     ; Set the permitted LSP Categories for WinVista and above
     ${SetAppLSPCategories} ${LSP_CATEGORIES}
   ${EndIf}
 
   ; Create shortcuts
   ${LogHeader} "Adding Shortcuts"
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -293,16 +293,19 @@ Section "Uninstall"
 
   StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
   ${If} $R9 == "false"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
     StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\${FileMainEXE}"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
+    StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe"
+    DeleteRegKey HKLM "$0"
+    DeleteRegKey HKCU "$0"
     StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=firefox"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
   ${Else}
     ReadRegStr $R1 HKLM "$0" ""
     ${un.RemoveQuotesFromPath} "$R1" $R1
     ${un.GetParent} "$R1" $R1
     ${If} "$INSTDIR" == "$R1"
--- a/browser/locales/en-US/chrome/browser/syncSetup.dtd
+++ b/browser/locales/en-US/chrome/browser/syncSetup.dtd
@@ -87,18 +87,16 @@
 <!ENTITY choice2.merge.main.label      "Merge this computer's data with my &syncBrand.shortName.label; data">
 <!ENTITY choice2.merge.recommended.label "Recommended:">
 <!ENTITY choice2.client.main.label     "Replace all data on this computer with my &syncBrand.shortName.label; data">
 <!ENTITY choice2.server.main.label     "Replace all other devices with this computer's data">
 
 <!-- Confirm Merge Options -->
 <!ENTITY setup.optionsConfirmPage.title "Confirm">
 <!ENTITY confirm.merge.label    "&syncBrand.fullName.label; will now merge all this computer's browser data into your Sync account.">
-<!ENTITY confirm.client.label         "All &brandShortName; data on this computer will be deleted, including the following:">
+<!ENTITY confirm.client2.label         "Warning: The following &brandShortName; data on this computer will be deleted:">
 <!ENTITY confirm.client.moreinfo.label "&brandShortName; will then copy your &syncBrand.fullName.label; data to this computer.">
-<!ENTITY confirm.client.warning.label "WARNING: This will result in all &brandShortName; data on this computer being replaced!">
-<!ENTITY confirm.server.label         "The following devices will be overwritten with your local data:">
-<!ENTITY confirm.server.warning.label "WARNING: Your local data will replace all &brandShortName; data on these devices!">
+<!ENTITY confirm.server2.label         "Warning: The following devices will be overwritten with your local data:">
 
 <!-- New & Existing Account: Setup Complete -->
 <!ENTITY setup.successPage.title "Setup Complete">
 <!ENTITY changeOptions.label "You can change this preference by selecting Sync Options below.">
 <!ENTITY continueUsing.label "You may now continue using &brandShortName;.">
--- a/browser/themes/gnomestripe/browser/tabview/tabview.css
+++ b/browser/themes/gnomestripe/browser/tabview/tabview.css
@@ -8,81 +8,122 @@ body {
 #bg {
   background: -moz-linear-gradient(top,#C4C4C4,#9E9E9E);
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   background-color: #D7D7D7;
   border-radius: 0.4em;
   box-shadow: 0 1px 0 #FFFFFF inset,
               0 -1px 1px rgba(255, 255, 255, 0.4) inset,
               1px 0 1px rgba(255, 255, 255, 0.4) inset,
               -1px 0 1px rgba(255, 255, 255, 0.4) inset,
               0 1px 1.5px rgba(0, 0, 0, 0.4);
   cursor: pointer;
   margin: 4px;
 }
 
+html[dir=rtl] .tab {
+  box-shadow: 0 1px 0 #FFFFFF inset,
+              0 -1px 1px rgba(255, 255, 255, 0.4) inset,
+              -1px 0 1px rgba(255, 255, 255, 0.4) inset,
+              1px 0 1px rgba(255, 255, 255, 0.4) inset,
+              0 1px 1.5px rgba(0, 0, 0, 0.4);
+}
+
 .tab canvas,
 .cached-thumb {
   border: 1px solid rgba(0,0,0,0.2);
 }
 
 .thumb {
   box-shadow: 1px 2px 0 rgba(0, 0, 0, 0.2);
   background-color: white;  
 }
 
+html[dir=rtl] .thumb {
+  box-shadow: -1px 2px 0 rgba(0, 0, 0, 0.2);
+}
+
 .favicon {
   background-color: #D7D7D7;
-  border-bottom-right-radius: 0.4em;
   box-shadow:
     0 -1px 0 rgba(225, 225, 225, 0.8) inset,
     -1px 0 0 rgba(225, 225, 225, 0.8) inset;
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   top: 4px;
   left: 4px;
-  border-right: 1px solid rgba(0, 0, 0, 0.3);
+  -moz-border-end: 1px solid rgba(0, 0, 0, 0.3);
   border-bottom: 1px solid rgba(0, 0, 0, 0.3);
   height: 16px;
   width: 16px;
 }
 
+html[dir=ltr] .favicon {
+  border-bottom-right-radius: 0.4em;
+}
+
+html[dir=rtl] .favicon {
+  border-bottom-left-radius: 0.4em;
+  box-shadow:
+    0 -1px 0 rgba(225, 225, 225, 0.8) inset,
+    1px 0 0 rgba(225, 225, 225, 0.8) inset;
+  left: auto;
+  right: 2px;
+}
+
 .favicon img {
   border: none;
   width: 16px;
   height: 16px;
 }
 
 .close {
   top: 6px;
   right: 6px;
   width: 16px;
   height: 16px;
   opacity: 0.2;
   background: url("moz-icon://stock/gtk-close?size=menu") no-repeat;
 }
 
+html[dir=rtl] .close {
+  right: auto;
+  left: 6px;
+}
+
 .close:hover {
   opacity: 1.0;
 }
 
 .expander {
   bottom: 8px;
   right: 6px;
   width: 16px;
   height: 16px;
   background: url(chrome://global/skin/icons/resizer.png) no-repeat;
   opacity: 0.2;
 }
 
+html[dir=rtl] .expander {
+  right: auto;
+  left: 6px;
+  -moz-transform: scaleX(-1);
+}
+
 .expander:hover {
   opacity: 1.0;
 }
 
 .close:hover,
 .expander:hover {
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
@@ -107,22 +148,30 @@ body {
 .stacked {
   padding: 0;
 }
 
 .stacked .thumb {
   box-shadow: rgba(0,0,0,.2) 1px 1px 4px;
 }
 
+html[dir=rtl] .stacked .thumb {
+  box-shadow: rgba(0,0,0,.2) -1px 1px 4px;
+}
+
 .stack-trayed .tab-title {
   text-shadow: rgba(0,0,0,1) 1px 1px 1.5px;
   color: #EEE;
   font-size: 11px;
 }
 
+html[dir=rtl] .stack-trayed .tab-title {
+  text-shadow: rgba(0,0,0,1) -1px 1px 1.5px;
+}
+
 .stack-trayed .thumb {
   box-shadow: none !important;
 }
 
 .focus {
   box-shadow: rgba(54,79,225,1) 0px 0px 3.5px -1px !important;
 }
 
@@ -154,42 +203,56 @@ body {
   border: 1px solid rgba(230,230,230,1);
   background-color: rgba(248,248,248,1);
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0,0.2) 1px 1px 3px;
 }
 
+html[dir=rtl] .groupItem {
+  box-shadow:
+    inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
+    rgba(0,0,0,0.2) -1px 1px 3px;
+}
+
 .groupItem.activeGroupItem {
   box-shadow:
     rgba(0,0,0,0.6) 1px 1px 5.5px;
 }
 
+html[dir=rtl] .groupItem.activeGroupItem {
+  box-shadow:
+    rgba(0,0,0,0.6) -1px 1px 5.5px;
+}
+
 .phantom {
   border: 1px solid rgba(190,190,190,1);
 }
 
 .overlay {
   background-color: rgba(0,0,0,.7) !important;
   box-shadow: 3px 3px 5.5px rgba(0,0,0,.5);
   border-radius: 0.4em;
-  /*
-  border: 1px solid rgba(230,230,230,1);
-  background-color: rgba(248,248,248,1);
-  box-shadow:
-    rgba(0,0,0, .3) 2px 2px 5.5px,
-    inset rgba(255, 255, 255, 0.6) 0 0 0 2px; */
+}
+
+html[dir=rtl] .overlay {
+  box-shadow: -3px 3px 5.5px rgba(0,0,0,.5);
 }
 
 .appTabTray {
   top: 34px;
   right: 1px;
 }
 
+html[dir=rtl] .appTabTray {
+  right: auto;
+  left: 1px;
+}
+
 .appTabIcon {
   width: 16px;
   height: 16px;
   cursor: pointer;
 }
 
 .undo {
   background-color: #A0A0A0;
@@ -210,16 +273,21 @@ body {
 }
 
 .undo .close {
   top: 4px;
   left: 4px;
   opacity: 0.5;
 }
 
+html[dir=rtl] .undo .close {
+  left: auto;
+  right: 4px;
+}
+
 .undo .close:hover{
   opacity: 1.0;
 }
 
 
 /* InfoItems
 ----------------------------------*/
 
@@ -228,28 +296,38 @@ body {
   border: 1px solid rgba(230,230,230,1);
   background-color: rgba(248,248,248,1);
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0, .2) 1px 1px 3px;
 }
 
+html[dir=rtl] .info-item {
+  box-shadow:
+    inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
+    rgba(0,0,0, .2) -1px 1px 3px;
+}
+
 .intro {
   margin: 10px;
 }
 
 /* Trenches
 ----------------------------------*/
 
 .guideTrench {
   opacity: 0.9;
   border: 1px dashed  rgba(0,0,0,.12);
   border-bottom: none;
-  border-right: none;
+  -moz-border-end: none;
+  box-shadow: 1px 1px 0 rgba(255,255,255,.15);
+}
+
+html[dir=rtl] .guideTrench {
   box-shadow: 1px 1px 0 rgba(255,255,255,.15);
 }
 
 .visibleTrench {
   opacity: 0.05;
 }
 
 .activeVisibleTrench {
@@ -278,42 +356,62 @@ body {
   height: 15px;
   bottom: 10px;
   left: 10px;
   cursor: pointer;
   opacity: .3;
   background-image: url(chrome://browser/skin/tabview/new-tab.png);
 }
 
+html[dir=rtl] .newTabButton {
+  left: auto;
+  right: 10px;
+}
+
 .newTabButton:hover {
   opacity: 1;
 }
 
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
+html[dir=rtl] .active {
+  box-shadow: -5px 5px 3px rgba(0,0,0,.5);
+}
+
 .acceptsDrop {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
+html[dir=rtl] .acceptsDrop {
+  box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
+}
+
 .titlebar {
   font-size: 12px;
   line-height: 18px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: #999;
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-start: 3px;
   padding: 1px;
   background-image: url(chrome://browser/skin/tabview/edit-light.png);
-  padding-left: 20px;
+  -moz-padding-start: 20px;
+}
+
+html[dir=rtl] input.name {
+  background-position: right top;
 }
 
 .title-container:hover input.name {
   border: 1px solid #ddd;
 }
 
 .title-container:hover input.name-locked {
   border: 1px solid transparent !important;
@@ -334,24 +432,32 @@ input.defaultName {
   color: #CCC;
 }
 
 .title-container {
   cursor: text;
 }
 
 .title-shield {
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-start: 3px;
   padding: 1px;
   left: 0;
   top: 0;
   width: 100%;
   height: 100%;
 }
 
+html[dir=rtl] .title-shield {
+  left: auto;
+  right: 0;
+}
+
 .transparentBorder {
   border: 1px solid transparent !important;
 }
 
 .stackExpander {
   opacity: .4;
   cursor: pointer;
   background-image: url(chrome://browser/skin/tabview/stack-expander.png);
@@ -369,43 +475,61 @@ input.defaultName {
   background-image: url(chrome://global/skin/icons/resizer.png);
   width: 16px;
   height: 16px;
   bottom: 0px;
   right: 0px;
   opacity: .2;
 }
 
+html[dir=rtl] .resizer {
+  right: auto;
+  left: 0;
+  -moz-transform: scaleX(-1);
+}
+
 .iq-resizable-handle {
   font-size: 0.1px;
 }
 
 .iq-resizable-se {
   cursor: se-resize;
   width: 12px;
   height: 12px;
   right: 1px;
   bottom: 1px;
 }
 
+html[dir=rtl] .iq-resizable-se {
+  cursor: sw-resize;
+  right: auto;
+  left: 1px;
+}
+
 /* Exit button
 +----------------------------------*/
 #exit-button {
   cursor: default;
   top: 0;
   right: 0;
   width: 28px;
   height: 27px;
   background: -moz-image-rect(url(chrome://browser/skin/tabview/tabview.png), 0, 16, 16, 0) no-repeat scroll 7px 7px #b7b7b7;
   border-bottom: 1px solid #909090;
-  border-left: 1px solid #B7B7B7;
+  -moz-border-start: 1px solid #B7B7B7;
   border-top: 1px solid #CFCFCF;
   border-radius: 3px 0 0 3px;
 }
 
+html[dir=rtl] #exit-button {
+  right: auto;
+  left: 0;
+  border-radius: 0 3px 3px 0;
+}
+
 /* Search
 ----------------------------------*/
 
 #search{
   background-color: rgba(0,0,0,.42);
   width: 100%;
   height: 100%;  
 }
@@ -413,32 +537,42 @@ input.defaultName {
 #searchbox{
   width: 270px;
   height: 30px;
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,1), 0px 0px 9px rgba(0,0,0,.8);
   color: white;
   border: none;
   background-color: #272727;
   border-radius: 0.4em;
-  padding-left:5px; padding-right: 5px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 5px;
   font-size: 14px;  
 }
 
 #actions{
   width: 30px;
   height: 30px;
   background-color: #666;
   border: none;
-  border-bottom-left-radius: 0.4em;
-  border-top-left-radius: 0.4em;    
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset 6px 6px 9px rgba(0,0,0,.56);
   opacity: .64;
   text-align: center;
 }
 
+html[dir=ltr] #actions {
+  border-bottom-left-radius: 0.4em;
+  border-top-left-radius: 0.4em;    
+}
+
+html[dir=rtl] #actions {
+  border-bottom-right-radius: 0.4em;
+  border-top-right-radius: 0.4em;    
+  box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset -6px 6px 9px rgba(0,0,0,.56);
+}
+
 #actions #searchbutton{
   background: transparent url(chrome://browser/skin/tabview/search.png) no-repeat;
   border: none;
   width: 20px;
   height: 20px;
   margin-top:5px;
   opacity: .8;  
 }
@@ -455,41 +589,46 @@ input.defaultName {
   left: 0px;
   bottom: 0px;
   width: 100%;
   height: 30px;
   background-color: rgba(0,0,0,.3);
   box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
 }
 
+html[dir=rtl] #otherresults {
+  left: auto;
+  right: 0;
+}
+
 #otherresults .label {
   color: #999;
   line-height: 30px;
-  margin-left: 5px;
-  margin-right: 5px;
+  -moz-margin-start: 5px;
+  -moz-margin-end: 5px;
 }
 
 .inlineMatch {
   background-color: #EBEBEB;
   border-radius: 0.4em;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
   border: 1px solid rgba(255, 255, 255, 0.5);
-  padding-left: 3px;
-  padding-right: 3px;
+  -moz-padding-start: 3px;
+  -moz-padding-end: 3px;
   height: 20px;
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   cursor: pointer;
 }
 
 .inlineMatch:hover {
   opacity: 1.0;
 }
 
 .inlineMatch > img {
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   position: relative;
   top: 2px;
 }
 
 .inlineMatch > span {
   max-width: 200px;
   height: 15px;
 }
--- a/browser/themes/pinstripe/browser/tabview/tabview.css
+++ b/browser/themes/pinstripe/browser/tabview/tabview.css
@@ -9,17 +9,20 @@ body {
 #bg {
   background: -moz-linear-gradient(top,#C4C4C4,#9E9E9E);
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   background-color: #D7D7D7;
   border-radius: 0.4em;
   box-shadow: 0 1px 1.5px rgba(0, 0, 0, 0.4);
   border: 1px solid rgba(255, 255, 255, 0.5);
   cursor: pointer;
   margin: 8px;
 }
 
@@ -28,31 +31,50 @@ body {
   border: 1px solid rgba(0, 0, 0, 0.3);
 }
 
 .thumb {
   box-shadow: 1px 2px 0 rgba(0, 0, 0, 0.2);
   background-color: white;  
 }
 
+html[dir=rtl] .thumb {
+  box-shadow: -1px 2px 0 rgba(0, 0, 0, 0.2);
+}
+
 .favicon {
   background-color: #D7D7D7;
-  border-bottom-right-radius: 0.4em;
   box-shadow:
     0 -1px 0 rgba(225, 225, 225, 0.8) inset,
     -1px 0 0 rgba(225, 225, 225, 0.8) inset;
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   top: 4px;
   left: 4px;
-  border-right: 1px solid rgba(0, 0, 0, 0.3);
+  -moz-border-end: 1px solid rgba(0, 0, 0, 0.3);
   border-bottom: 1px solid rgba(0, 0, 0, 0.3);
   height: 16px;
   width: 16px;
 }
 
+html[dir=ltr] .favicon {
+  border-bottom-right-radius: 0.4em;
+}
+
+html[dir=rtl] .favicon {
+  border-bottom-left-radius: 0.4em;
+  box-shadow:
+    0 -1px 0 rgba(225, 225, 225, 0.8) inset,
+    1px 0 0 rgba(225, 225, 225, 0.8) inset;
+  left: auto;
+  right: 2px;
+}
+
 .favicon img {
   border: none;
   width: 16px;
   height: 16px;
 }
 
 .close {
   top: 6px;
@@ -61,28 +83,39 @@ body {
   height: 16px;
   background: url(chrome://global/skin/icons/closetab.png) no-repeat;
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 0.2;
 }
 
+html[dir=rtl] .close {
+  right: auto;
+  left: 6px;
+}
+
 .expander {
   bottom: 8px;
   right: 6px;
   width: 16px;
   height: 16px;
   background: url(chrome://global/skin/icons/resizer.png) no-repeat;
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 0.2;
 }
 
+html[dir=rtl] .expander {
+  right: auto;
+  left: 6px;
+  -moz-transform: scaleX(-1);
+}
+
 .close:hover,
 .expander:hover {
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 1.0;
 }
 
@@ -105,22 +138,30 @@ body {
 .stacked {
   padding: 0;
 }
 
 .stacked .thumb {
   box-shadow: rgba(0,0,0,.2) 1px 1px 4px;
 }
 
+html[dir=rtl] .stacked .thumb {
+  box-shadow: rgba(0,0,0,.2) -1px 1px 4px;
+}
+
 .stack-trayed .tab-title {
   text-shadow: rgba(0,0,0,1) 1px 1px 1.5px;
   color: #EEE;
   font-size: 11px;
 }
 
+html[dir=rtl] .stack-trayed .tab-title {
+  text-shadow: rgba(0,0,0,1) -1px 1px 1.5px;
+}
+
 .stack-trayed .thumb {
   box-shadow: none !important;
 }
 
 .tab.focus {
   box-shadow: 0 0 5.5px -moz-mac-menuselect/*#0060D6*/;
   border: 1px solid rgba(255, 255, 255, 0.6);
 }
@@ -166,37 +207,45 @@ body {
   border: 1px solid rgba(255, 255, 255, 0.5);
 }
 
 .groupItem.activeGroupItem {
   box-shadow:
     rgba(0,0,0,0.6) 1px 1px 5.5px;
 }
 
+html[dir=rtl] .groupItem.activeGroupItem {
+  box-shadow:
+    rgba(0,0,0,0.6) -1px 1px 5.5px;
+}
+
 .phantom {
   border: 1px solid rgba(255, 255, 255, 0.5);
 }
 
 .overlay {
   background-color: rgba(0,0,0,.7) !important;
   box-shadow: 3px 3px 5.5px rgba(0,0,0,.5);
   border-radius: 0.4em;
-  /*
-  border: 1px solid rgba(230,230,230,1);
-  background-color: rgba(248,248,248,1);
-  box-shadow:
-    rgba(0,0,0, .3) 2px 2px 5.5px,
-    inset rgba(255, 255, 255, 0.6) 0 0 0 2px; */
+}
+
+html[dir=rtl] .overlay {
+  box-shadow: -3px 3px 5.5px rgba(0,0,0,.5);
 }
 
 .appTabTray {
   top: 34px;
   right: 1px;
 }
 
+html[dir=rtl] .appTabTray {
+  right: auto;
+  left: 1px;
+}
+
 .appTabIcon {
   width: 16px;
   height: 16px;
   cursor: pointer;
 }
 
 .undo {
   background-color: #A0A0A0;
@@ -217,16 +266,21 @@ body {
 }
 
 .undo .close {
   top: 4px;
   left: 4px;
   opacity: 0.5;
 }
 
+html[dir=rtl] .undo .close {
+  left: auto;
+  right: 4px;
+}
+
 .undo .close:hover{
   opacity: 1.0;
 }
 
 /* InfoItems
 ----------------------------------*/
 
 .info-item {
@@ -234,31 +288,41 @@ body {
   border: 1px solid rgba(230,230,230,1);
   background-color: rgba(248,248,248,1);
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0, .2) 1px 1px 3px;
 }
 
+html[dir=rtl] .info-item {
+  box-shadow:
+    inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
+    rgba(0,0,0, .2) -1px 1px 3px;
+}
+
 .intro {
   margin: 10px;
 }
 
 /* Trenches
 ----------------------------------*/
 
 .guideTrench {
   opacity: 0.9;
   border: 1px dashed  rgba(0,0,0,.12);
   border-bottom: none;
-  border-right: none;
+  -moz-border-end: none;
   box-shadow: 1px 1px 0 rgba(255,255,255,.15);
 }
 
+html[dir=rtl] .guideTrench {
+  box-shadow: -1px 1px 0 rgba(255,255,255,.15);
+}
+
 .visibleTrench {
   opacity: 0.05;
 }
 
 .activeVisibleTrench {
   opacity: 0;
 }
 
@@ -284,42 +348,62 @@ body {
   height: 15px;
   bottom: 10px;
   left: 10px;
   cursor: pointer;
   opacity: .3;
   background-image: url(chrome://browser/skin/tabview/new-tab.png);
 }
 
+html[dir=rtl] .newTabButton {
+  left: auto;
+  right: 10px;
+}
+
 .newTabButton:hover {
   opacity: 1;
 }
 
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
+html[dir=rtl] .active {
+  box-shadow: -5px 5px 3px rgba(0,0,0,.5);
+}
+
 .acceptsDrop {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
+html[dir=rtl] .acceptsDrop {
+  box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
+}
+
 .titlebar {
   font-size: 12px;
   line-height: 18px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: #999;
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-begin: 3px;
   padding: 1px;
   background-image: url(chrome://browser/skin/tabview/edit-light.png);
-  padding-left: 20px;
+  -moz-padding-start: 20px;
+}
+
+html[dir=rtl] input.name {
+  background-position: right top;
 }
 
 .title-container:hover input.name {
   border: 1px solid #ddd;
 }
 
 .title-container:hover input.name-locked {
   border: 1px solid transparent !important;
@@ -340,24 +424,32 @@ input.defaultName {
   color: #CCC;
 }
 
 .title-container {
   cursor: text;
 }
 
 .title-shield {
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-begin: 3px;
   padding: 1px;
   left: 0;
   top: 0;
   width: 100%;
   height: 100%;
 }
 
+html[dir=rtl] .title-shield {
+  left: auto;
+  right: 0;
+}
+
 .transparentBorder {
   border: 1px solid transparent !important;
 }
 
 .stackExpander {
   opacity: .4;
   cursor: pointer;
   background-image: url(chrome://browser/skin/tabview/stack-expander.png);
@@ -375,43 +467,61 @@ input.defaultName {
   background-image: url(chrome://global/skin/icons/resizer.png);
   width: 16px;
   height: 16px;
   bottom: 0px;
   right: 0px;
   opacity: .2;
 }
 
+html[dir=rtl] .resizer {
+  right: auto;
+  left: 0;
+  -moz-transform: scaleX(-1);
+}
+
 .iq-resizable-handle {
   font-size: 0.1px;
 }
 
 .iq-resizable-se {
   cursor: se-resize;
   width: 12px;
   height: 12px;
   right: 1px;
   bottom: 1px;
 }
 
+html[dir=rtl] .iq-resizable-se {
+  cursor: sw-resize;
+  right: auto;
+  left: 1px;
+}
+
 /* Exit button
 +----------------------------------*/
 #exit-button {
   cursor: default;
   top: 0;
   right: 0;
   width: 28px;
   height: 27px;
   background: -moz-image-rect(url(chrome://browser/skin/tabview/tabview.png), 0, 20, 20, 0) no-repeat scroll 4px 4px #b7b7b7;
   border-bottom: 1px solid #909090;
-  border-left: 1px solid #B7B7B7;
+  -moz-border-start: 1px solid #B7B7B7;
   border-top: 1px solid #CFCFCF;
   border-radius: 3px 0 0 3px;
 }
 
+html[dir=rtl] #exit-button {
+  right: auto;
+  left: 0;
+  border-radius: 0 3px 3px 0;
+}
+
 /* Search
 ----------------------------------*/
 
 #search {
   background-color: rgba(0,0,0,.42);
   width: 100%;
   height: 100%;  
 }
@@ -419,32 +529,42 @@ input.defaultName {
 #searchbox {
   width: 270px;
   height: 30px;
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,1), 0px 0px 13px rgba(0,0,0,.8);
   color: white;
   border: none;
   background-color: #272727;
   border-radius: 0.4em;
-  padding-left: 5px; padding-right: 5px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 5px;
   font-size: 14px;  
 }
 
 #actions {
   width: 30px;
   height: 30px;
   background-color: #666;
   border: none;
-  border-bottom-left-radius: 0.4em;
-  border-top-left-radius: 0.4em;    
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset 6px 6px 13px rgba(0,0,0,.56);
   opacity: .64;
   text-align: center;
 }
 
+html[dir=ltr] #actions {
+  border-bottom-left-radius: 0.4em;
+  border-top-left-radius: 0.4em;    
+}
+
+html[dir=rtl] #actions {
+  border-bottom-right-radius: 0.4em;
+  border-top-right-radius: 0.4em;    
+  box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset -6px 6px 13px rgba(0,0,0,.56);
+}
+
 #actions #searchbutton {
   background: transparent url(chrome://browser/skin/tabview/search.png) no-repeat;
   border: none;
   width: 20px;
   height: 20px;
   margin-top:5px;
   opacity: .8;  
 }
@@ -461,41 +581,46 @@ input.defaultName {
   left: 0px;
   bottom: 0px;
   width: 100%;
   height: 30px;
   background-color: rgba(0,0,0,.3);
   box-shadow: 0 -1px 0 rgba(255,255,255,.1), inset 0 2px 5px rgba(0,0,0,.3);
 }
 
+html[dir=rtl] #otherresults {
+  left: auto;
+  right: 0px;
+}
+
 #otherresults .label {
   color: #999;
   line-height: 30px;
-  margin-left: 5px;
-  margin-right: 5px;
+  -moz-margin-start: 5px;
+  -moz-margin-end: 5px;
 }
 
 .inlineMatch {
   background-color: #EBEBEB;
   border-radius: 0.4em;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
   border: 1px solid rgba(255, 255, 255, 0.5);
-  padding-left: 3px;
-  padding-right: 3px;
+  -moz-padding-start: 3px;
+  -moz-padding-end: 3px;
   height: 20px;
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   cursor: pointer;
 }
 
 .inlineMatch:hover {
   opacity: 1.0;
 }
 
 .inlineMatch > img {
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   position: relative;
   top: 2px;
 }
 
 .inlineMatch > span {
   max-width:200px;
   height: 15px;
 }
@@ -504,41 +629,46 @@ input.defaultName {
   left: 0px;
   bottom: 0px;
   width: 100%;
   height: 30px;
   background-color: rgba(0,0,0,.3);
   box-shadow: 0 -1px 0 rgba(255,255,255,.1), inset 0 2px 5px rgba(0,0,0,.3);
 }
 
+html[dir=rtl] #otherresults {
+  left: auto;
+  right: 0;
+}
+
 #otherresults .label {
   color: #999;
   line-height:30px;
-  margin-left:5px;
-  margin-right: 5px;
+  -moz-margin-start: 5px;
+  -moz-margin-end: 5px;
 }
 
 .inlineMatch {
   background-color: #EBEBEB;
   border-radius: 0.4em;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
   border: 1px solid rgba(255, 255, 255, 0.5);
-  padding-left: 3px;
-  padding-right: 3px;
+  -moz-padding-start: 3px;
+  -moz-padding-end: 3px;
   height: 20px;
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   cursor: pointer;
 }
 
 .inlineMatch:hover {
   opacity: 1.0;
 }
 
 .inlineMatch > img {
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   position: relative;
   top: 2px;
 }
 
 .inlineMatch > span {
   max-width: 200px;
   height: 15px;
 }
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -24,26 +24,32 @@
   }
 
   #appmenu-button {
     border: 2px solid;
     border-top: none;
     -moz-border-left-colors: rgba(255,255,255,.5) rgba(83,42,6,.9);
     -moz-border-bottom-colors: rgba(255,255,255,.5) rgba(83,42,6,.9);
     -moz-border-right-colors: rgba(255,255,255,.5) rgba(83,42,6,.9);
+    margin-bottom: -1px; /* compensate white outer border */
     box-shadow: 0 1px 0 rgba(255,255,255,.25) inset,
                 0 0 2px 1px rgba(255,255,255,.25) inset;
   }
 
   #main-window[privatebrowsingmode=temporary] #appmenu-button {
     -moz-border-left-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
     -moz-border-bottom-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
     -moz-border-right-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
   }
 
+  #appmenu-popup {
+    margin-top: -1px;
+    -moz-margin-start: 1px;
+  }
+
   /* Bug 413060, comment 16: Vista Aero is a special case where we use a
      tooltip appearance for the address bar popup panels */
   #identity-popup,
   #editBookmarkPanel {
     -moz-appearance: tooltip;
     color: InfoText;
   }
 
@@ -63,17 +69,16 @@
     -moz-margin-start: -3px;
     position: relative;
     z-index: 10;
   }
 }
 
 @media all and (-moz-windows-compositor) {
   /* these should be hidden w/glass enabled. windows draws it's own buttons. */
-  #titlebar-buttonbox:not(:-moz-lwtheme),
   .titlebar-button {
     display: none;
   }
 
   #main-window[sizemode="maximized"] #titlebar-buttonbox {
     -moz-margin-end: 2px;
   }
 
@@ -124,20 +129,22 @@
   }
   #navigator-toolbox,
   #navigator-toolbox > toolbar {
     border-color: @glassToolbarBorderColor@ !important;
   }
 
   #main-window[sizemode="normal"]:not([inFullscreen="true"]) #navigator-toolbox[tabsontop="true"] > #nav-bar:not(:-moz-lwtheme),
   #main-window[sizemode="normal"]:not([inFullscreen="true"]) #navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme),
-  #main-window[sizemode="normal"]:not([inFullscreen="true"]) #navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme) {
+  #main-window[sizemode="normal"]:not([inFullscreen="true"]) #navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
+  #main-window[sizemode="normal"]:not([inFullscreen="true"]) #navigator-toolbox:not([tabsontop="true"]) > #PersonalToolbar:not(:-moz-lwtheme) {
     border-top-left-radius: 3.5px;
     border-top-right-radius: 3.5px;
   }
+
   #main-window[sizemode="normal"]:not([inFullscreen="true"]) #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
     padding-left: 4px;
     padding-right: 4px;
   }
 
   /* Make the window draggable by glassed toolbars (bug 555081) */
   #toolbar-menubar:not([autohide="true"]),
   #TabsToolbar[tabsontop="true"],
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -117,17 +117,17 @@
   border: 1px solid rgba(83,42,6,.9);
   border-top: none;
   box-shadow: 0 1px 0 rgba(255,255,255,.25) inset,
               0 0 0 1px rgba(255,255,255,.25) inset;
   color: white;
   text-shadow: 0 0 1px rgba(0,0,0,.7),
                0 1px 1.5px rgba(0,0,0,.5);
   font-weight: bold;
-  padding: .1em 1.5em .15em;
+  padding: 0 1.5em .05em;
   margin: 0;
 }
 
 #main-window[privatebrowsingmode=temporary] #appmenu-button {
   background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%);
   border-color: rgba(43,8,65,.9);
 }
 
@@ -173,25 +173,16 @@
   list-style-image: url(appmenu-dropmarker.png);
   width: auto;
   height: auto;
   padding: 0;
   margin: 0;
   -moz-margin-start: .5em;
 }
 
-/* menupopup > menu[_moz-menuactive="true"] etc. from menu.css doesn't match these nodes */
-.split-menuitem-item[_moz-menuactive="true"]:not([disabled]),
-.split-menuitem-menu[_moz-menuactive="true"]:not([disabled]),
-:-moz-any(#appmenuPrimaryPane, #appmenuSecondaryPane) > menu[_moz-menuactive="true"]:not([disabled]),
-:-moz-any(#appmenuPrimaryPane, #appmenuSecondaryPane) > menuitem[_moz-menuactive="true"]:not([disabled]) {
-  background-color: -moz-menuhover;
-  color: -moz-menuhovertext;
-}
-
 .split-menuitem-menu {
   -moz-box-pack: end;
 }
 
 .appmenu-edit-button {
   -moz-appearance: none;
   border: 1px solid transparent;
   padding: 2px;
@@ -205,29 +196,31 @@
 
 @media all and (-moz-windows-default-theme) {
   #appmenu-popup {
     -moz-appearance: none;
     background: white;
     border: 1px solid rgba(0,0,0,.5);
   }
   #appmenuPrimaryPane {
-    margin-right: -1px;
+    -moz-margin-end: -1px;
     background-color: rgba(255,255,255,0.5);
-    border-right: 1px solid #c4c4c5;
-    padding-left: 2px;
+    -moz-border-end: 1px solid #c4c4c5;
+    -moz-padding-start: 2px;
   }
   #appmenuSecondaryPane {
-    -moz-appearance: none;
     background-color: #f1f5fb;
     box-shadow: 1px 0 2px rgb(204,214,234) inset;
     border: 0;
     padding-top: 5px;
     font-family: "Segoe UI Semibold", "Segoe UI", sans-serif;
   }
+  #appmenuSecondaryPane:-moz-locale-dir(rtl) {
+    box-shadow: -1px 0 2px rgb(204,214,234) inset;
+  }
 
   .appmenu-menuseparator {
     -moz-appearance: none;
     margin-top: 3px;
     margin-bottom: 3px;
 %ifdef WINSTRIPE_AERO
     -moz-margin-start: 30px;
 %else
@@ -315,17 +308,16 @@
 
 #main-window[sizemode="maximized"] > #titlebar {
   -moz-appearance: -moz-window-titlebar-maximized;
 }
 
 #titlebar-content {
   margin-left: 15px;
   margin-right: 15px;
-  -moz-box-align: start;
 }
 
 @media all and (-moz-windows-classic) {
   #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
     margin-top: 4px;
   }
 }
 
--- a/browser/themes/winstripe/browser/tabview/tabview.css
+++ b/browser/themes/winstripe/browser/tabview/tabview.css
@@ -9,51 +9,79 @@ body {
   background: url("chrome://browser/skin/tabview/grain.png") repeat scroll center top,
               -moz-linear-gradient(center top , #CCD9EA, #C7D5E7) repeat scroll 0 0 transparent;
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   background-color: #E0EAF5;
   border-radius: 0.4em;
   box-shadow:
     0 1px 0 #FFFFFF inset,
     0 -1px 1px rgba(255, 255, 255, 0.8) inset,
     1px 0 1px rgba(255, 255, 255, 0.8) inset,
     -1px 0 1px rgba(255, 255, 255, 0.8) inset,
     0 1px 1.5px rgba(4, 38, 60, 0.4);
   cursor: pointer;
   margin: 4px;
 }
 
+html[dir=rtl] .tab {
+  box-shadow:
+    0 1px 0 #FFFFFF inset,
+    0 -1px 1px rgba(255, 255, 255, 0.8) inset,
+    -1px 0 1px rgba(255, 255, 255, 0.8) inset,
+    1px 0 1px rgba(255, 255, 255, 0.8) inset,
+    0 1px 1.5px rgba(4, 38, 60, 0.4);
+}
+
 .tab canvas,
 .cached-thumb {
   border: 1px solid rgba(73, 99, 119, 0.3);
 }
 
 .thumb {
   box-shadow: 1px 2px 0 rgba(0, 0, 0, 0.1);
   background-color: white;  
 }
 
+html[dir=rtl] .thumb {
+  box-shadow: -1px 2px 0 rgba(0, 0, 0, 0.1);
+}
+
 .favicon {
   background-color: #E0EAF5;
-  border-bottom-right-radius: 0.4em;
-  padding: 4px 6px 6px 4px;
+  padding-top: 4px;
+  -moz-padding-end: 6px;
+  padding-bottom: 6px;
+  -moz-padding-start: 4px;
   top: 4px;
   left: 4px;
-  border-right: 1px solid rgba(73, 99, 119, 0.3);
+  -moz-border-end: 1px solid rgba(73, 99, 119, 0.3);
   border-bottom: 1px solid rgba(73, 99, 119, 0.3);
   height: 17px;
   width: 17px;
 }
 
+html[dir=ltr] .favicon {
+  border-bottom-right-radius: 0.4em;
+}
+
+html[dir=rtl] .favicon {
+  border-bottom-left-radius: 0.4em;
+  left: auto;
+  right: 2px;
+}
+
 .favicon img {
   border: none;
   width: 16px;
   height: 16px;
 }
 
 .close {
   top: 6px;
@@ -62,28 +90,39 @@ body {
   height: 16px;
   background: url(chrome://global/skin/icons/Close.gif) no-repeat;
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 0.2;
 }
 
+html[dir=rtl] .close {
+  right: auto;
+  left: 6px;
+}
+
 .expander {
   bottom: 6px;
   right: 6px;
   width: 16px;
   height: 16px;
   background: url(chrome://global/skin/icons/resizer.png) no-repeat;
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 0.2;
 }
 
+html[dir=rtl] .expander {
+  right: auto;
+  left: 6px;
+  -moz-transform: scaleX(-1);
+}
+
 .close:hover,
 .expander:hover {
   -moz-transition-property: opacity;
   -moz-transition-duration: 0.5s;
   -moz-transition-timing-function: ease-out;
   opacity: 1.0;
 }
 
@@ -106,35 +145,52 @@ body {
 .stacked {
   padding: 0;
 }
 
 .stacked .thumb {
   box-shadow: rgba(0,0,0,.2) 1px 1px 4px;
 }
 
+html[dir=rtl] .stacked .thumb {
+  box-shadow: rgba(0,0,0,.2) -1px 1px 4px;
+}
+
 .stack-trayed .tab-title {
   text-shadow: rgba(0,0,0,1) 1px 1px 1.5px;
   color: #EEE;
   font-size: 11px;
 }
 
+html[dir=rtl] .stack-trayed .tab-title {
+  text-shadow: rgba(0,0,0,1) -1px 1px 1.5px;
+}
+
 .stack-trayed .thumb {
   box-shadow: none !important;
 }
 
 .tab.focus {
   box-shadow:
     0 1px 0 #FFFFFF inset,
     0 -1px 1px #FFFFFF inset,
     1px 0 1px #FFFFFF inset,
     -1px 0 1px #FFFFFF inset,
     0 0 5.5px #007ECE;
 }
 
+html[dir=rtl] .tab.focus {
+  box-shadow:
+    0 1px 0 #FFFFFF inset,
+    0 -1px 1px #FFFFFF inset,
+    -1px 0 1px #FFFFFF inset,
+    1px 0 1px #FFFFFF inset,
+    0 0 5.5px #007ECE;
+}
+
 /* Tab: Zooming
 ----------------------------------*/
 
 .front .tab-title, 
 .front .close, 
 .front .favicon, 
 .front .expander, 
 .front .thumb-shadow {
@@ -168,41 +224,55 @@ body {
   box-shadow:
     0 1px 0 #FFFFFF inset,
     0 -1px 1px rgba(255, 255, 255, 0.8) inset,
     1px 0 1px rgba(255, 255, 255, 0.8) inset,
     -1px 0 1px rgba(255, 255, 255, 0.8) inset,
     0 1px 3px rgba(4, 38, 60, 0.6);
 }
 
+html[dir=rtl] .groupItem {
+  box-shadow:
+    0 1px 0 #FFFFFF inset,
+    0 -1px 1px rgba(255, 255, 255, 0.8) inset,
+    -1px 0 1px rgba(255, 255, 255, 0.8) inset,
+    1px 0 1px rgba(255, 255, 255, 0.8) inset,
+    0 1px 3px rgba(4, 38, 60, 0.6);
+}
+
 .groupItem.activeGroupItem {
   box-shadow:
     rgba(0,0,0,0.6) 1px 1px 5.5px;
 }
 
-.phantom {
+html[dir=rtl] .groupItem.activeGroupItem {
+  box-shadow:
+    rgba(0,0,0,0.6) -1px 1px 5.5px;
 }
 
 .overlay {
   background-color: rgba(0,0,0,.7) !important;
   box-shadow: 3px 3px 5.5px rgba(0,0,0,.5);
   border-radius: 0.4em;
-  /*
-  border: 1px solid rgba(230,230,230,1);
-  background-color: rgba(248,248,248,1);
-  box-shadow:
-    rgba(0,0,0, .3) 2px 2px 5.5px,
-    inset rgba(255, 255, 255, 0.6) 0 0 0 2px; */
+}
+
+html[dir=rtl] .overlay {
+  box-shadow: -3px 3px 5.5px rgba(0,0,0,.5);
 }
 
 .appTabTray {
   top: 34px;
   right: 1px;
 }
 
+html[dir=rtl] .appTabTray {
+  right: auto;
+  left: 1px;
+}
+
 .appTabIcon {
   width: 16px;
   height: 16px;
   cursor: pointer;
 }
 
 .undo {
   background-color: #A0A0A0;
@@ -223,16 +293,21 @@ body {
 }
 
 .undo .close {
   top: 4px;
   left: 4px;
   opacity: 0.5;
 }
 
+html[dir=rtl] .undo .close {
+  left: auto;
+  right: 4px;
+}
+
 .undo .close:hover{
   opacity: 1.0;
 }
 
 /* InfoItems
 ----------------------------------*/
 
 .info-item {
@@ -240,31 +315,41 @@ body {
   border: 1px solid rgba(230,230,230,1);
   background-color: rgba(248,248,248,1);
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0, .2) 1px 1px 3px;
 }
 
+.info-item {
+  box-shadow:
+    inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
+    rgba(0,0,0, .2) -1px 1px 3px;
+}
+
 .intro {
   margin: 10px;
 }
 
 /* Trenches
 ----------------------------------*/
 
 .guideTrench {
   opacity: 0.9;
   border: 1px dashed  rgba(0,0,0,.12);
   border-bottom: none;
-  border-right: none;
+  -moz-border-end: none;
   box-shadow: 1px 1px 0 rgba(255,255,255,.15);
 }
 
+html[dir=rtl] .guideTrench {
+  box-shadow: -1px 1px 0 rgba(255,255,255,.15);
+}
+
 .visibleTrench {
   opacity: 0.05;
 }
 
 .activeVisibleTrench {
   opacity: 0;
 }
 
@@ -290,42 +375,62 @@ body {
   height: 15px;
   bottom: 10px;
   left: 10px;
   cursor: pointer;
   opacity: .3;
   background-image: url(chrome://browser/skin/tabview/new-tab.png);
 }
 
+html[dir=rtl] .newTabButton {
+  left: auto;
+  right: 10px;
+}
+
 .newTabButton:hover {
   opacity: 1;
 }
 
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
+html[dir=rtl] .active {
+  box-shadow: -5px 5px 3px rgba(0,0,0,.5);
+}
+
 .acceptsDrop {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
+html[dir=rtl] .acceptsDrop {
+  box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
+}
+
 .titlebar {
   font-size: 12px;
   line-height: 18px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: #999;
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-start: 3px;
   padding: 1px;
   background-image: url(chrome://browser/skin/tabview/edit-light.png);
-  padding-left: 20px;
+  -moz-padding-start: 20px;
+}
+
+html[dir=rtl] input.name {
+  background-position: right top;
 }
 
 .title-container:hover input.name {
   border: 1px solid #ddd;
 }
 
 .title-container:hover input.name-locked {
   border: 1px solid transparent !important;
@@ -346,24 +451,32 @@ input.defaultName {
   color: #CCC;
 }
 
 .title-container {
   cursor: text;
 }
 
 .title-shield {
-  margin: 3px 0px 0px 3px;
+  margin-top: 3px;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-start: 3px;
   padding: 1px;
   left: 0;
   top: 0;
   width: 100%;
   height: 100%;
 }
 
+html[dir=rtl] .title-shield {
+  left: auto;
+  right: 0;
+}
+
 .transparentBorder {
   border: 1px solid transparent !important;
 }
 
 .stackExpander {
   opacity: .4;
   cursor: pointer;
   background-image: url(chrome://browser/skin/tabview/stack-expander.png);
@@ -381,43 +494,61 @@ input.defaultName {
   background-image: url(chrome://global/skin/icons/resizer.png);
   width: 16px;
   height: 16px;
   bottom: 0px;
   right: 0px;
   opacity: .2;
 }
 
+html[dir=rtl] .resizer {
+  right: auto;
+  left: 0;
+  -moz-transform: scaleX(-1);
+}
+
 .iq-resizable-handle {
   font-size: 0.1px;
 }
 
 .iq-resizable-se {
   cursor: se-resize;
   width: 12px;
   height: 12px;
   right: 1px;
   bottom: 1px;
 }
 
+html[dir=rtl] .iq-resizable-se {
+  cursor: sw-resize;
+  right: auto;
+  left: 1px;
+}
+
 /* Exit button
 +----------------------------------*/
 #exit-button {
   cursor: default;
   top: 0;
   right: 0;
   width: 28px;
   height: 27px;
   background: -moz-image-rect(url(chrome://browser/skin/tabview/tabview.png), 0, 18, 18, 0) no-repeat scroll 4px 4px #b7b7b7;
   border-bottom: 1px solid #909090;
-  border-left: 1px solid #B7B7B7;
+  -moz-border-start: 1px solid #B7B7B7;
   border-top: 1px solid #CFCFCF;
   border-radius: 3px 0 0 3px;
 }
 
+html[dir=rtl] #exit-button {
+  right: auto;
+  left: 0;
+  border-radius: 0 3px 3px 0;
+}
+
 /* Search
 ----------------------------------*/
 
 #search{
   background-color: rgba(0,0,0,.42);
   width: 100%;
   height: 100%;  
 }
@@ -425,32 +556,42 @@ input.defaultName {
 #searchbox{
   width: 270px;
   height: 30px;
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,1), 0px 0px 9px rgba(0,0,0,.8);
   color: white;
   border: none;
   background-color: #272727;
   border-radius: 0.4em;
-  padding-left:5px; padding-right: 5px;
+  -moz-padding-start: 5px;
+  -moz-padding-end: 5px;
   font-size: 14px;  
 }
 
 #actions{
   width: 30px;
   height: 30px;
   background-color: #CFDBE8;
   border: none;
-  border-bottom-left-radius: 0.4em;
-  border-top-left-radius: 0.4em;    
   box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset 6px 6px 9px rgba(0,0,0,.56);
   opacity: .64;
   text-align: center;
 }
 
+html[dir=ltr] #actions {
+  border-bottom-left-radius: 0.4em;
+  border-top-left-radius: 0.4em;
+}
+
+html[dir=rtl] #actions {
+  border-bottom-right-radius: 0.4em;
+  border-top-right-radius: 0.4em;
+  box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.8), inset -6px 6px 9px rgba(0,0,0,.56);
+}
+
 #actions #searchbutton{
   background: transparent url(chrome://browser/skin/tabview/search.png) no-repeat;
   border: none;
   width: 20px;
   height: 20px;
   margin-top:5px;
   opacity: .8;  
 }
@@ -467,41 +608,46 @@ input.defaultName {
   left: 0px;
   bottom: 0px;
   width: 100%;
   height: 30px;
   background-color: rgba(0,0,0,.3);
   box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
 }
 
+html[dir=rtl] #otherresults {
+  left: auto;
+  right: 0;
+}
+
 #otherresults .label {
   color: #999;
   line-height: 30px;
-  margin-left: 5px;
-  margin-right: 5px;
+  -moz-margin-start: 5px;
+  -moz-margin-end: 5px;
 }
 
 .inlineMatch {
   background-color: #EBEBEB;
   border-radius: 0.4em;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
   border: 1px solid rgba(255, 255, 255, 0.5);
-  padding-left: 3px;
-  padding-right: 3px;
+  -moz-padding-start: 3px;
+  -moz-padding-end: 3px;
   height: 20px;
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   cursor: pointer;
 }
 
 .inlineMatch:hover {
   opacity: 1.0;
 }
 
 .inlineMatch > img {
-  margin-right: 5px;
+  -moz-margin-end: 5px;
   position: relative;
   top: 2px;
 }
 
 .inlineMatch > span {
   max-width: 200px;
   height: 15px;
 }
new file mode 100644
--- /dev/null
+++ b/build/unix/gnu-ld-scripts/jemalloc-standalone-linkage-version-script
@@ -0,0 +1,19 @@
+{
+   global:
+		_malloc_postfork;
+		_malloc_prefork;
+		jemalloc_stats;
+		malloc_usable_size;
+		posix_memalign;
+		free;
+		realloc;
+		calloc;
+		malloc;
+		memalign;
+		valloc;
+		__free_hook;
+		__malloc_hook;
+		__realloc_hook;
+		__memalign_hook;
+   local: *;
+};
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -166,16 +166,17 @@ 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@
 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_JAVAXPCOM = @MOZ_JAVAXPCOM@
 JAVA_INCLUDE_PATH="@JAVA_INCLUDE_PATH@"
@@ -190,16 +191,17 @@ MAKENSISU=@MAKENSISU@
 RM = rm -f
 
 # The MOZ_UI_LOCALE var is used to build a particular locale. Do *not*
 # use the var to change any binary files. Do *not* use this var unless you
 # write rules for the "clean-locale" and "locale" targets.
 MOZ_UI_LOCALE = @MOZ_UI_LOCALE@
 
 MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@
+MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS = @MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS@
 MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@
 
 MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@
 
 XPCOM_FROZEN_LDOPTS=@XPCOM_FROZEN_LDOPTS@
 XPCOM_LIBS=@XPCOM_LIBS@
 LIBXUL_LIBS=@LIBXUL_LIBS@
 MOZ_TIMELINE=@MOZ_TIMELINE@
--- a/config/config.mk
+++ b/config/config.mk
@@ -157,16 +157,21 @@ FINAL_LINK_COMPS = $(DEPTH)/config/final
 FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
 ifdef MOZ_MEMORY
 ifneq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
 JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(call EXPAND_MOZLIBNAME,jemalloc) $(MKSHLIB_UNFORCE_ALL)
+# If we are linking jemalloc into a program, we want the jemalloc symbols
+# to be exported
+ifneq (,$(SIMPLE_PROGRAMS)$(PROGRAM))
+JEMALLOC_LIBS += $(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
+endif
 endif
 endif
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 
 # determine debug-related options
 _DEBUG_CFLAGS :=
--- a/config/system-headers
+++ b/config/system-headers
@@ -547,29 +547,26 @@ OpenTptInternet.h
 OpenTransport.h
 os2.h
 OS.h
 osreldate.h
 OSUtils.h
 Packages.h
 Palettes.h
 PALM_CMN.H
-pango-engine.h
-pango-glyph.h
-pango-modules.h
+pango/pango-modules.h
 pango/pangocairo.h
 pango/pangofc-decoder.h
 pango/pangofc-font.h
 pango/pangofc-fontmap.h
 pango/pango-break.h
 pango/pango-fontmap.h
 pango/pango.h
 pango/pangoxft.h
 pango/pango-utils.h
-pango-types.h
 pascal.h
 Patches.h
 Path.h
 pcfs/pc_dir.h
 Pgenerr.h
 PGenErr.h
 Ph.h
 photon/Pg.h
--- a/configure.in
+++ b/configure.in
@@ -2888,21 +2888,23 @@ case "$target" in
     if test -z "$GNU_CC"; then
         NO_LD_ARCHIVE_FLAGS=
     fi
     ;;
 esac
 AC_SUBST(NO_LD_ARCHIVE_FLAGS)
 
 dnl ========================================================
-dnl = Flags to strip unused symbols from .so components
+dnl = Flags to strip unused symbols from .so components and
+dnl = to export jemalloc symbols when linking a program
 dnl ========================================================
 case "$target" in
     *-linux*|*-kfreebsd*-gnu|*-gnu*)
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
+        MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS='-rdynamic -Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/jemalloc-standalone-linkage-version-script'
         ;;
     *-solaris*)
         if test -z "$GNU_CC"; then
          MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
         else
          if test -z "$GCC_USE_GNU_LD"; then
           MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,-M -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
          else
@@ -4987,16 +4989,17 @@ MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_USE_NATIVE_UCONV=
 MOZ_VIEW_SOURCE=1
 MOZ_XSLT_STANDALONE=
 MOZ_XTF=1
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
+MOZ_PDF_PRINTING=
 MOZ_DISABLE_DOMCRYPTO=
 NSS_DISABLE_DBM=
 NECKO_WIFI=1
 NECKO_COOKIES=1
 NECKO_DISK_CACHE=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource wyciwyg"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
@@ -5026,17 +5029,16 @@ case "$target_os" in
         ;;
 esac
 
 case "${target}" in
     arm-android-eabi)
         NSS_DISABLE_DBM=1
         USE_ARM_KUSER=1
         MOZ_INSTALLER=
-        NS_PRINTING=
         NECKO_WIFI=
         MOZ_THUMB2=1
         MOZ_THEME_FASTSTRIPE=1
         MOZ_TREE_FREETYPE=1
         MOZ_MEMORY=1
         ;;
 esac
 
@@ -5182,32 +5184,34 @@ photon)
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
     MOZ_WEBGL=1
     case "${target}" in
     *-wince*)
         NS_PRINTING=
         ;;
     esac
+    MOZ_PDF_PRINTING=1
     ;;
 
 cairo-gtk2|cairo-gtk2-x11)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
     MOZ_ENABLE_XREMOTE=1
     MOZ_WEBGL=1
     MOZ_WEBGL_GLX=1
 
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
+    MOZ_PDF_PRINTING=1
     ;;
 
 cairo-gtk2-dfb)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
     MOZ_WEBGL=
 
     AC_DEFINE(MOZ_DFB)
@@ -5215,16 +5219,17 @@ cairo-gtk2-dfb)
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     if test "$no_x" != "yes"; then
         AC_MSG_WARN([Disabling X when DirectFB is specified.])
         no_x=yes
     fi
+    MOZ_PDF_PRINTING=1
     ;;
 
 cairo-qt)
     MOZ_WIDGET_TOOLKIT=qt
     MOZ_ENABLE_QT=1
     MOZ_ENABLE_XREMOTE=1
     MOZ_WEBGL=1
     MOZ_WEBGL_GLX=1
@@ -5232,30 +5237,32 @@ cairo-qt)
 
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
 
     TK_CFLAGS='$(MOZ_QT_CFLAGS)'
     TK_LIBS='$(MOZ_QT_LIBS)'
     AC_DEFINE(MOZ_WIDGET_QT)
+    MOZ_PDF_PRINTING=1
     ;;
 
 cairo-beos)
     MOZ_WIDGET_TOOLKIT=beos
     USE_FC_FREETYPE=1
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     ;;
 
 cairo-os2)
     MOZ_WIDGET_TOOLKIT=os2
     USE_FC_FREETYPE=1
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
+    MOZ_PDF_PRINTING=1
     ;;
 
 cairo-cocoa)
     MOZ_WIDGET_TOOLKIT=cocoa
     AC_DEFINE(MOZ_WIDGET_COCOA)
     MOZ_USER_DIR="Mozilla"
     AC_DEFINE(XP_MACOSX)
     TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL'
@@ -5266,21 +5273,30 @@ cairo-cocoa)
     LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
     MOZ_FS_LAYOUT=bundle
     MOZ_WEBGL=1
     ;;
 
 cairo-android)
     AC_DEFINE(MOZ_WIDGET_ANDROID)
     MOZ_WIDGET_TOOLKIT=android
+    TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
+    TK_LIBS='$(MOZ_CAIRO_LIBS)'
     MOZ_WEBGL=1
+    MOZ_PDF_PRINTING=1
     ;;
 
 esac
 
+AC_SUBST(MOZ_PDF_PRINTING)
+if test "$MOZ_PDF_PRINTING"; then
+   PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
+   AC_DEFINE(MOZ_PDF_PRINTING)
+fi
+
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_ENABLE_GTK2"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
@@ -5489,34 +5505,34 @@ dnl ====================================
 dnl = Pango
 dnl ========================================================
 if test "$MOZ_ENABLE_GTK2"
 then
     AC_SUBST(MOZ_PANGO)
 
     PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION)
 
-    PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION)
+    PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION)
     AC_SUBST(MOZ_PANGO_CFLAGS)
     AC_SUBST(MOZ_PANGO_LIBS)
     if test "$MOZ_PANGO"
     then
         AC_DEFINE(MOZ_PANGO)
     else
         PKG_CHECK_MODULES(FT2, freetype2 > 6.1.0 fontconfig)
         AC_SUBST(FT2_CFLAGS)
         AC_SUBST(FT2_LIBS)
     fi
 fi
 
 if test "$MOZ_ENABLE_QT"
 then
     if test "$MOZ_PANGO"
     then
-        PKG_CHECK_MODULES(MOZ_PANGO, [pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION],
+        PKG_CHECK_MODULES(MOZ_PANGO, [pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION],
         [
             AC_SUBST(MOZ_PANGO_CFLAGS)
             AC_SUBST(MOZ_PANGO_LIBS)
             AC_DEFINE(MOZ_PANGO)
         ],
         [
             echo "Pango library not found, will use FT2 font engine"
             MOZ_PANGO=
@@ -6100,17 +6116,17 @@ if test -n "$MOZ_WEBM" -a -z "$MOZ_NATIV
     ;;
     *:arm*)
       if test -n "$GNU_AS" ; then
         VPX_AS=$AS
         dnl These flags are a lie; they're just used to enable the requisite
         dnl opcodes; actual arch detection is done at runtime.
         VPX_ASFLAGS="-march=armv7-a -mfpu=neon"
         VPX_DASH_C_FLAG="-c"
-        VPX_AS_CONVERSION="$PERL ${srcdir}/media/libvpx/build/make/ads2gas.pl"
+        VPX_AS_CONVERSION='$(PERL) $(topsrcdir)/media/libvpx/build/make/ads2gas.pl'
         VPX_ASM_SUFFIX="$ASM_SUFFIX"
         VPX_ARM_ASM=1
       fi
     esac
 
     if test -n "$COMPILE_ENVIRONMENT" -a -n "$VPX_X86_ASM" -a -z "$VPX_AS"; then
       AC_MSG_ERROR([yasm is a required build tool for this architecture when webm is enabled. You may either install yasm or --disable-webm (which disables the WebM video format). See https://developer.mozilla.org/en/YASM for more details.])
     fi
@@ -6509,24 +6525,27 @@ fi
 dnl ========================================================
 dnl Build Freetype in the tree
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(tree-freetype,
 [  --enable-tree-freetype  Enable Tree FreeType],
     MOZ_TREE_FREETYPE=1,
     MOZ_TREE_FREETYPE= )
 if test -n "$MOZ_TREE_FREETYPE"; then
+   if test -n "$_WIN32_MSVC"; then
+      AC_ERROR("building with in-tree freetype is not supported on MSVC")
+   fi
    AC_DEFINE(MOZ_TREE_FREETYPE)
    AC_SUBST(MOZ_TREE_FREETYPE)
    MOZ_ENABLE_CAIRO_FT=1       
    FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
    FT2_CFLAGS='-I$(topsrcdir)/modules/freetype2/include'
    CAIRO_FT_CFLAGS='-I$(topsrcdir)/modules/freetype2/include'
-   FT2_LIBS='$(call EXPAND_LIBNAME_PATH,freetype2,$(LIBXUL_DIST)/lib)'
-   CAIRO_FT_LIBS='$(call EXPAND_LIBNAME_PATH,freetype2,$(LIBXUL_DIST)/lib)'
+   FT2_LIBS='$(call EXPAND_LIBNAME_PATH,freetype,$(DEPTH)/modules/freetype2/.libs)'
+   CAIRO_FT_LIBS='$(call EXPAND_LIBNAME_PATH,freetype,$(DEPTH)/modules/freetype2/.libs)'
    AC_DEFINE(HAVE_FT_BITMAP_SIZE_Y_PPEM)
    AC_DEFINE(HAVE_FT_GLYPHSLOT_EMBOLDEN)
    AC_DEFINE(HAVE_FT_LOAD_SFNT_TABLE)
    AC_SUBST(CAIRO_FT_CFLAGS)
 fi
 
 
 dnl ========================================================
@@ -8491,17 +8510,16 @@ if test "$MOZ_TREE_CAIRO"; then
     # one of the above headers or mozstdint.h.
     AC_DEFINE(HAVE_UINT64_T)
 
     # Define macros for cairo-features.h
     if test "$MOZ_X11"; then
         XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
         XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
         PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
-        PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="$FT2_CFLAGS"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "qt"; then
         QT_SURFACE_FEATURE="#define CAIRO_HAS_QT_SURFACE 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
@@ -8530,22 +8548,20 @@ if test "$MOZ_TREE_CAIRO"; then
 
         AC_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1)
 
         dnl D3D10 Layers depend on D2D Surfaces.
         if test -n "$WIN32_D2D_SURFACE_FEATURE"; then
           AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
         fi
 
-        PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
         OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
-        PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="-I${MZFTCFGFT2}/include"
         CAIRO_FT_LIBS="-L${MZFTCFGFT2}/lib -lmozft -lmzfntcfg"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "beos"; then
         PKG_CHECK_MODULES(CAIRO_FT, fontconfig freetype2)
         BEOS_SURFACE_FEATURE="#define CAIRO_HAS_BEOS_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
@@ -8916,16 +8932,17 @@ AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
 AC_SUBST(MOZ_UPDATER)
 
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(USE_ELF_DYNSTR_GC)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
+AC_SUBST(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
 AC_SUBST(MOZ_COMPONENT_NSPR_LIBS)
 
 AC_SUBST(MOZ_FIX_LINK_PATHS)
 AC_SUBST(XPCOM_LIBS)
 AC_SUBST(XPCOM_FROZEN_LDOPTS)
 AC_SUBST(XPCOM_GLUE_LDOPTS)
 AC_SUBST(XPCOM_STANDALONE_GLUE_LDOPTS)
 
@@ -9363,16 +9380,28 @@ if test "$CAIRO_FEATURES_H"; then
   if cmp -s $CAIRO_FEATURES_H "$CAIRO_FEATURES_H".orig; then
     echo "$CAIRO_FEATURES_H is unchanged"
     mv -f "$CAIRO_FEATURES_H".orig "$CAIRO_FEATURES_H" 2> /dev/null
   else
     rm -f "$CAIRO_FEATURES_H".orig 2> /dev/null
   fi
 fi
 
+# Run freetype configure script
+
+if test "$MOZ_TREE_FREETYPE"; then
+   export CFLAGS="$CFLAGS -std=c99"
+   export CPPFLAGS="$CPPFLAGS"
+   export CXXFLAGS="$CXXFLAGS"
+   export LDFLAGS="$LDFLAGS"
+   export CONFIG_FILES="unix-cc.mk:unix-cc.in unix-def.mk:unix-def.in freetype-config freetype2.pc:freetype2.in"
+   ac_configure_args="$ac_configure_args --host=$target --disable-shared --with-pic=yes"
+   AC_OUTPUT_SUBDIRS(modules/freetype2)
+fi
+
 dnl ========================================================
 dnl = Setup a nice relatively clean build environment for
 dnl = sub-configures.
 dnl ========================================================
 CC="$_SUBDIR_CC" 
 CXX="$_SUBDIR_CXX" 
 CFLAGS="$_SUBDIR_CFLAGS" 
 CPPFLAGS="$_SUBDIR_CPPFLAGS"
--- a/content/base/public/nsIScriptElement.h
+++ b/content/base/public/nsIScriptElement.h
@@ -41,33 +41,37 @@
 
 #include "nsISupports.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptLoaderObserver.h"
 #include "nsWeakPtr.h"
 #include "nsIParser.h"
 #include "nsContentCreatorFunctions.h"
+#include "nsIDOMHTMLScriptElement.h"
 
 #define NS_ISCRIPTELEMENT_IID \
 { 0x6d625b30, 0xfac4, 0x11de, \
 { 0x8a, 0x39, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
 
 /**
  * Internal interface implemented by script elements
  */
 class nsIScriptElement : public nsIScriptLoaderObserver {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
 
   nsIScriptElement(mozilla::dom::FromParser aFromParser)
     : mLineNumber(0),
       mAlreadyStarted(PR_FALSE),
       mMalformed(PR_FALSE),
-      mDoneAddingChildren(PR_TRUE),
+      mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
+                          aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
+      mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
+                  aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
       mFrozen(PR_FALSE),
       mDefer(PR_FALSE),
       mAsync(PR_FALSE),
       mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ?
                      mozilla::dom::NOT_FROM_PARSER : aFromParser),
                      // Fragment parser-created scripts (if executable)
                      // behave like script-created scripts.
       mCreatorParser(nsnull)
@@ -154,16 +158,22 @@ public:
   }
 
   void LoseParserInsertedness()
   {
     mFrozen = PR_FALSE;
     mUri = nsnull;
     mCreatorParser = nsnull;
     mParserCreated = mozilla::dom::NOT_FROM_PARSER;
+    PRBool async = PR_FALSE;
+    nsCOMPtr<nsIDOMHTMLScriptElement> htmlScript = do_QueryInterface(this);
+    if (htmlScript) {
+      htmlScript->GetAsync(&async);
+    }
+    mForceAsync = !async;
   }
 
   void SetCreatorParser(nsIParser* aParser)
   {
     mCreatorParser = getter_AddRefs(NS_GetWeakReference(aParser));
   }
 
   /**
@@ -214,16 +224,22 @@ protected:
   PRPackedBool mMalformed;
   
   /**
    * False if parser-inserted but the parser hasn't triggered running yet.
    */
   PRPackedBool mDoneAddingChildren;
 
   /**
+   * If true, the .async property returns true instead of reflecting the
+   * content attribute.
+   */
+  PRPackedBool mForceAsync;
+
+  /**
    * Whether src, defer and async are frozen.
    */
   PRPackedBool mFrozen;
   
   /**
    * The effective deferredness.
    */
   PRPackedBool mDefer;
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1068,21 +1068,17 @@ nsAttrValue::ParseSpecialIntValue(const 
 
   if (NS_FAILED(ec)) {
     return PR_FALSE;
   }
 
   PRInt32 val = NS_MAX(originalVal, 0);
 
   // % (percent)
-  // XXX RFindChar means that 5%x will be parsed!
   if (aCanBePercent && (isPercent || tmp.RFindChar('%') >= 0)) {
-    if (val > 100) {
-      val = 100;
-    }
     isPercent = PR_TRUE;
   }
 
   strict = strict && (originalVal == val);
 
   SetIntValueAndType(val,
                      isPercent ? ePercent : eInteger,
                      strict ? nsnull : &aString);
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -226,16 +226,18 @@ public:
   /**
    * Parse a string into an integer. Can optionally parse percent (n%).
    * This method explicitly sets a lower bound of zero on the element,
    * whether it be percent or raw integer.
    *
    * @param aString the string to parse
    * @param aCanBePercent PR_TRUE if it can be a percent value (%)
    * @return whether the value could be parsed
+   *
+   * @see http://www.whatwg.org/html/#rules-for-parsing-dimension-values
    */
   PRBool ParseSpecialIntValue(const nsAString& aString,
                               PRBool aCanBePercent);
 
 
   /**
    * Parse a string value into an integer.
    *
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -178,16 +178,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsLayoutStatics.h"
 #include "nsLayoutUtils.h"
 #include "nsFrameManager.h"
 #include "BasicLayers.h"
 #include "nsFocusManager.h"
 #include "nsTextEditorState.h"
 #include "nsIPluginHost.h"
 #include "nsICategoryManager.h"
+#include "nsAHtml5FragmentParser.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -3893,31 +3894,37 @@ nsContentUtils::CreateContextualFragment
     if (contextAsContent && !contextAsContent->IsElement()) {
       contextAsContent = contextAsContent->GetParent();
       if (contextAsContent && !contextAsContent->IsElement()) {
         // can this even happen?
         contextAsContent = nsnull;
       }
     }
     
+    nsAHtml5FragmentParser* asFragmentParser =
+        static_cast<nsAHtml5FragmentParser*> (parser.get());
     nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
     if (contextAsContent &&
         !(nsGkAtoms::html == contextAsContent->Tag() &&
           contextAsContent->IsHTML())) {
-      parser->ParseFragment(aFragment, 
-                            fragment, 
-                            contextAsContent->Tag(), 
-                            contextAsContent->GetNameSpaceID(), 
-                            (document->GetCompatibilityMode() == eCompatibility_NavQuirks));    
+      asFragmentParser->ParseHtml5Fragment(aFragment,
+                                           fragment,
+                                           contextAsContent->Tag(),
+                                           contextAsContent->GetNameSpaceID(),
+                                           (document->GetCompatibilityMode() ==
+                                               eCompatibility_NavQuirks),
+                                           PR_FALSE);
     } else {
-      parser->ParseFragment(aFragment, 
-                            fragment,
-                            nsGkAtoms::body, 
-                            kNameSpaceID_XHTML, 
-                            (document->GetCompatibilityMode() == eCompatibility_NavQuirks));
+      asFragmentParser->ParseHtml5Fragment(aFragment,
+                                           fragment,
+                                           nsGkAtoms::body,
+                                           kNameSpaceID_XHTML,
+                                           (document->GetCompatibilityMode() ==
+                                               eCompatibility_NavQuirks),
+                                           PR_FALSE);
     }
   
     frag.swap(*aReturn);
     document->SetFragmentParser(parser);
     return NS_OK;
   }
 
   nsAutoTArray<nsString, 32> tagStack;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -794,16 +794,17 @@ GK_ATOM(preload, "preload")
 GK_ATOM(preserve, "preserve")
 GK_ATOM(preserveSpace, "preserve-space")
 GK_ATOM(preventdefault, "preventdefault")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
+GK_ATOM(progress, "progress")
 GK_ATOM(progressmeter, "progressmeter")
 GK_ATOM(progressNormal, "progressNormal")
 GK_ATOM(progressUndetermined, "progressUndetermined")
 GK_ATOM(projection, "projection")
 GK_ATOM(prompt, "prompt")
 GK_ATOM(propagate, "propagate")
 GK_ATOM(properties, "properties")
 GK_ATOM(property, "property")
@@ -1699,17 +1700,16 @@ GK_ATOM(onseeking, "onseeking")
 GK_ATOM(onseeked, "onseeked")
 GK_ATOM(ontimeupdate, "ontimeupdate")
 GK_ATOM(onended, "onended")
 GK_ATOM(onratechange, "onratechange")
 GK_ATOM(ondurationchange, "ondurationchange")
 GK_ATOM(onvolumechange, "onvolumechange")
 GK_ATOM(onMozAudioAvailable, "onMozAudioAvailable")
 GK_ATOM(loadstart, "loadstart")
-GK_ATOM(progress, "progress")
 GK_ATOM(suspend, "suspend")
 GK_ATOM(emptied, "emptied")
 GK_ATOM(stalled, "stalled")
 GK_ATOM(play, "play")
 GK_ATOM(pause, "pause")
 GK_ATOM(loadedmetadata, "loadedmetadata")
 GK_ATOM(loadeddata, "loadeddata")
 GK_ATOM(waiting, "waiting")
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -63,29 +63,67 @@
 #include "nsEscape.h"
 #include "nsITextToSubURI.h"
 #include "nsCRT.h"
 #include "nsIParserService.h"
 #include "nsContentUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsIScriptElement.h"
 #include "nsAttrName.h"
+#include "nsIDocShell.h"
+#include "nsIEditorDocShell.h"
+#include "nsIEditor.h"
+#include "nsIHTMLEditor_MOZILLA_2_0_BRANCH.h"
 
 static const PRInt32 kLongLineLen = 128;
 
 nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsHTMLContentSerializer* it = new nsHTMLContentSerializer();
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return CallQueryInterface(it, aSerializer);
 }
 
+static
+PRBool
+IsInvisibleBreak(nsIContent *aNode, nsIAtom *aTag) {
+  // xxxehsan: we should probably figure out a way to determine
+  // if a BR node is visible without using the editor.
+  if (aTag != nsGkAtoms::br || !aNode->IsEditable()) {
+    return PR_FALSE;
+  }
+
+  // Grab the editor associated with the document
+  nsIDocument *doc = aNode->GetCurrentDoc();
+  if (doc) {
+    nsPIDOMWindow *window = doc->GetWindow();
+    if (window) {
+      nsIDocShell *docShell = window->GetDocShell();
+      if (docShell) {
+        nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
+        if (editorDocShell) {
+          nsCOMPtr<nsIEditor> editor;
+          editorDocShell->GetEditor(getter_AddRefs(editor));
+          nsCOMPtr<nsIHTMLEditor_MOZILLA_2_0_BRANCH> htmlEditor = do_QueryInterface(editor);
+          if (htmlEditor) {
+            PRBool isVisible = PR_FALSE;
+            nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
+            htmlEditor->BreakIsVisible(domNode, &isVisible);
+            return !isVisible;
+          }
+        }
+      }
+    }
+  }
+  return PR_FALSE;
+}
+
 nsHTMLContentSerializer::nsHTMLContentSerializer()
 {
     mIsHTMLSerializer = PR_TRUE;
 }
 
 nsHTMLContentSerializer::~nsHTMLContentSerializer()
 {
 }
@@ -199,16 +237,22 @@ nsHTMLContentSerializer::AppendElementSt
   nsIContent* content = aElement;
 
   PRBool forceFormat = PR_FALSE;
   if (!CheckElementStart(content, forceFormat, aStr)) {
     return NS_OK;
   }
 
   nsIAtom *name = content->Tag();
+
+  if ((mFlags & nsIDocumentEncoder::OutputPreformatted) &&
+      IsInvisibleBreak(content, name)) {
+    return NS_OK;
+  }
+
   PRBool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
 
   if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
     if (mColPos && lineBreakBeforeOpen) {
       AppendNewLineToString(aStr);
     }
     else {
       MaybeAddNewlineForRootNode(aStr);
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -275,34 +275,18 @@ nsInProcessTabChildGlobal::InitTabChildG
   JSContext* cx = JS_NewContext(rt, 8192);
   NS_ENSURE_STATE(cx);
 
   mCx = cx;
 
   nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
   nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
-  PRUint32 stackDummy;
-  jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
-
-  // 256k stack space.
-  const jsuword kStackSize = 0x40000;
-
-#if JS_STACK_GROWTH_DIRECTION < 0
-  stackLimit = (currentStackAddr > kStackSize) ?
-               currentStackAddr - kStackSize :
-               0;
-#else
-  stackLimit = (currentStackAddr + kStackSize > currentStackAddr) ?
-               currentStackAddr + kStackSize :
-               (jsuword) -1;
-#endif
-
-  JS_SetThreadStackLimit(cx, stackLimit);
-  JS_SetScriptStackQuota(cx, 100*1024*1024);
+  JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
+  JS_SetScriptStackQuota(cx, 25 * sizeof(size_t) * 1024 * 1024);
 
   JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_ANONFUNFIX | JSOPTION_PRIVATE_IS_NSISUPPORTS);
   JS_SetVersion(cx, JSVERSION_LATEST);
 
   JSAutoRequest ar(cx);
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
                          /*nsIXPConnect::OMIT_COMPONENTS_OBJECT ?  |*/
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -273,18 +273,17 @@ nsNodeUtils::LastRelease(nsINode* aNode)
       }
     }
 
     // I wonder whether it's faster to do the HasFlag check first....
     if (aNode->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) &&
         aNode->HasFlag(ADDED_TO_FORM)) {
       // Tell the form (if any) this node is going away.  Don't
       // notify, since we're being destroyed in any case.
-      static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(PR_TRUE,
-                                                               PR_FALSE);
+      static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(PR_TRUE);
     }
   }
   aNode->UnsetFlags(NODE_HAS_PROPERTIES);
 
   if (aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
 #ifdef DEBUG
     if (nsContentUtils::IsInitialized()) {
       nsIEventListenerManager* manager =
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -164,16 +164,20 @@ nsScriptLoader::~nsScriptLoader()
   for (PRUint32 i = 0; i < mDeferRequests.Length(); i++) {
     mDeferRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
   }
 
   for (PRUint32 i = 0; i < mAsyncRequests.Length(); i++) {
     mAsyncRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
   }
 
+  for (PRUint32 i = 0; i < mNonAsyncExternalScriptInsertedRequests.Length(); i++) {
+    mNonAsyncExternalScriptInsertedRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
+  }
+
   // Unblock the kids, in case any of them moved to a different document
   // subtree in the meantime and therefore aren't actually going away.
   for (PRUint32 j = 0; j < mPendingChildLoaders.Length(); ++j) {
     mPendingChildLoaders[j]->RemoveExecuteBlocker();
   }  
 }
 
 NS_IMPL_ISUPPORTS1(nsScriptLoader, nsIStreamLoaderObserver)
@@ -566,41 +570,52 @@ nsScriptLoader::ProcessScriptElement(nsI
       request->mIsInline = PR_FALSE;
       request->mLoading = PR_TRUE;
       rv = StartLoad(request, type);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     request->mJSVersion = version;
 
-    PRBool async = !aElement->GetParserCreated() || aElement->GetScriptAsync();
-
-    // we now have a request that may or may not be still loading
-    if (!async && aElement->GetScriptDeferred()) {
+    if (aElement->GetScriptAsync()) {
+      mAsyncRequests.AppendElement(request);
+      if (!request->mLoading) {
+        // The script is available already. Run it ASAP when the event
+        // loop gets a chance to spin.
+        ProcessPendingRequestsAsync();
+      }
+      return NS_OK;
+    }
+    if (!aElement->GetParserCreated()) {
+      // Violate the HTML5 spec in order to make LABjs and the "order" plug-in
+      // for RequireJS work with their Gecko-sniffed code path. See
+      // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
+      mNonAsyncExternalScriptInsertedRequests.AppendElement(request);
+      if (!request->mLoading) {
+        // The script is available already. Run it ASAP when the event
+        // loop gets a chance to spin.
+        ProcessPendingRequestsAsync();
+      }
+      return NS_OK;
+    }
+    // we now have a parser-inserted request that may or may not be still
+    // loading
+    if (aElement->GetScriptDeferred()) {
       // We don't want to run this yet.
       // If we come here, the script is a parser-created script and it has
       // the defer attribute but not the async attribute. Since a
       // a parser-inserted script is being run, we came here by the parser
       // running the script, which means the parser is still alive and the
       // parse is ongoing.
       NS_ASSERTION(mDocument->GetCurrentContentSink() ||
                    aElement->GetParserCreated() == FROM_PARSER_XSLT,
           "Non-XSLT Defer script on a document without an active parser; bug 592366.");
       mDeferRequests.AppendElement(request);
       return NS_OK;
     }
-    if (async) {
-      mAsyncRequests.AppendElement(request);
-      if (!request->mLoading) {
-        // The script is available already. Run it ASAP when the event
-        // loop gets a chance to spin.
-        ProcessPendingRequestsAsync();
-      }
-      return NS_OK;
-    }
 
     if (aElement->GetParserCreated() == FROM_PARSER_XSLT) {
       // Need to maintain order for XSLT-inserted scripts
       NS_ASSERTION(!mParserBlockingRequest,
           "Parser-blocking scripts and XSLT scripts in the same doc!");
       mXSLTRequests.AppendElement(request);
       if (!request->mLoading) {
         // The script is available already. Run it ASAP when the event
@@ -709,61 +724,71 @@ nsScriptLoader::ProcessRequest(nsScriptL
   NS_ENSURE_ARG(aRequest);
   nsAFlatString* script;
   nsAutoString textData;
 
   NS_TIME_FUNCTION;
 
   nsCOMPtr<nsIDocument> doc;
 
+  nsCOMPtr<nsINode> scriptElem = do_QueryInterface(aRequest->mElement);
+
   // If there's no script text, we try to get it from the element
   if (aRequest->mIsInline) {
     // XXX This is inefficient - GetText makes multiple
     // copies.
     aRequest->mElement->GetScriptText(textData);
 
     script = &textData;
   }
   else {
     script = &aRequest->mScriptText;
 
-    nsCOMPtr<nsIContent> eltAsContent = do_QueryInterface(aRequest->mElement);
-    NS_ASSERTION(eltAsContent, "Script should QI to nsIContent.");
-    doc = eltAsContent->GetOwnerDoc();
+    doc = scriptElem->GetOwnerDoc();
+  }
+
+  nsCOMPtr<nsIScriptElement> oldParserInsertedScript;
+  PRUint32 parserCreated = aRequest->mElement->GetParserCreated();
+  if (parserCreated) {
+    oldParserInsertedScript = mCurrentParserInsertedScript;
+    mCurrentParserInsertedScript = aRequest->mElement;
   }
 
   FireScriptAvailable(NS_OK, aRequest);
 
-  nsCOMPtr<nsINode> scriptElem = do_QueryInterface(aRequest->mElement);
   PRBool runScript = PR_TRUE;
   nsContentUtils::DispatchTrustedEvent(scriptElem->GetOwnerDoc(),
                                        scriptElem,
                                        NS_LITERAL_STRING("beforescriptexecute"),
                                        PR_TRUE, PR_TRUE, &runScript);
 
   nsresult rv = NS_OK;
   if (runScript) {
-    aRequest->mElement->BeginEvaluating();
     if (doc) {
       doc->BeginEvaluatingExternalScript();
     }
+    aRequest->mElement->BeginEvaluating();
     rv = EvaluateScript(aRequest, *script);
+    aRequest->mElement->EndEvaluating();
     if (doc) {
       doc->EndEvaluatingExternalScript();
     }
-    aRequest->mElement->EndEvaluating();
 
     nsContentUtils::DispatchTrustedEvent(scriptElem->GetOwnerDoc(),
                                          scriptElem,
                                          NS_LITERAL_STRING("afterscriptexecute"),
                                          PR_TRUE, PR_FALSE);
   }
 
   FireScriptEvaluated(rv, aRequest);
 
+  if (parserCreated) {
+    mCurrentParserInsertedScript = oldParserInsertedScript;
+  }
+
   return rv;
 }
 
 void
 nsScriptLoader::FireScriptAvailable(nsresult aResult,
                                     nsScriptLoadRequest* aRequest)
 {
   for (PRInt32 i = 0; i < mObservers.Count(); i++) {
@@ -902,32 +927,44 @@ nsScriptLoader::ProcessPendingRequests()
       request.swap(mAsyncRequests[i]);
       mAsyncRequests.RemoveElementAt(i);
       ProcessRequest(request);
       continue;
     }
     ++i;
   }
 
+  while (mEnabled && !mNonAsyncExternalScriptInsertedRequests.IsEmpty() &&
+         !mNonAsyncExternalScriptInsertedRequests[0]->mLoading) {
+    // Violate the HTML5 spec and execute these in the insertion order in
+    // order to make LABjs and the "order" plug-in for RequireJS work with
+    // their Gecko-sniffed code path. See
+    // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
+    request.swap(mNonAsyncExternalScriptInsertedRequests[0]);
+    mNonAsyncExternalScriptInsertedRequests.RemoveElementAt(0);
+    ProcessRequest(request);
+  }
+
   if (mDocumentParsingDone && mXSLTRequests.IsEmpty()) {
     while (!mDeferRequests.IsEmpty() && !mDeferRequests[0]->mLoading) {
       request.swap(mDeferRequests[0]);
       mDeferRequests.RemoveElementAt(0);
       ProcessRequest(request);
     }
   }
 
   while (!mPendingChildLoaders.IsEmpty() && ReadyToExecuteScripts()) {
     nsRefPtr<nsScriptLoader> child = mPendingChildLoaders[0];
     mPendingChildLoaders.RemoveElementAt(0);
     child->RemoveExecuteBlocker();
   }
 
   if (mDocumentParsingDone && mDocument &&
       !mParserBlockingRequest && mAsyncRequests.IsEmpty() &&
+      mNonAsyncExternalScriptInsertedRequests.IsEmpty() &&
       mXSLTRequests.IsEmpty() && mDeferRequests.IsEmpty()) {
     // No more pending scripts; time to unblock onload.
     // OK to unblock onload synchronously here, since callers must be
     // prepared for the world changing anyway.
     mDocumentParsingDone = PR_FALSE;
     mDocument->UnblockOnload(PR_TRUE);
   }
 }
@@ -1089,16 +1126,17 @@ nsScriptLoader::OnStreamComplete(nsIStre
   NS_ASSERTION(request, "null request in stream complete handler");
   NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
 
   nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
                                      aString);
   if (NS_FAILED(rv)) {
     if (mDeferRequests.RemoveElement(request) ||
         mAsyncRequests.RemoveElement(request) ||
+        mNonAsyncExternalScriptInsertedRequests.RemoveElement(request) ||
         mXSLTRequests.RemoveElement(request)) {
       FireScriptAvailable(rv, request);
     } else if (mParserBlockingRequest == request) {
       mParserBlockingRequest = nsnull;
       // nsContentSink::ScriptAvailable unblocks the parser
       FireScriptAvailable(rv, request);
     } else {
       mPreloads.RemoveElement(request, PreloadRequestComparator());
@@ -1167,16 +1205,17 @@ nsScriptLoader::PrepareLoadedRequest(nsS
   }
 
   // This assertion could fire errorously if we ran out of memory when
   // inserting the request in the array. However it's an unlikely case
   // so if you see this assertion it is likely something else that is
   // wrong, especially if you see it more than once.
   NS_ASSERTION(mDeferRequests.IndexOf(aRequest) >= 0 ||
                mAsyncRequests.IndexOf(aRequest) >= 0 ||
+               mNonAsyncExternalScriptInsertedRequests.IndexOf(aRequest) >= 0 ||
                mXSLTRequests.IndexOf(aRequest) >= 0 ||
                mPreloads.Contains(aRequest, PreloadRequestComparator()) ||
                mParserBlockingRequest,
                "aRequest should be pending!");
 
   // Mark this as loaded
   aRequest->mLoading = PR_FALSE;
 
@@ -1220,16 +1259,17 @@ nsScriptLoader::ParsingComplete(PRBool a
     // Have to check because we apparently get ParsingComplete
     // without BeginDeferringScripts in some cases
     mDocumentParsingDone = PR_TRUE;
   }
   mDeferEnabled = PR_FALSE;
   if (aTerminated) {
     mDeferRequests.Clear();
     mAsyncRequests.Clear();
+    mNonAsyncExternalScriptInsertedRequests.Clear();
     mXSLTRequests.Clear();
     mParserBlockingRequest = nsnull;
   }
 
   // Have to call this even if aTerminated so we'll correctly unblock
   // onload and all.
   ProcessPendingRequests();
 }
--- a/content/base/src/nsScriptLoader.h
+++ b/content/base/src/nsScriptLoader.h
@@ -121,16 +121,21 @@ public:
    * Gets the currently executing script. This is useful if you want to
    * generate a unique key based on the currently executing script.
    */
   nsIScriptElement* GetCurrentScript()
   {
     return mCurrentScript;
   }
 
+  nsIScriptElement* GetCurrentParserInsertedScript()
+  {
+    return mCurrentParserInsertedScript;
+  }
+
   /**
    * Whether the loader is enabled or not.
    * When disabled, processing of new script elements is disabled. 
    * Any call to ProcessScriptElement() will fail with a return code of
    * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
    * currently loading or executing scripts.
    */
   PRBool GetEnabled()
@@ -292,16 +297,17 @@ private:
   nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
                                 nsIStreamLoader* aLoader,
                                 nsresult aStatus,
                                 PRUint32 aStringLen,
                                 const PRUint8* aString);
 
   nsIDocument* mDocument;                   // [WEAK]
   nsCOMArray<nsIScriptLoaderObserver> mObservers;
+  nsTArray<nsRefPtr<nsScriptLoadRequest> > mNonAsyncExternalScriptInsertedRequests;
   nsTArray<nsRefPtr<nsScriptLoadRequest> > mAsyncRequests;
   nsTArray<nsRefPtr<nsScriptLoadRequest> > mDeferRequests;
   nsTArray<nsRefPtr<nsScriptLoadRequest> > mXSLTRequests;
   nsRefPtr<nsScriptLoadRequest> mParserBlockingRequest;
 
   // In mRequests, the additional information here is stored by the element.
   struct PreloadInfo {
     nsRefPtr<nsScriptLoadRequest> mRequest;
@@ -316,16 +322,17 @@ private:
     }
   };
   struct PreloadURIComparator {
     PRBool Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const;
   };
   nsTArray<PreloadInfo> mPreloads;
 
   nsCOMPtr<nsIScriptElement> mCurrentScript;
+  nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
   // XXXbz do we want to cycle-collect these or something?  Not sure.
   nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
   PRUint32 mBlockerCount;
   PRPackedBool mEnabled;
   PRPackedBool mDeferEnabled;
   PRPackedBool mDocumentParsingDone;
 };
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1316,25 +1316,25 @@ nsXMLHttpRequest::GetStatusText(nsACStri
   if (httpChannel) {
     if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
       // Make sure we don't leak status information from denied cross-site
       // requests.
       if (mChannel) {
         nsresult status;
         mChannel->GetStatus(&status);
         if (NS_FAILED(status)) {
-          return NS_ERROR_NOT_AVAILABLE;
+          return NS_OK;
         }
       }
     }
 
-    rv = httpChannel->GetResponseStatusText(aStatusText);
+    httpChannel->GetResponseStatusText(aStatusText);
   }
 
-  return rv;
+  return NS_OK;
 }
 
 /* void abort (); */
 NS_IMETHODIMP
 nsXMLHttpRequest::Abort()
 {
   if (mReadRequest) {
     mReadRequest->Cancel(NS_BINDING_ABORTED);
@@ -1383,33 +1383,31 @@ nsXMLHttpRequest::Abort()
 /* string getAllResponseHeaders (); */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nsnull;
 
   if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
+    *_retval = ToNewCString(EmptyString());
     return NS_OK;
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
 
   if (httpChannel) {
-    nsHeaderVisitor *visitor = new nsHeaderVisitor();
-    if (!visitor)
-      return NS_ERROR_OUT_OF_MEMORY;
-    NS_ADDREF(visitor);
-
+    nsRefPtr<nsHeaderVisitor> visitor = new nsHeaderVisitor();
     nsresult rv = httpChannel->VisitResponseHeaders(visitor);
     if (NS_SUCCEEDED(rv))
       *_retval = ToNewCString(visitor->Headers());
-
-    NS_RELEASE(visitor);
-    return rv;
+  }
+ 
+  if (!*_retval) {
+    *_retval = ToNewCString(EmptyString());
   }
 
   return NS_OK;
 }
 
 /* ACString getResponseHeader (in AUTF8String header); */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
@@ -2760,19 +2758,21 @@ nsXMLHttpRequest::SetRequestHeader(const
   PRBool privileged;
   rv = IsCapabilityEnabled("UniversalBrowserWrite", &privileged);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   if (!privileged) {
     // Check for dangerous headers
     const char *kInvalidHeaders[] = {
-      "accept-charset", "accept-encoding", "connection", "content-length",
-      "content-transfer-encoding", "date", "expect", "host", "keep-alive",
-      "referer", "te", "trailer", "transfer-encoding", "upgrade", "via"
+      "accept-charset", "accept-encoding", "access-control-request-headers",
+      "access-control-request-method", "connection", "content-length",
+      "cookie", "cookie2", "content-transfer-encoding", "date", "expect",
+      "host", "keep-alive", "origin", "referer", "te", "trailer",
+      "transfer-encoding", "upgrade", "user-agent", "via"
     };
     PRUint32 i;
     for (i = 0; i < NS_ARRAY_LENGTH(kInvalidHeaders); ++i) {
       if (header.LowerCaseEqualsASCII(kInvalidHeaders[i])) {
         NS_WARNING("refusing to set request header");
         return NS_OK;
       }
     }
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -73,17 +73,17 @@ include $(topsrcdir)/config/rules.mk
 		file_bug218236_multipart.txt^headers^ \
 		test_bug218277.html \
 		test_bug238409.html \
 		test_bug254337.html \
 		test_bug276037-1.html \
 		test_bug276037-2.xhtml \
 		test_bug298064.html \
 		bug298064-subframe.html \
-		test_bug308484.html \
+		test_xhr_forbidden_headers.html \
 		test_bug311681.xml \
 		test_bug322317.html \
 		test_bug330925.xhtml \
 		test_bug333673.html \
 		test_bug337631.html \
 		test_bug338541.xhtml \
 		test_bug338679.html \
 		test_bug339494.html \
@@ -420,30 +420,34 @@ include $(topsrcdir)/config/rules.mk
 		test_x-frame-options.html \
 		file_x-frame-options_main.html \
 		file_x-frame-options_page.sjs \
 		test_createHTMLDocument.html \
 		test_bug567350.html \
 		test_bug574596.html \
 		test_bug578096.html \
 		test_bug598877.html \
+		test_bug599588.html \
 		test_bug600466.html \
 		test_bug600468.html \
 		test_bug600471.html \
 		test_bug601803.html \
 		file_bug601803a.html \
 		file_bug601803b.html \
+		test_bug602838.html \
+		script_bug602838.sjs \
 		test_bug604660.html \
 		file_bug604660-1.xml \
 		file_bug604660-2.xsl \
 		file_bug604660-3.js \
 		file_bug604660-4.js \
 		file_bug604660-5.xml \
 		file_bug604660-6.xsl \
 		test_bug605982.html \
+		test_treewalker_nextsibling.xml \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
 _TEST_FILES2 += 	test_copyimage.html \
 		$(NULL)
 endif
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/script_bug602838.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response)
+{
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "text/javascript", false);
+  response.write("ok(asyncRan, 'Async script should have run first.'); firstRan = true;");
+  response.processAsync();
+  var timer = Components.classes["@mozilla.org/timer;1"]
+    .createInstance(Components.interfaces.nsITimer);
+  timer.initWithCallback(function() {
+      response.finish();
+    }, 200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
--- a/content/base/test/test_CrossSiteXHR.html
+++ b/content/base/test/test_CrossSiteXHR.html
@@ -643,17 +643,17 @@ function runTest() {
           }
         }
       }
     }
     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, undefined, "wrong status in test for " + test.toSource());
+      is(res.statusText, "", "wrong status in test 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",
          "wrong events in test for " + test.toSource());
       is(res.progressEvents, 0,
@@ -783,17 +783,17 @@ function runTest() {
       is(res.events.join(","),
          "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
          "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, undefined, "wrong status in test for " + test.toSource());
+      is(res.statusText, "", "wrong status in test 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",
          "wrong events in test for " + test.toSource());
       is(res.progressEvents, 0,
@@ -1052,17 +1052,17 @@ function runTest() {
       is(res.events.join(","),
          "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
          "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, undefined, "wrong status in test for " + test.toSource());
+      is(res.statusText, "", "wrong status in test 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",
          "wrong events in test for " + test.toSource());
       is(res.progressEvents, 0,
--- a/content/base/test/test_CrossSiteXHR_origin.html
+++ b/content/base/test/test_CrossSiteXHR_origin.html
@@ -144,17 +144,17 @@ function runTest() {
         method: "GET",
       };
       loaderWindow.postMessage(req.toSource(), isNullOrigin ? "*" : origin);
 
       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, undefined, "wrong status text 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",
          "wrong events in test for " + allowOrigin);
       is(res.progressEvents, 0,
          "wrong events in test for " + allowOrigin);
     }
   }
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -85,12 +85,31 @@ is(ab.byteLength, 12, "wrong arraybuffer
 
 u8v = new Uint8Array(ab);
 i32v = new Int32Array(ab);
 u32v = new Uint32Array(ab, 8);
 ok(u8v[0] == 0xaa && u8v[1] == 0xee && u8v[2] == 0x00 && u8v[3] == 0x03, "wrong initial 4 bytes");
 is(i32v[1], -1, "wrong value, expected -1 (0xffffffff)");
 is(u32v[0], 0xbbbbbbbb, "wrong value, expected 0xbbbbbbbb");
 
+var client = new XMLHttpRequest();
+client.onreadystatechange = function() {
+    if(client.readyState == 4) {
+      try {
+        is(client.responseXML, null, "responseXML should be null.");
+        is(client.responseText, "", "responseText should be empty string.");
+        is(client.status, 0, "status should be 0.");
+        is(client.statusText, "", "statusText should be empty string.");
+        is(client.getAllResponseHeaders(), "",
+           "getAllResponseHeaders() should return empty string.");
+      } catch(ex) {
+        ok(false, "Shouldn't throw! [" + ex + "]");
+      }
+    }
+  }
+client.open("GET", "file_XHR_pass1.xml", true);
+client.send();
+client.abort();
+
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug599588.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=599588
+-->
+<head>
+  <title>Test for Bug 599588</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599588">Mozilla Bug 599588</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 599588 **/
+
+var div = document.createElement("div");
+div.innerHTML = "\u003Cscript>ok(false, 'Scripts created by innerHTML should not run.');\u003C/script>";
+document.body.appendChild(div);
+
+var contextualFragmentRan = false;
+
+var range = document.createRange();
+range.selectNode(document.body);
+var fragment = range.createContextualFragment("\u003Cscript>contextualFragmentRan = true;\u003C/script>");
+document.body.appendChild(fragment);
+
+ok(contextualFragmentRan, "Script from createContextualFragment should have run.");
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug602838.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602838
+-->
+<head>
+  <title>Test for Bug 602838</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602838">Mozilla Bug 602838</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script id=withasync async></script>
+<script id=withoutasync></script>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 602838 **/
+SimpleTest.waitForExplicitFinish();
+var firstRan = false;
+var asyncRan = false;
+
+var withoutasync = document.getElementById("withoutasync");
+ok(withoutasync.async, "When a script loses parser-insertedness, it should become async.");
+
+var withasync = document.getElementById("withasync");
+ok(withasync.async, "A script with the async content attribute should have the DOM attribute reporting true.");
+withasync.removeAttribute("async");
+ok(!withasync.async, "Should be able to remove asyncness from a script that had the async content attribute when losing parser-insertedness by removing the content attribute.");
+
+var s = document.createElement("script");
+ok(s.async, "Script-created scripts should default to .async=true");
+ok(!s.hasAttribute("async"), "Script-created scripts should not have the async content attribute by default.");
+s.removeAttribute("async");
+ok(s.async, "Removing a non-existing content-attribute should not have an effect on the forced async DOM property.");
+s.setAttribute("async", "");
+ok(s.async, "The async DOM property should still be true.");
+s.removeAttribute("async");
+ok(!s.async, "When a previously present async content attribute is removed, the DOM property should become false.");
+s.src = "script_bug602838.sjs";
+document.body.appendChild(s);
+
+s = document.createElement("script");
+s.src = "data:text/javascript,ok(firstRan, 'The first script should have run'); SimpleTest.finish();";
+s.async = false;
+ok(!s.async, "Setting the async DOM property to false should turned of forcing async to true.");
+document.body.appendChild(s);
+
+s = document.createElement("script");
+s.src = "data:text/javascript,ok(!firstRan, 'Non-async should not have run yet.'); asyncRan = true;";
+document.body.appendChild(s);
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_treewalker_nextsibling.xml
@@ -0,0 +1,98 @@
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css" ?>
+<root>
+  <script type="text/javascript" src="/MochiKit/packed.js" xmlns="http://www.w3.org/1999/xhtml"/>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js" xmlns="http://www.w3.org/1999/xhtml"/>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <p id="display"></p>
+    <div id="content" style="display: none;"></div>
+    <textarea id="test" style="height: 300px; max-width: 800px; overflow: scroll;"
+              rows="10" cols="160" readonly="readonly"/>
+  </body>
+
+<pre id="test" xmlns="http://www.w3.org/1999/xhtml">
+<script class="testbody" type="text/javascript" xmlns="http://www.w3.org/1999/xhtml">
+<![CDATA[
+function setPass(aNode) {
+  aNode.setUserData("pass", true, null);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("load", function() {
+  const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
+  var walker = document.createTreeWalker(
+    document,
+    nsIDOMNodeFilter.SHOW_TEXT | nsIDOMNodeFilter.SHOW_DOCUMENT,
+    null,
+    true
+  );
+  setPass(walker.firstChild());
+  while (walker.nextSibling()) {
+    setPass(walker.currentNode);
+  }
+
+/*
+From http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/traversal.html#Traversal-TreeWalker
+Omitting nodes from the logical view of a subtree can result in a structure that
+is substantially different from the same subtree in the complete, unfiltered
+document. Nodes that are siblings in the TreeWalker view may be children of
+different, widely separated nodes in the original view. For instance, consider a
+NodeFilter that skips all nodes except for Text nodes and the root node of a
+document. In the logical view that results, all text nodes will be siblings and
+appear as direct children of the root node, no matter how deeply nested the
+structure of the original document.
+*/
+
+  walker2 = document.createTreeWalker(document, nsIDOMNodeFilter.SHOW_TEXT, null, true);
+  while (walker2.nextNode()) {
+    var cNode = walker2.currentNode;
+    ok(cNode.getUserData("pass"), "Every text node should appear: " + walker2.currentNode.nodeValue);
+    walker.currentNode = cNode;
+    var parent = walker.parentNode();
+    is(parent, document, "parent of text node should be document");
+
+    // Check nextSibling's previousSibling.
+    walker.currentNode = cNode;
+    if (walker.nextSibling()) {
+      is(cNode, walker.previousSibling(), "nextSibling.previousSibling should be consistent");
+    }
+
+    // Check previousSibling's nextSibling.
+    walker.currentNode = cNode;
+    if (walker.previousSibling()) {
+      is(cNode, walker.nextSibling(), "previousSibling.nextSibling should be consistent");
+    }
+  }
+  SimpleTest.finish();
+}, true);
+]]>
+</script>
+</pre>
+
+  <test>
+    zero
+    <one>
+      one-A
+      <two>
+        two-A
+      </two>
+      <two>
+        two-B
+      </two>
+      one-B
+    </one>
+    <one>
+      one-C
+      <two>
+        two-D
+      </two>
+      <two>
+        two-E
+      </two>
+      one-F
+    </one>
+    zero
+  </test>
+</root>
+
rename from content/base/test/test_bug308484.html
rename to content/base/test/test_xhr_forbidden_headers.html
--- a/content/base/test/test_bug308484.html
+++ b/content/base/test/test_xhr_forbidden_headers.html
@@ -18,28 +18,34 @@ https://bugzilla.mozilla.org/show_bug.cg
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 308484 **/
 
 var headers = [
   "aCCept-chaRset",
   "acCePt-eNcoDing",
+  "aCcEsS-cOnTrOl-ReQuEsT-mEtHoD",
+  "aCcEsS-cOnTrOl-ReQuEsT-hEaDeRs",
   "coNnEctIon",
   "coNtEnt-LEngth",
+  "CoOKIe",
+  "cOOkiE2",
   "cOntEnt-tRAnsFer-enCoDiNg",
   "DATE",
   "exPeCt",
   "hOSt",
   "keep-alive",
+  "oRiGiN",
   "reFERer",
   "te",
   "trAiLer",
   "trANsfEr-eNcoDiNg",
   "uPGraDe",
+  "user-AGENT",
   "viA",
   "pRoxy-",
   "sEc-",
   "proxy-fOobar",
   "sec-bAZbOx"
 ];
 var i, request;
 
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -45,16 +45,17 @@
 
 // {EC90F32E-7848-4819-A1E3-02E64C682A72}
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
 { 0xec90f32e, 0x7848, 0x4819, { 0xa1, 0xe3, 0x2, 0xe6, 0x4c, 0x68, 0x2a, 0x72 } }
 
 class nsHTMLCanvasElement;
 class gfxContext;
 class gfxASurface;
+class nsIPropertyBag;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
 class LayerManager;
 }
 namespace ipc {
 class Shmem;
@@ -110,16 +111,24 @@ public:
   virtual already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
                                                        LayerManager *aManager) = 0;
 
   virtual void MarkContextClean() = 0;
 
   // Redraw the dirty rectangle of this canvas.
   NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
 
+  // Passes a generic nsIPropertyBag options argument, along with the
+  // previous one, if any.  Optional.
+  NS_IMETHOD SetContextOptions(nsIPropertyBag *aNewOptions) { return NS_OK; }
+
+  //
+  // shmem support
+  //
+
   // If this context can be set to use Mozilla's Shmem segments as its backing
   // store, this will set it to that state. Note that if you have drawn
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsIPC(PRBool isIPC) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -77,24 +77,24 @@ helper_isFloat32Array(JSObject *obj) {
 
 /*
  * BufferData takes:
  *    BufferData (int, int, int)
  *    BufferData_buf (int, js::ArrayBuffer *, int)
  *    BufferData_array (int, js::TypedArray *, int)
  */
 static JSBool
-nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp)
+nsIDOMWebGLRenderingContext_BufferData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -144,24 +144,24 @@ nsICanvasRenderingContextWebGL_BufferDat
 }
 
 /*
  * BufferSubData takes:
  *    BufferSubData (int, int, js::ArrayBuffer *)
  *    BufferSubData_array (int, int, js::TypedArray *)
  */
 static JSBool
-nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
+nsIDOMWebGLRenderingContext_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -210,26 +210,26 @@ nsICanvasRenderingContextWebGL_BufferSub
     return JS_TRUE;
 }
 
 /*
  * ReadPixels takes:
  *    ReadPixels(int, int, int, int, uint, uint, ArrayBufferView)
  */
 static JSBool
-nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
+nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 7)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -273,26 +273,26 @@ nsICanvasRenderingContextWebGL_ReadPixel
 
 /*
  * TexImage2D takes:
  *    TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)
  *    TexImage2D(uint, int, uint, uint, uint, nsIDOMElement)
  *    TexImage2D(uint, int, uint, uint, uint, ImageData)
  */
 static JSBool
-nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
+nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 6 || argc == 7 || argc == 8)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -391,26 +391,26 @@ nsICanvasRenderingContextWebGL_TexImage2
 }
 
 /* TexSubImage2D takes:
  *    TexSubImage2D(uint, int, int, int, int, int, uint, uint, ArrayBufferView)
  *    TexSubImage2D(uint, int, int, int, uint, uint, nsIDOMElement)
  *    TexSubImage2D(uint, int, int, int, uint, uint, ImageData)
  */
 static JSBool
-nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
+nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 7 || argc == 8)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -499,26 +499,26 @@ nsICanvasRenderingContextWebGL_TexSubIma
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 /* NOTE: There is a TN version of this below, update it as well */
 static inline JSBool
-helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -573,26 +573,26 @@ helper_nsICanvasRenderingContextWebGL_Un
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 /* NOTE: There is a TN version of this below, update it as well */
 static inline JSBool
-helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -647,26 +647,26 @@ helper_nsICanvasRenderingContextWebGL_Un
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 /* NOTE: There is a TN version of this below, update it as well */
 static inline JSBool
-helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -722,26 +722,26 @@ helper_nsICanvasRenderingContextWebGL_Un
     if (NS_FAILED(rv))
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static inline JSBool
-helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
-    nsICanvasRenderingContextWebGL *self;
+    nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
@@ -791,123 +791,123 @@ helper_nsICanvasRenderingContextWebGL_Ve
     if (NS_FAILED(rv))
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
-nsICanvasRenderingContextWebGL_Uniform1iv(JSContext *cx, uintN argc, jsval *vp)