Merge cvs-trunk-mirror to mozilla-central
authorbenjamin@smedbergs.us
Thu, 20 Sep 2007 13:33:44 -0400
changeset 6143 a51e9fb65b8a
parent 5943 b490108eb99c (current diff)
parent 6142 099d324f65ac (diff)
child 6190 324afbcccb71
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9a8pre
Merge cvs-trunk-mirror to mozilla-central
browser/components/shell/content/dummyWindow.xul
browser/locales/filter.py
client.mk
configure.in
content/svg/content/src/nsSVGAnimatedInteger.cpp
content/svg/content/src/nsSVGAnimatedInteger.h
content/svg/content/src/nsSVGInteger.cpp
content/svg/content/src/nsSVGInteger.h
js/src/js.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jscntxt.cpp
js/src/jsdbgapi.cpp
js/src/jsemit.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsparse.cpp
js/src/jsscope.cpp
js/src/jsstr.cpp
js/tests/e4x/Regress/regress-380833.js
js/tests/js1_5/decompilation/regress-375639.js
layout/reftests/bugs/376532-2-ref.html
layout/reftests/bugs/376532-2.html
testing/performance/talos/config.py
widget/public/nsIDragSessionMac.h
widget/public/nsIPrintingContext.h
xpcom/ds/nsAutoBuffer.h
xpcom/ds/nsDeque.cpp
xpcom/ds/nsDeque.h
xpfe/components/bookmarks/Makefile.in
xpfe/components/bookmarks/public/Makefile.in
xpfe/components/bookmarks/public/nsIBookmarksService.idl
xpfe/components/bookmarks/src/Makefile.in
xpfe/components/bookmarks/src/nsBookmarksService.cpp
xpfe/components/bookmarks/src/nsBookmarksService.h
xpfe/components/search/Makefile.in
xpfe/components/search/public/Makefile.in
xpfe/components/search/public/nsISearchService.idl
xpfe/components/search/src/Makefile.in
xpfe/components/search/src/nsInternetSearchService.cpp
xpfe/components/search/src/nsInternetSearchService.h
xpfe/components/search/src/nsLocalSearchService.cpp
xpfe/components/search/src/nsLocalSearchService.h
xpfe/components/search/src/nsRegisterSearch.cpp
xpfe/components/search/src/nsSearchModule.cpp
--- a/accessible/public/nsIAccessibilityService.idl
+++ b/accessible/public/nsIAccessibilityService.idl
@@ -50,17 +50,17 @@ interface nsIAccessibilityService : nsIA
 {
   nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
   nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
 
   nsIAccessible createHTML4ButtonAccessible(in nsISupports aFrame);
   nsIAccessible createHyperTextAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLBRAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLButtonAccessible(in nsISupports aFrame);
-  nsIAccessible createHTMLAccessibleByMarkup(in nsIFrame aFrame, in nsIWeakReference aWeakShell, in nsIDOMNode aDOMNode, in AString aRole);
+  nsIAccessible createHTMLAccessibleByMarkup(in nsIFrame aFrame, in nsIWeakReference aWeakShell, in nsIDOMNode aDOMNode);
   nsIAccessible createHTMLLIAccessible(in nsISupports aFrame, in nsISupports aBulletFrame, in AString aBulletText);
   nsIAccessible createHTMLCheckboxAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLComboboxAccessible(in nsIDOMNode aNode, in nsIWeakReference aPresShell);
   nsIAccessible createHTMLGenericAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLGroupboxAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLHRAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLImageAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLLabelAccessible(in nsISupports aFrame);
--- a/accessible/public/nsIAccessible.idl
+++ b/accessible/public/nsIAccessible.idl
@@ -189,16 +189,20 @@ interface nsIAccessible : nsISupports
    * @param similarItemsInGroup - 1-based, similar to ARIA 'setsize' property
    * @param positionInGroup - 1-based, similar to ARIA 'posinset' property
    */
   void groupPosition(out long aGroupLevel, out long aSimilarItemsInGroup,
                      out long aPositionInGroup);
 
   /**
    * Accessible child which contains the coordinate at (x, y) in screen pixels.
+   * If the point is in the current accessible but not in a child, the
+   * current accessible will be returned.
+   * If the point is in neither the current accessible or a child, then
+   * null will be returned.
    */
   nsIAccessible getChildAtPoint(in long x, in long y);
 
   /**
    * Nth accessible child using zero-based index or last child if index less than zero
    */
   nsIAccessible getChildAt(in long aChildIndex);
 
--- a/accessible/public/nsIAccessibleProvider.idl
+++ b/accessible/public/nsIAccessibleProvider.idl
@@ -67,16 +67,18 @@ interface nsIAccessibleProvider : nsISup
   const long XULColorPickerTile = 0x00001005;
   const long XULCombobox = 0x00001006;
   const long XULDropmarker = 0x00001007;
   const long XULGroupbox = 0x00001008;
   const long XULImage = 0x00001009;
   const long XULLink = 0x0000100A;
   const long XULListbox = 0x0000100B;
   const long XULListitem = 0x0000100C;
+  const long XULListHead = 0x00001024;
+  const long XULListHeader = 0x00001025;
   const long XULMenubar = 0x0000100D;
   const long XULMenuitem = 0x0000100E;
   const long XULMenupopup = 0x0000100F;
   const long XULMenuSeparator = 0x00001010;
   const long XULProgressMeter = 0x00001011;
   const long XULScale = 0x00001012;
   const long XULStatusBar = 0x00001013;
   const long XULRadioButton = 0x00001014;
@@ -92,17 +94,17 @@ interface nsIAccessibleProvider : nsISup
    as well */
   const long XULTabs = 0x00001018;
 
   const long XULText             = 0x00001019;
   const long XULTextBox          = 0x0000101A;
   const long XULThumb            = 0x0000101B;
   const long XULTree             = 0x0000101C;
   const long XULTreeColumns      = 0x0000101D;
-  const long XULTreeColumnitem   = 0x0000101E;
+  const long XULTreeColumnItem   = 0x0000101E;
   const long XULToolbar          = 0x0000101F;
   const long XULToolbarSeparator = 0x00001020;
   const long XULTooltip          = 0x00001021;
   const long XULToolbarButton    = 0x00001022;
 
 
   /**
    * Constants set is used by XForms elements.
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -119,16 +119,18 @@ static GType GetAtkTypeForMai(MaiInterfa
     case MAI_INTERFACE_DOCUMENT:
       return ATK_TYPE_DOCUMENT;
     case MAI_INTERFACE_IMAGE:
       return ATK_TYPE_IMAGE;
   }
   return G_TYPE_INVALID;
 }
 
+static const char* kNonUserInputEvent = ":system";
+    
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
      (GInterfaceFinalizeFunc) NULL, NULL}, 
     {(GInterfaceInitFunc)actionInterfaceInitCB,
      (GInterfaceFinalizeFunc) NULL, NULL},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
      (GInterfaceFinalizeFunc) NULL, NULL},
     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
@@ -786,17 +788,17 @@ AtkAttributeSet *
 GetAttributeSet(nsIAccessible* aAccessible)
 {
     AtkAttributeSet *objAttributeSet = nsnull;
     nsCOMPtr<nsIPersistentProperties> attributes;
     aAccessible->GetAttributes(getter_AddRefs(attributes));
     
     if (attributes) {
         // Deal with attributes that we only need to expose in ATK
-        PRUint32 state, extraState;
+        PRUint32 state;
         aAccessible->GetFinalState(&state, nsnull);
         if (state & nsIAccessibleStates::STATE_HASPOPUP) {
           // There is no ATK state for haspopup, must use object attribute to expose the same info
           nsAutoString oldValueUnused;
           attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"), NS_LITERAL_STRING("true"),
                                         oldValueUnused);
         }
         if (state & nsIAccessibleStates::STATE_CHECKABLE) {
@@ -1280,25 +1282,16 @@ nsAccessibleWrap::FireAccessibleEvent(ns
         g_signal_emit_by_name(atkObj, "column_reordered");
         break;
 
     case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_SECTION_CHANGED\n"));
         g_signal_emit_by_name(atkObj, "visible_data_changed");
         break;
 
-    case nsIAccessibleEvent::EVENT_HYPERTEXT_LINK_SELECTED:
-        MAI_LOG_DEBUG(("\n\nReceived: EVENT_HYPERTEXT_LINK_SELECTED\n"));
-        atk_focus_tracker_notify(atkObj);
-        g_signal_emit_by_name(atkObj,
-                              "link_selected",
-                              // Selected link index 
-                              *(gint *)eventData);
-        break;
-
     case nsIAccessibleEvent::EVENT_DOM_CREATE:
     case nsIAccessibleEvent::EVENT_ASYNCH_SHOW:
         return FireAtkShowHideEvent(aEvent, atkObj, PR_TRUE);
 
     case nsIAccessibleEvent::EVENT_DOM_DESTROY:
     case nsIAccessibleEvent::EVENT_ASYNCH_HIDE:
         return FireAtkShowHideEvent(aEvent, atkObj, PR_FALSE);
 
@@ -1348,21 +1341,16 @@ nsAccessibleWrap::FireAccessibleEvent(ns
         g_signal_emit_by_name (atkObj, "reload");
       } break;
 
     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_STOPPED\n"));
         g_signal_emit_by_name (atkObj, "load_stopped");
       } break;
-    case nsIAccessibleEvent::EVENT_DOCUMENT_ATTRIBUTES_CHANGED:
-      {
-        MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_ATTRIBUTES_CHANGED\n"));
-        g_signal_emit_by_name (atkObj, "attributes_changed");
-      } break;
 
     case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUPOPUP_START\n"));
         atk_focus_tracker_notify(atkObj); // fire extra focus event
         atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, PR_TRUE);
         atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, PR_TRUE);
         break;
 
@@ -1432,21 +1420,23 @@ nsAccessibleWrap::FireAtkTextChangedEven
     event->GetStart(&start);
 
     PRUint32 length = 0;
     event->GetLength(&length);
 
     PRBool isInserted;
     event->IsInserted(&isInserted);
 
-    g_signal_emit_by_name (aObject,
-                           isInserted ? \
-                           "text_changed::insert":"text_changed::delete",
-                           start,
-                           length);
+    PRBool isFromUserInput;
+    event->GetIsFromUserInput(&isFromUserInput);
+
+    char *signal_name = g_strconcat(isInserted ? "text_changed::insert" : "text_changed::delete",
+                                    isFromUserInput ? "" : kNonUserInputEvent, NULL);
+    g_signal_emit_by_name(aObject, signal_name, start, length);
+    g_free (signal_name);
 
     return NS_OK;
 }
 
 nsresult
 nsAccessibleWrap::FireAtkPropChangedEvent(nsIAccessibleEvent *aEvent,
                                           AtkObject *aObject)
 {
@@ -1534,19 +1524,18 @@ nsAccessibleWrap::FireAtkShowHideEvent(n
     NS_ENSURE_STATE(parentAccessible);
 
     PRInt32 indexInParent = -1;
     accessible->GetIndexInParent(&indexInParent);
 
     AtkObject *parentObject = GetAtkObject(parentAccessible);
     NS_ENSURE_STATE(parentObject);
 
-    g_signal_emit_by_name(parentObject,
-                          aIsAdded ? \
-                          "children_changed::add" : \
-                          "children_changed::remove",
-                          indexInParent,
-                          aObject,
-                          NULL);
+    PRBool isFromUserInput;
+    aEvent->GetIsFromUserInput(&isFromUserInput);
+    char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
+                                    isFromUserInput ? "" : kNonUserInputEvent, NULL);
+    g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, NULL);
+    g_free(signal_name);
 
     return NS_OK;
 }
 
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp
@@ -67,19 +67,23 @@ AtkObject *
 refAccessibleAtPointCB(AtkComponent *aComponent,
                        gint aAccX, gint aAccY,
                        AtkCoordType aCoordType)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
     if (!accWrap || nsAccessibleWrap::MustPrune(accWrap))
         return nsnull;
 
-    // or ATK_XY_SCREEN  what is definition this in nsIAccessible ???
+    // nsIAccessible getChildAtPoint (x,y) is in screen pixels.
     if (aCoordType == ATK_XY_WINDOW) {
-        /* deal with the coord type */
+        nsCOMPtr<nsIDOMNode> domNode;
+        accWrap->GetDOMNode(getter_AddRefs(domNode));
+        nsIntPoint winCoords = nsAccUtils::GetScreenCoordsForWindow(domNode);
+        aAccX += winCoords.x;
+        aAccY += winCoords.y;
     }
 
     nsCOMPtr<nsIAccessible> pointAcc;
     accWrap->GetChildAtPoint(aAccX, aAccY, getter_AddRefs(pointAcc));
     if (!pointAcc) {
         return nsnull;
     }
 
--- a/accessible/src/atk/nsMaiInterfaceImage.cpp
+++ b/accessible/src/atk/nsMaiInterfaceImage.cpp
@@ -64,18 +64,28 @@ getImagePositionCB(AtkImage *aImage, gin
 
     nsCOMPtr<nsIAccessibleImage> image;
     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleImage),
                             getter_AddRefs(image));
     if (!image)
       return;
 
     PRInt32 width, height; // dummy
-    image->GetImageBounds(aAccX, aAccY, &width, &height);
-    // TODO: translate (x,y) accroding aCoordType. see bug 369821
+    // Returned in screen coordinates
+    nsresult rv = image->GetImageBounds(aAccX, aAccY, &width, &height);
+    if (NS_FAILED(rv))
+      return;
+    
+    if (aCoordType == ATK_XY_WINDOW) {
+        nsCOMPtr<nsIDOMNode> domNode;
+        accWrap->GetDOMNode(getter_AddRefs(domNode));
+        nsIntPoint winCoords = nsAccUtils::GetScreenCoordsForWindow(domNode);
+        *aAccX -= winCoords.x;
+        *aAccY -= winCoords.y;
+    }
 }
 
 const gchar *
 getImageDescriptionCB(AtkImage *aImage)
 {
    return getDescriptionCB(ATK_OBJECT(aImage));
 }
 
--- a/accessible/src/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/src/atk/nsMaiInterfaceTable.cpp
@@ -282,17 +282,17 @@ getColumnHeaderCB(AtkTable *aTable, gint
     nsresult rv = accTable->GetColumnHeader(getter_AddRefs(header));
     NS_ENSURE_SUCCESS(rv, nsnull);
     NS_ENSURE_TRUE(header, nsnull);
 
     // Note: "table column header" has different definition between atk and mai
     //
     // 1. "getColumnHeaderCB" defined in AtkTableIface should return object
     // whose role is "ATK_ROLE_TABLE_COLUMN_HEADER", which is implemented
-    // by nsXULTreeColumnitemAccessible.
+    // by nsXULTreeColumnItemAccessible.
     //
     // 2. "GetColumnHeader" defined in nsIAccessibleTable returns
     // nsXULTreeColumnsAccessibleWrap, which exports nsIAccessibleTable and is
     // "ROLE_LIST".
     nsCOMPtr<nsIAccessible> accHeader;
     header->CellRefAt(0, aColumn, getter_AddRefs(accHeader));
     NS_ENSURE_TRUE(accHeader, nsnull);
 
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -61,32 +61,31 @@ static const nsStateMapEntry kEndEntry =
 
 nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
 {
   {"alert", nsIAccessibleRole::ROLE_ALERT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
-            {"pressed", kBoolState, nsIAccessibleStates::STATE_PRESSED}, kEndEntry},
+            {"pressed", kBoolState, nsIAccessibleStates::STATE_PRESSED},
+            {"pressed", "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
   {"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED},
-            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
-  {"checkboxtristate", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
-            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED},
             {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
-  {"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_COLLAPSED,
+  {"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax,
+               nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
+            // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aaa:autocomplete
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
             {"expanded", kBoolState, nsIAccessibleStates::STATE_EXPANDED}, kEndEntry},
   {"description", nsIAccessibleRole::ROLE_TEXT_CONTAINER, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"dialog", nsIAccessibleRole::ROLE_DIALOG, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"document", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"grid", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_FOCUSABLE,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
@@ -111,37 +110,40 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
   {"listbox", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
             {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
   {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
   {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
   {"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
-  {"menuitemcheckbox", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+  {"menuitemcheckbox", nsIAccessibleRole::ROLE_CHECK_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
-            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
-  {"menuitemradio", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED },
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
+  {"menuitemradio", nsIAccessibleRole::ROLE_RADIO_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
   {"option", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
   {"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
   {"radio", nsIAccessibleRole::ROLE_RADIOBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED}, kEndEntry},
   {"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
@@ -167,16 +169,19 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"status", nsIAccessibleRole::ROLE_STATUSBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
   {"tablist", nsIAccessibleRole::ROLE_PAGETABLIST, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"tabpanel", nsIAccessibleRole::ROLE_PROPERTYPAGE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"textbox", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eNoValue, kNoReqStates,
             // Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aaa:multiline
+            // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aaa:autocomplete
+            {"autocomplete", "list", nsIAccessibleStates::STATE_HASPOPUP},
+            {"autocomplete", "both", nsIAccessibleStates::STATE_HASPOPUP},
             {"secret", kBoolState, nsIAccessibleStates::STATE_PROTECTED},
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
   {"tooltip", nsIAccessibleRole::ROLE_TOOLTIP, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"tree", nsIAccessibleRole::ROLE_OUTLINE, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
@@ -188,17 +193,17 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
             {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"treeitem", nsIAccessibleRole::ROLE_OUTLINEITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
             {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
             {"expanded", kBoolState, nsIAccessibleStates::STATE_EXPANDED},
             {"expanded", "false", nsIAccessibleStates::STATE_COLLAPSED},
             {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE},},
   {nsnull, nsIAccessibleRole::ROLE_NOTHING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry} // Last item
 };
 
 /**
  * Universal states:
  * The following state rules are applied to any accessible element,
  * whether there is an ARIA role or not:
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -42,22 +42,24 @@
 #include "nsHashtable.h"
 #include "nsIAccessibilityService.h"
 #include "nsIAccessibleDocument.h"
 #include "nsPIAccessibleDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIDocumentViewer.h"
+#include "nsIDOM3Node.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
+#include "nsIDOMNSDocument.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsIPrefService.h"
@@ -885,8 +887,76 @@ nsAccessNode::GetLanguage(nsAString& aLa
     if (doc) {
       doc->GetHeaderData(nsAccessibilityAtoms::headerContentLanguage, aLanguage);
     }
   }
  
   return NS_OK;
 }
 
+PRBool
+nsAccessNode::GetARIARole(nsIContent *aContent, nsString& aRole)
+{
+  nsAutoString prefix;
+  PRBool strictPrefixChecking = PR_TRUE;
+  aRole.Truncate();
+
+  if (aContent->IsNodeOfType(nsINode::eHTML)) { // HTML node
+    // Allow non-namespaced role attribute in HTML
+    aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, aRole);
+    // Find non-namespaced role attribute on HTML node
+    nsCOMPtr<nsIDOMNSDocument> doc(do_QueryInterface(aContent->GetDocument()));
+    if (doc) {
+      // In text/html we are hardcoded to allow the exact prefix "wairole:" to 
+      // always indicate that we are using the WAI roles.
+      // This allows ARIA to be used within text/html where namespaces cannot be defined.
+      // We also now relax the prefix checking, which means no prefix is required to use WAI Roles
+      nsAutoString mimeType;
+      doc->GetContentType(mimeType);
+      if (mimeType.EqualsLiteral("text/html")) {
+        prefix = NS_LITERAL_STRING("wairole:");
+        strictPrefixChecking = PR_FALSE;
+      }
+    }
+  }
+
+  // Try namespaced-role attribute (xhtml or xhtml2 namespace) -- allowed in any kind of content
+  if (aRole.IsEmpty() && !aContent->GetAttr(kNameSpaceID_XHTML, nsAccessibilityAtoms::role, aRole) &&
+      !aContent->GetAttr(kNameSpaceID_XHTML2_Unofficial, nsAccessibilityAtoms::role, aRole)) {
+    return PR_FALSE;
+  }
+
+  PRBool hasPrefix = (aRole.Find(":") >= 0);
+
+  if (!hasPrefix) {
+    // * No prefix* -- not a QName
+    // Just return entire string as long as prefix is not currently required
+    if (strictPrefixChecking) {
+      // Prefix was required and we didn't have one
+      aRole.Truncate();
+      return PR_FALSE;
+    }
+    return PR_TRUE;
+  }
+
+  // * Has prefix * -- is a QName (role="prefix:rolename")
+  if (strictPrefixChecking) {  // Not text/html, we need to actually find the WAIRole prefix
+    // QI to nsIDOM3Node causes some overhead. Unfortunately we need to do this each
+    // time there is a prefixed role attribute, because the prefix to namespace mappings
+    // can change within any subtree via the xmlns attribute
+    nsCOMPtr<nsIDOM3Node> dom3Node(do_QueryInterface(aContent));
+    if (dom3Node) {
+      // Look up exact prefix name for WAI Roles
+      NS_NAMED_LITERAL_STRING(kWAIRoles_Namespace, "http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#");
+      dom3Node->LookupPrefix(kWAIRoles_Namespace, prefix);
+      prefix += ':';
+    }
+  }
+
+  PRUint32 length = prefix.Length();
+  if (length > 1 && StringBeginsWith(aRole, prefix)) {
+    // Is a QName (role="prefix:rolename"), and prefix matches WAI Role prefix
+    // Trim the WAI Role prefix off
+    aRole.Cut(0, length);
+  }
+
+  return PR_TRUE;
+}
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -66,16 +66,26 @@ class nsRootAccessible;
 class nsApplicationAccessibleWrap;
 
 #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
 #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
 
 typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsIAccessNode>
         nsAccessNodeHashtable;
 
+/**
+ * Does the current content have this ARIA role? 
+ * Implemented as a compiler macro so that length can be computed at compile time.
+ * @param aContent  Node to get role string from
+ * @param aRoleName Role string to compare with -- literal const char*
+ * @return PR_TRUE if there is a match
+ */
+#define ARIARoleEquals(aContent, aRoleName) \
+  nsAccessNode::ARIARoleEqualsImpl(aContent, aRoleName, NS_ARRAY_LENGTH(aRoleName) - 1)
+
 class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
 {
   public: // construction, destruction
     nsAccessNode(nsIDOMNode *, nsIWeakReference* aShell);
     virtual ~nsAccessNode();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIACCESSNODE
@@ -109,24 +119,26 @@ class nsAccessNode: public nsIAccessNode
     // Return PR_TRUE if there is a role attribute
     static PRBool HasRoleAttribute(nsIContent *aContent)
     {
       return (aContent->IsNodeOfType(nsINode::eHTML) && aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) ||
               aContent->HasAttr(kNameSpaceID_XHTML, nsAccessibilityAtoms::role) ||
               aContent->HasAttr(kNameSpaceID_XHTML2_Unofficial, nsAccessibilityAtoms::role);
     }
 
-    // Return PR_TRUE if there is a role attribute, and fill it into aRole
-    static PRBool GetRoleAttribute(nsIContent *aContent, nsAString& aRole)
-    {
-      aRole.Truncate();
-      return (aContent->IsNodeOfType(nsINode::eHTML) && aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, aRole)) ||
-              aContent->GetAttr(kNameSpaceID_XHTML, nsAccessibilityAtoms::role, aRole) ||
-              aContent->GetAttr(kNameSpaceID_XHTML2_Unofficial, nsAccessibilityAtoms::role, aRole);
-    }
+    /**
+     * Provide the role string if there is one
+     * @param aContent Node to get role string from
+     * @param aRole String to fill role into
+     * @return PR_TRUE if there is a role attribute, and fill it into aRole
+     */
+    static PRBool GetARIARole(nsIContent *aContent, nsString& aRole);
+
+    static PRBool ARIARoleEqualsImpl(nsIContent* aContent, const char* aRoleName, PRUint32 aLen)
+      { nsAutoString role; return GetARIARole(aContent, role) && role.EqualsASCII(aRoleName, aLen); }
 
     static void GetComputedStyleDeclaration(const nsAString& aPseudoElt,
                                             nsIDOMElement *aElement,
                                             nsIDOMCSSStyleDeclaration **aCssDecl);
 
     already_AddRefed<nsRootAccessible> GetRootAccessible();
 
     static nsIDOMNode *gLastFocusedNode;
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -159,17 +159,16 @@ ACCESSIBILITY_ATOM(cycles, "cycles") // 
 ACCESSIBILITY_ATOM(curpos, "curpos") // XUL
 ACCESSIBILITY_ATOM(data, "data")
 ACCESSIBILITY_ATOM(disabled, "disabled")
 ACCESSIBILITY_ATOM(droppable, "droppable")   // XUL combo box
 ACCESSIBILITY_ATOM(editable, "editable")
 ACCESSIBILITY_ATOM(_for, "for")
 ACCESSIBILITY_ATOM(hidden, "hidden")   // XUL tree columns
 ACCESSIBILITY_ATOM(href, "href")
-ACCESSIBILITY_ATOM(id, "id")
 ACCESSIBILITY_ATOM(increment, "increment") // XUL
 ACCESSIBILITY_ATOM(lang, "lang")
 ACCESSIBILITY_ATOM(maxpos, "maxpos") // XUL
 ACCESSIBILITY_ATOM(minpos, "minpos") // XUL
 ACCESSIBILITY_ATOM(multiline, "multiline")
 ACCESSIBILITY_ATOM(name, "name")
 ACCESSIBILITY_ATOM(onclick, "onclick")
 ACCESSIBILITY_ATOM(readonly, "readonly")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -429,17 +429,16 @@ nsAccessibilityService::CreateHTMLButton
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 nsresult
 nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame *aFrame,
                                                      nsIWeakReference *aWeakShell,
                                                      nsIDOMNode *aNode,
-                                                     const nsAString& aRole,
                                                      nsIAccessible **aAccessible)
 {
   // This method assumes we're in an HTML namespace.
   *aAccessible = nsnull;
   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
   nsIAtom *tag = content->Tag();
   if (tag == nsAccessibilityAtoms::legend) {
     *aAccessible = new nsHTMLLegendAccessible(aNode, aWeakShell);
@@ -1332,19 +1331,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
       *aIsHidden = PR_TRUE;
       return NS_OK;
     }
     frame->GetAccessible(getter_AddRefs(newAcc));
     return InitAccessible(newAcc, aAccessible);
   }
 
   nsAutoString role;
-  if (nsAccessNode::GetRoleAttribute(content, role) &&
-      StringEndsWith(role, NS_LITERAL_STRING(":presentation")) &&
-      !content->IsFocusable()) {
+  if (nsAccessNode::GetARIARole(content, role) && role.EqualsLiteral("presentation") && !content->IsFocusable()) {
     // Only create accessible for role=":presentation" if it is focusable --
     // in that case we need an accessible in case it gets focused, we
     // don't want focus ever to be 'lost'
     return NS_OK;
   }
 
   // Elements may implement nsIAccessibleProvider via XBL. This allows them to
   // say what kind of accessible to create.
@@ -1359,22 +1356,19 @@ NS_IMETHODIMP nsAccessibilityService::Ge
                                         nsIAccessibleRole::ROLE_DIAGRAM);
     }
     else if (content->GetNameSpaceID() == kNameSpaceID_MathML &&
              content->Tag() == nsAccessibilityAtoms::math) {
       newAcc = new nsEnumRoleAccessible(aNode, aWeakShell,
                                         nsIAccessibleRole::ROLE_EQUATION);
     }
   } else if (!newAcc) {  // HTML accessibles
-    // Prefer to use markup (mostly tag name, perhaps attributes) to
-    // decide if and what kind of accessible to create.
-    CreateHTMLAccessibleByMarkup(frame, aWeakShell, aNode, role, getter_AddRefs(newAcc));
+    PRBool tryTagNameOrFrame = PR_TRUE;
 
-    PRBool tryFrame = (newAcc == nsnull);
-    if (!content->IsFocusable()) { 
+    if (!content->IsFocusable()) {
       // If we're in unfocusable table-related subcontent, check for the
       // Presentation role on the containing table
       nsIAtom *tag = content->Tag();
       if (tag == nsAccessibilityAtoms::td ||
           tag == nsAccessibilityAtoms::th ||
           tag == nsAccessibilityAtoms::tr ||
           tag == nsAccessibilityAtoms::tbody ||
           tag == nsAccessibilityAtoms::tfoot ||
@@ -1384,51 +1378,63 @@ NS_IMETHODIMP nsAccessibilityService::Ge
         while ((tableContent = tableContent->GetParent()) != nsnull) {
           if (tableContent->Tag() == nsAccessibilityAtoms::table) {
             nsIFrame *tableFrame = aPresShell->GetPrimaryFrameFor(tableContent);
             if (!tableFrame || tableFrame->GetType() != nsAccessibilityAtoms::tableOuterFrame ||
                 nsAccessNode::HasRoleAttribute(tableContent)) {
               // Table that we're a descendant of is not styled as a table,
               // and has no table accessible for an ancestor, or
               // table that we're a descendant of is presentational
-              tryFrame = PR_FALSE;
+              tryTagNameOrFrame = PR_FALSE;
             }
-
             break;
           }
         }
       }
     }
 
-    if (tryFrame) {
-      // 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
-      if (frame->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
-         frame->GetRect().IsEmpty()) {
-        // XXX This is not the ideal place for this code, but right now there is 
-        // no better place:
-        *aIsHidden = PR_TRUE;
-        return NS_OK;
+    if (tryTagNameOrFrame) {
+      // Prefer to use markup (mostly tag name, perhaps attributes) to
+      // decide if and what kind of accessible to create.
+      // The method creates accessibles for table related content too therefore
+      // we do not call it if accessibles for table related content are
+      // prevented above.
+      rv = CreateHTMLAccessibleByMarkup(frame, aWeakShell, aNode,
+                                        getter_AddRefs(newAcc));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      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.
+        if (frame->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
+           frame->GetRect().IsEmpty()) {
+          // XXX This is not the ideal place for this code, but right now there
+          // is no better place:
+          *aIsHidden = PR_TRUE;
+          return NS_OK;
+        }
+        frame->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
       }
-      frame->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
     }
   }
 
   if (!newAcc) {
     GetAccessibleForDeckChildren(aNode, getter_AddRefs(newAcc));
   }
 
   // If no accessible, see if we need to create a generic accessible because
   // of some property that makes this object interesting
   // We don't do this for <body>, <html>, <window>, <dialog> etc. which 
   // correspond to the doc accessible and will be created in any case
   if (!newAcc && content->Tag() != nsAccessibilityAtoms::body && content->GetParent() && 
-      (content->IsFocusable() ||
+      (content->IsFocusable() || content->GetID() ||
       (isHTML && nsAccUtils::HasListener(content, NS_LITERAL_STRING("click"))) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::describedby) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::labelledby) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::flowto) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::controls) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::atomic) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::busy) ||
        content->HasAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::channel) ||
@@ -1592,16 +1598,22 @@ nsresult nsAccessibilityService::GetAcce
       break;
     }
     case nsIAccessibleProvider::XULLink:
       *aAccessible = new nsXULLinkAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULListbox:
       *aAccessible = new nsXULListboxAccessible(aNode, weakShell);
       break;
+    case nsIAccessibleProvider::XULListHead:
+      *aAccessible = new nsXULColumnsAccessible(aNode, weakShell);
+      break;
+    case nsIAccessibleProvider::XULListHeader:
+      *aAccessible = new nsXULColumnItemAccessible(aNode, weakShell);
+      break;
     case nsIAccessibleProvider::XULListitem:
       *aAccessible = new nsXULListitemAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULMenubar:
       *aAccessible = new nsXULMenubarAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULMenuitem:
       *aAccessible = new nsXULMenuitemAccessibleWrap(aNode, weakShell);
@@ -1662,18 +1674,18 @@ nsresult nsAccessibilityService::GetAcce
       *aAccessible = new nsXULThumbAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULTree:
       *aAccessible = new nsXULTreeAccessibleWrap(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULTreeColumns:
       *aAccessible = new nsXULTreeColumnsAccessibleWrap(aNode, weakShell);
       break;
-    case nsIAccessibleProvider::XULTreeColumnitem:
-      *aAccessible = new nsXULTreeColumnitemAccessible(aNode, weakShell);
+    case nsIAccessibleProvider::XULTreeColumnItem:
+      *aAccessible = new nsXULColumnItemAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULToolbar:
       *aAccessible = new nsXULToolbarAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULToolbarSeparator:
       *aAccessible = new nsXULToolbarSeparatorAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULTooltip:
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -62,16 +62,18 @@
 #include "nsIInterfaceRequestorUtils.h"
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 void
 nsAccUtils::GetAccAttr(nsIPersistentProperties *aAttributes, nsIAtom *aAttrName,
                        nsAString& aAttrValue)
 {
+  aAttrValue.Truncate();
+
   nsCAutoString attrName;
   aAttrName->ToUTF8String(attrName);
   aAttributes->GetStringProperty(attrName, aAttrValue);
 }
 
 void
 nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes, nsIAtom *aAttrName,
                        const nsAString& aAttrValue)
@@ -397,8 +399,14 @@ nsAccUtils::GetDocShellTreeItemFor(nsIDO
   nsCOMPtr<nsISupports> container = doc->GetContainer();
   nsIDocShellTreeItem *docShellTreeItem = nsnull;
   if (container)
     CallQueryInterface(container, &docShellTreeItem);
 
   return docShellTreeItem;
 }
 
+PRBool
+nsAccUtils::GetID(nsIContent *aContent, nsAString& aID)
+{
+  nsIAtom *idAttribute = aContent->GetIDAttributeName();
+  return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : PR_FALSE;
+}
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -175,12 +175,20 @@ public:
    */
   static nsIntPoint GetScreenCoordsForWindow(nsIDOMNode *aNode);
 
   /**
    * Return document shell tree item for the given DOM node.
    */
   static already_AddRefed<nsIDocShellTreeItem>
     GetDocShellTreeItemFor(nsIDOMNode *aNode);
+
+  /**
+   * Get the ID for an element, in some types of XML this may not be the ID attribute
+   * @param aContent  Node to get the ID for
+   * @param aID       Where to put ID string
+   * @return          PR_TRUE if there is an ID set for this node
+   */
+  static PRBool GetID(nsIContent *aContent, nsAString& aID);
 };
 
 #endif
 
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -40,25 +40,23 @@
 #include "nsAccessible.h"
 #include "nsAccessibleRelation.h"
 #include "nsHyperTextAccessibleWrap.h"
 
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleHyperText.h"
 #include "nsAccessibleTreeWalker.h"
 
-#include "nsIDOM3Node.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMNodeFilter.h"
-#include "nsIDOMNSDocument.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULLabelElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
@@ -402,19 +400,22 @@ nsAccessible::GetKeyboardShortcut(nsAStr
 {
   aAccessKey.Truncate();
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   if (!content)
     return NS_ERROR_FAILURE;
 
   PRUint32 key = nsAccUtils::GetAccessKeyFor(content);
-  if (!key) {
+  if (!key && content->IsNodeOfType(nsIContent::eELEMENT)) {
+    // Copy access key from label node unless it is labeled
+    // via an ancestor <label>, in which case that would be redundant
     nsCOMPtr<nsIContent> labelContent(GetLabelContent(content));
-    if (labelContent)
+    nsCOMPtr<nsIDOMNode> labelNode = do_QueryInterface(labelContent);
+    if (labelNode && !nsAccUtils::IsAncestorOf(labelNode, mDOMNode))
       key = nsAccUtils::GetAccessKeyFor(labelContent);
   }
 
   if (!key)
     return NS_OK;
 
   nsAutoString accesskey(key);
 
@@ -470,55 +471,28 @@ NS_IMETHODIMP nsAccessible::SetNextSibli
   mNextSibling = aNextSibling? aNextSibling: DEAD_END_ACCESSIBLE;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAccessible::Init()
 {
   nsIContent *content = GetRoleContent(mDOMNode);
   nsAutoString roleString;
-  if (content && GetRoleAttribute(content, roleString)) {
-    // QI to nsIDOM3Node causes some overhead. Unfortunately we need to do this each
-    // time there is a role attribute, because the prefixe to namespace mappings
-    // can change within any subtree via the xmlns attribute
-    nsCOMPtr<nsIDOM3Node> dom3Node(do_QueryInterface(content));
-    if (dom3Node) {
-      nsAutoString prefix;
-      NS_NAMED_LITERAL_STRING(kWAIRoles_Namespace, "http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#");
-      dom3Node->LookupPrefix(kWAIRoles_Namespace, prefix);
-      if (prefix.IsEmpty()) {
-        // In HTML we are hardcoded to allow the exact prefix "wairole:" to 
-        // always indicate that we are using the WAI roles. This allows DHTML accessibility
-        // to be used within HTML
-        nsCOMPtr<nsIDOMNSDocument> doc(do_QueryInterface(content->GetDocument()));
-        if (doc) {
-          nsAutoString mimeType;
-          doc->GetContentType(mimeType);
-          if (mimeType.EqualsLiteral("text/html")) {
-            prefix = NS_LITERAL_STRING("wairole");
-          }
-        }
-      }
-      prefix += ':';
-      PRUint32 length = prefix.Length();
-      if (length > 1 && StringBeginsWith(roleString, prefix)) {
-        roleString.Cut(0, length);
-        nsCString utf8Role = NS_ConvertUTF16toUTF8(roleString); // For easy comparison
-        ToLowerCase(utf8Role);
-        PRUint32 index;
-        for (index = 0; nsARIAMap::gWAIRoleMap[index].roleString; index ++) {
-          if (utf8Role.Equals(nsARIAMap::gWAIRoleMap[index].roleString)) {
-            break; // The dynamic role attribute maps to an entry in our table
-          }
-        }
-        // Always use some entry if there is a role string
-        // If no match, we use the last entry which maps to ROLE_NOTHING
-        mRoleMapEntry = &nsARIAMap::gWAIRoleMap[index];
+  if (content && GetARIARole(content, roleString)) {
+    nsCString utf8Role = NS_ConvertUTF16toUTF8(roleString); // For easy comparison
+    ToLowerCase(utf8Role);
+    PRUint32 index;
+    for (index = 0; nsARIAMap::gWAIRoleMap[index].roleString; index ++) {
+      if (utf8Role.Equals(nsARIAMap::gWAIRoleMap[index].roleString)) {
+        break; // The dynamic role attribute maps to an entry in our table
       }
     }
+    // Always use some entry if there is a role string
+    // If no match, we use the last entry which maps to ROLE_NOTHING
+    mRoleMapEntry = &nsARIAMap::gWAIRoleMap[index];
   }
 
   return nsAccessNodeWrap::Init();
 }
 
 nsIContent *nsAccessible::GetRoleContent(nsIDOMNode *aDOMNode)
 {
   // Given the DOM node for an acessible, return content node that
@@ -1088,75 +1062,129 @@ NS_IMETHODIMP nsAccessible::GetFocusedCh
   /* nsIAccessible getChildAtPoint (in long x, in long y); */
 NS_IMETHODIMP
 nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                               nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
+  if (!mDOMNode) {
+    return NS_ERROR_FAILURE;  // Already shut down
+  }
+
+  // If we can't find the point in a child, we will return the fallback answer:
+  // we return |this| if the point is within it, otherwise nsnull
+  nsCOMPtr<nsIAccessible> fallbackAnswer;
+  PRInt32 x, y, width, height;
+  GetBounds(&x, &y, &width, &height);
+  if (aX >= x && aX < x + width &&
+      aY >= y && aY < y + height) {
+    fallbackAnswer = this;
+  }
+  if (MustPrune(this)) {  // Do not dig any further
+    NS_IF_ADDREF(*aAccessible = fallbackAnswer);
+    return NS_OK;
+  }
+
   // Search an accessible at the given point starting from accessible document
   // because containing block (see CSS2) for out of flow element (for example,
   // absolutely positioned element) may be different from its DOM parent and
   // therefore accessible for containing block may be different from accessible
   // for DOM parent but GetFrameForPoint() should be called for containing block
   // to get an out of flow element.
   nsCOMPtr<nsIAccessibleDocument> accDocument;
   nsresult rv = GetAccessibleDocument(getter_AddRefs(accDocument));
   NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!accDocument)
-    return NS_OK;
+  NS_ENSURE_TRUE(accDocument, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsPIAccessNode> accessNodeDocument(do_QueryInterface(accDocument));
   NS_ASSERTION(accessNodeDocument,
                "nsIAccessibleDocument doesn't implement nsPIAccessNode");
 
   nsIFrame *frame = accessNodeDocument->GetFrame();
   NS_ENSURE_STATE(frame);
 
   nsPresContext *presContext = frame->PresContext();
 
   nsIntRect screenRect = frame->GetScreenRectExternal();
   nsPoint offset(presContext->DevPixelsToAppUnits(aX - screenRect.x),
                  presContext->DevPixelsToAppUnits(aY - screenRect.y));
 
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
   nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
-  if (!foundFrame)
+  nsCOMPtr<nsIContent> content;
+  if (!foundFrame || !(content = foundFrame->GetContent())) {
+    NS_IF_ADDREF(*aAccessible = fallbackAnswer);
     return NS_OK;
-
-  nsCOMPtr<nsIContent> content(foundFrame->GetContent());
-  if (!content)
-    return NS_OK;
+  }
 
   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
   nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
 
   nsCOMPtr<nsIDOMNode> relevantNode;
   accService->GetRelevantContentNodeFor(node, getter_AddRefs(relevantNode));
-  if (!relevantNode)
+  if (!relevantNode) {
+    NS_IF_ADDREF(*aAccessible = fallbackAnswer);
     return NS_OK;
+  }
 
   nsCOMPtr<nsIAccessible> accessible;
   accService->GetAccessibleFor(relevantNode, getter_AddRefs(accessible));
-  if (!accessible)
-    return NS_OK;
-
-  nsCOMPtr<nsIAccessible> parent;
-  accessible->GetParent(getter_AddRefs(parent));
-
-  while (parent && parent != this) {
-    accessible.swap(parent);
-    accessible->GetParent(getter_AddRefs(parent));
+  if (!accessible) {
+    // No accessible for the node with the point, so find the first
+    // accessible in the DOM parent chain
+    accDocument->GetAccessibleInParentChain(relevantNode,
+                                            getter_AddRefs(accessible));
+    if (!accessible) {
+      NS_IF_ADDREF(*aAccessible = fallbackAnswer);
+      return NS_OK;
+    }
   }
 
-  if (parent)
-    NS_ADDREF(*aAccessible = accessible);
-
+  if (accessible == this) {
+    // Manually walk through accessible children and see if
+    // the are within this point.
+    // This takes care of cases where layout won't walk into
+    // things for us, such as image map areas and sub documents
+    nsCOMPtr<nsIAccessible> child;
+    while (NextChild(child)) {
+      PRInt32 childX, childY, childWidth, childHeight;
+      child->GetBounds(&childX, &childY, &childWidth, &childHeight);
+      if (aX >= childX && aX < childX + childWidth &&
+          aY >= childY && aY < childY + childHeight &&
+          (State(child) & nsIAccessibleStates::STATE_INVISIBLE) == 0) {
+        // Don't walk into offscreen or invisible items
+        NS_IF_ADDREF(*aAccessible = child);
+        return NS_OK;
+      }
+    }
+    // Fall through -- the point is in this accessible but not in a child
+    // We are allowed to return |this| as the answer
+  }
+  else {
+    nsCOMPtr<nsIAccessible> parent;
+    while (PR_TRUE) {
+      accessible->GetParent(getter_AddRefs(parent));
+      if (!parent) {
+        // Reached the top of the hierarchy
+        // these bounds were inside an accessible that is not a descendant of this one
+        NS_IF_ADDREF(*aAccessible = fallbackAnswer);
+        return NS_OK;
+      }
+      if (parent == this) {
+        // We reached |this|, so |accessible| is the
+        // child we want to return
+        break;
+      }
+      accessible.swap(parent);
+    }
+  }
+
+  NS_IF_ADDREF(*aAccessible = accessible);
   return NS_OK;
 }
 
 void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
 {
 /*
  * This method is used to determine the bounds of a content node.
  * Because HTML wraps and links are not always rectangular, this
@@ -1625,21 +1653,20 @@ nsIContent* nsAccessible::GetHTMLLabelCo
     }
     if (tag == nsAccessibilityAtoms::form ||
         tag == nsAccessibilityAtoms::body) {
       // Reached top ancestor in form
       // There can be a label targeted at this control using the 
       // for="control_id" attribute. To save computing time, only 
       // look for those inside of a form element
       nsAutoString forId;
-      aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::id, forId);
-      // Actually we'll be walking down the content this time, with a depth first search
-      if (forId.IsEmpty()) {
+      if (!nsAccUtils::GetID(aForNode, forId)) {
         break;
       }
+      // Actually we'll be walking down the content this time, with a depth first search
       return FindDescendantPointingToID(&forId, walkUpContent,
                                         nsAccessibilityAtoms::_for);
     }
   }
 
   return nsnull;
 }
 
@@ -1696,20 +1723,18 @@ nsresult nsAccessible::GetTextFromRelati
 
 nsIContent*
 nsAccessible::FindNeighbourPointingToNode(nsIContent *aForNode,
                                           nsIAtom *aTagName, nsIAtom *aRelationAttr,
                                           PRUint32 aRelationNameSpaceID,
                                           PRUint32 aAncestorLevelsToSearch)
 {
   nsCOMPtr<nsIContent> binding;
-
   nsAutoString controlID;
-  aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::id, controlID);
-  if (controlID.IsEmpty()) {
+  if (!nsAccUtils::GetID(aForNode, controlID)) {
     binding = aForNode->GetBindingParent();
     if (binding == aForNode)
       return nsnull;
 
     aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::anonid, controlID);
     if (controlID.IsEmpty())
       return nsnull;
   }
@@ -2058,41 +2083,61 @@ nsAccessible::GetAttributes(nsIPersisten
   NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
 
   nsAccEvent::GetLastEventAttributes(mDOMNode, attributes);
  
   nsresult rv = GetAttributesInternal(attributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content = GetRoleContent(mDOMNode);
-  if (content) {
-    nsAutoString id;
+  nsAutoString id;
+  if (content && nsAccUtils::GetID(content, id)) {
     nsAutoString oldValueUnused;
-    if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::id, id)) {
-      attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);    
-    }
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);
     // XXX In the future we may need to expose the dynamic content role inheritance chain
     // through this attribute
     nsAutoString xmlRole;
-    if (GetRoleAttribute(content, xmlRole)) {
+    if (GetARIARole(content, xmlRole)) {
       attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"), xmlRole, oldValueUnused);          
     }
 
     char *ariaProperties[] = { "live", "channel", "atomic", "relevant", "datatype", "level",
                                "posinset", "setsize", "sort", "grab", "dropeffect"};
 
     for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(ariaProperties); index ++) {
       nsAutoString value;
       nsCOMPtr<nsIAtom> attr = do_GetAtom(ariaProperties[index]);
       NS_ENSURE_TRUE(attr, NS_ERROR_OUT_OF_MEMORY);
       if (content->GetAttr(kNameSpaceID_WAIProperties, attr, value)) {
         ToLowerCase(value);
         attributes->SetStringProperty(nsDependentCString(ariaProperties[index]), value, oldValueUnused);    
       }
     }
+
+    // Get container-foo computed live region properties based on the closest container with
+    // the live region attribute
+    nsAutoString atomic, live, relevant, channel, busy;
+    while (content) {
+      if (relevant.IsEmpty() && 
+          content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::relevant, relevant))
+        attributes->SetStringProperty(NS_LITERAL_CSTRING("container-relevant"), relevant, oldValueUnused);
+      if (live.IsEmpty() &&
+          content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::live, live))
+        attributes->SetStringProperty(NS_LITERAL_CSTRING("container-live"), live, oldValueUnused);
+      if (channel.IsEmpty() &&
+          content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::channel, channel))
+        attributes->SetStringProperty(NS_LITERAL_CSTRING("container-channel"), channel, oldValueUnused);
+      if (atomic.IsEmpty() &&
+          content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::atomic, atomic))
+        attributes->SetStringProperty(NS_LITERAL_CSTRING("container-atomic"), atomic, oldValueUnused);
+      if (busy.IsEmpty() &&
+          content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::busy, busy))
+        attributes->SetStringProperty(NS_LITERAL_CSTRING("container-busy"), busy, oldValueUnused);
+      content = content->GetParent();
+    }
   }
 
   if (!nsAccUtils::HasAccGroupAttrs(attributes)) {
     // The role of an accessible can be pointed by ARIA attribute but ARIA
     // posinset, level, setsize may be skipped. Therefore we calculate here
     // these properties to map them into description.
 
     // If accessible is invisible we don't want to calculate group ARIA
@@ -2180,17 +2225,17 @@ nsAccessible::GroupPosition(PRInt32 *aGr
                             PRInt32 *aSimilarItemsInGroup,
                             PRInt32 *aPositionInGroup)
 {
   // Every element exposes level/posinset/sizeset for IAccessdible::attributes
   // if they make sense for it. These attributes are mapped into groupPosition.
   // If 'level' attribute doesn't make sense element then it isn't represented
   // via IAccessible::attributes and groupLevel of groupPosition method is 0.
   // Elements that expose 'level' attribute only (like html headings elements)
-  // don't support this method and all arguements are equealed 0.
+  // don't support this method and all arguments  are equalled 0.
 
   NS_ENSURE_ARG_POINTER(aGroupLevel);
   NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
   NS_ENSURE_ARG_POINTER(aPositionInGroup);
 
   *aGroupLevel = 0;
   *aSimilarItemsInGroup = 0;
   *aPositionInGroup = 0;
@@ -2290,27 +2335,39 @@ nsAccessible::GetFinalState(PRUint32 *aS
           *aExtraState |= nsIAccessibleStates::EXT_STATE_VERTICAL;
         }
         else {
           *aExtraState |= nsIAccessibleStates::EXT_STATE_HORIZONTAL;
         }
       }
     }
 
-    // XXX We can remove this hack once we support RDF-based role & state maps
-    if (mRoleMapEntry && (mRoleMapEntry->role == nsIAccessibleRole::ROLE_ENTRY ||
-        mRoleMapEntry->role == nsIAccessibleRole::ROLE_PASSWORD_TEXT)) {
-      nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
+    PRUint32 role;
+    GetFinalRole(&role);
+    if (role == nsIAccessibleRole::ROLE_ENTRY ||
+        role == nsIAccessibleRole::ROLE_PASSWORD_TEXT ||
+        role == nsIAccessibleRole::ROLE_COMBOBOX) {
+      nsIContent *content = frame->GetContent();
       NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
-      if (content->AttrValueIs(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::multiline,
-                               nsAccessibilityAtoms::_true, eCaseMatters)) {
-        *aExtraState |= nsIAccessibleStates::EXT_STATE_MULTI_LINE;
+      nsAutoString autocomplete;
+      if (content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::autocomplete, autocomplete) &&
+          (autocomplete.EqualsIgnoreCase("inline") ||
+           autocomplete.EqualsIgnoreCase("list") ||
+           autocomplete.EqualsIgnoreCase("both"))) {
+        *aExtraState |= nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION;
       }
-      else {
-        *aExtraState |= nsIAccessibleStates::EXT_STATE_SINGLE_LINE;
+      // XXX We can remove this hack once we support RDF-based role & state maps
+      if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_ENTRY) {
+        if (content->AttrValueIs(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::multiline,
+                                 nsAccessibilityAtoms::_true, eCaseMatters)) {
+          *aExtraState |= nsIAccessibleStates::EXT_STATE_MULTI_LINE;
+        }
+        else {
+          *aExtraState |= nsIAccessibleStates::EXT_STATE_SINGLE_LINE;
+        }
       }
     }
   }
 
   return NS_OK;
 }
 
 PRUint32
@@ -2560,16 +2617,36 @@ nsAccessible::FindNeighbourPointingToThi
   if (!description)
     return nsnull;
 
   nsIDOMNode *relatedNode;
   CallQueryInterface(description, &relatedNode);
   return relatedNode;
 }
 
+nsIDOMNode* nsAccessible::GetAtomicRegion()
+{
+  nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
+  nsIContent *loopContent = content;
+  nsAutoString atomic;
+
+  while (loopContent) {
+    loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::atomic, atomic);
+    if (!atomic.IsEmpty()) {
+      break;
+    }
+    loopContent = loopContent->GetParent();
+  }
+
+  nsCOMPtr<nsIDOMNode> atomicRegion;
+  if (atomic.EqualsLiteral("true")) {
+    atomicRegion = do_QueryInterface(loopContent);
+  }
+  return atomicRegion;
+}
 
 /* nsIAccessible getAccessibleRelated(); */
 NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated)
 {
   // When adding support for relations, make sure to add them to
   // appropriate places in nsAccessibleWrap implementations
   *aRelated = nsnull;
 
@@ -2724,17 +2801,17 @@ NS_IMETHODIMP nsAccessible::GetAccessibl
           }
           relatedNode = do_QueryInterface(buttonEl);
         }
       }
       break;
     }
   case nsIAccessibleRelation::RELATION_MEMBER_OF:
     {
-      relatedNode = nsAccEvent::GetLastEventAtomicRegion(mDOMNode);
+      relatedNode = GetAtomicRegion();
       break;
     }
   default:
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   if (!relatedID.IsEmpty()) {
     // In some cases we need to get the relatedNode from an ID-style attribute
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -273,16 +273,22 @@ protected:
   // For accessibles that have actions
   static void DoCommandCallback(nsITimer *aTimer, void *aClosure);
   nsresult DoCommand(nsIContent *aContent = nsnull);
 
   // Check the visibility across both parent content and chrome
   PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);
 
   /**
+   *  Get the container node for an atomic region, defined by aria:atomic="true"
+   *  @return the container node
+   */
+  nsIDOMNode* GetAtomicRegion();
+
+  /**
    * Get numeric value of the given attribute.
    *
    * @param aNameSpaceID - namespace ID of the attribute
    * @param aName - name of the attribute
    * @param aValue - value of the attribute
    *
    * @return - NS_OK_NO_ARIA_VALUE if there is no setted ARIA attribute
    */
--- a/accessible/src/base/nsAccessibleEventData.cpp
+++ b/accessible/src/base/nsAccessibleEventData.cpp
@@ -70,88 +70,24 @@ nsAccEvent::nsAccEvent(PRUint32 aEventTy
   mEventType(aEventType), mDOMNode(aDOMNode), mEventData(aEventData)
 {
   CaptureIsFromUserInput(aIsAsynch);
 }
 
 void nsAccEvent::GetLastEventAttributes(nsIDOMNode *aNode,
                                         nsIPersistentProperties *aAttributes)
 {
-  if (aNode != gLastEventNodeWeak) {
-    return; // Passed-in node doesn't Change the last event's node
-  }
-  nsAutoString oldValueUnused;
-  aAttributes->SetStringProperty(NS_LITERAL_CSTRING("event-from-input"),
-                                 gLastEventFromUserInput ? NS_LITERAL_STRING("true") :
-                                                           NS_LITERAL_STRING("false"),
-                                 oldValueUnused);
-
-  nsCOMPtr<nsIContent> lastEventContent = do_QueryInterface(aNode);
-  nsIContent *loopContent = lastEventContent;
-
-  nsAutoString atomic, live, relevant, channel, busy;
-
-  while (loopContent) {
-    if (relevant.IsEmpty()) {
-      loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::relevant, relevant);
-    }
-    if (live.IsEmpty()) {
-      loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::live, live);
-    }
-    if (channel.IsEmpty()) {
-      loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::channel, channel);
-    }
-    if (atomic.IsEmpty()) {
-      loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::atomic, atomic);
-    }
-    if (busy.IsEmpty()) {
-      loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::busy, busy);
-    }
-    loopContent = loopContent->GetParent();
-  }
-
-  if (!relevant.IsEmpty()) {
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("container-relevant"), relevant, oldValueUnused);
+  if (aNode == gLastEventNodeWeak) {
+    // Only provide event-from-input for last event's node
+    nsAutoString oldValueUnused;
+    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("event-from-input"),
+                                   gLastEventFromUserInput ? NS_LITERAL_STRING("true") :
+                                                             NS_LITERAL_STRING("false"),
+                                   oldValueUnused);
   }
-  if (!live.IsEmpty()) {
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("container-live"), live, oldValueUnused);
-  }
-  if (!channel.IsEmpty()) {
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("container-channel"), channel, oldValueUnused);
-  }
-  if (!atomic.IsEmpty()) {
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("container-atomic"), atomic, oldValueUnused);
-  }
-  if (!busy.IsEmpty()) {
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("container-busy"), busy, oldValueUnused);
-  }
-}
-
-nsIDOMNode* nsAccEvent::GetLastEventAtomicRegion(nsIDOMNode *aNode)
-{
-  if (aNode != gLastEventNodeWeak) {
-    return nsnull; // Passed-in node doesn't Change the last changed node
-  }
-  nsCOMPtr<nsIContent> lastEventContent = do_QueryInterface(aNode);
-  nsIContent *loopContent = lastEventContent;
-  nsAutoString atomic;
-
-  while (loopContent) {
-    loopContent->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::atomic, atomic);
-    if (!atomic.IsEmpty()) {
-      break;
-    }
-    loopContent = loopContent->GetParent();
-  }
-
-  nsCOMPtr<nsIDOMNode> atomicRegion;
-  if (atomic.EqualsLiteral("true")) {
-    atomicRegion = do_QueryInterface(loopContent);
-  }
-  return atomicRegion;
 }
 
 void nsAccEvent::CaptureIsFromUserInput(PRBool aIsAsynch)
 {
   nsCOMPtr<nsIDOMNode> eventNode;
   GetDOMNode(getter_AddRefs(eventNode));
   if (!eventNode) {
     NS_NOTREACHED("There should always be a DOM node for an event");
--- a/accessible/src/base/nsAccessibleEventData.h
+++ b/accessible/src/base/nsAccessibleEventData.h
@@ -59,17 +59,16 @@ public:
   nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, void *aEventData, PRBool aIsAsynch = PR_FALSE);
   virtual ~nsAccEvent() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIACCESSIBLEEVENT
 
   static void GetLastEventAttributes(nsIDOMNode *aNode,
                                       nsIPersistentProperties *aAttributes);
-  static nsIDOMNode* GetLastEventAtomicRegion(nsIDOMNode *aNode);
 
 protected:
   already_AddRefed<nsIAccessible> GetAccessibleByNode();
 
   void CaptureIsFromUserInput(PRBool aIsAsynch);
   PRBool mIsFromUserInput;
 
 private:
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -58,16 +58,18 @@ class nsLeafAccessible : public nsAccess
 {
 public:
   nsLeafAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_DECL_ISUPPORTS_INHERITED
   NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
   NS_IMETHOD GetLastChild(nsIAccessible **_retval);
   NS_IMETHOD GetChildCount(PRInt32 *_retval);
   NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
+  NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
+    { *aAccessible = this; return NS_OK; } // Don't walk into these
 };
 
 /**
   * A type of accessible for DOM nodes containing an href="" attribute.
   *  It knows how to report the state of the link ( traveled or not )
   *  and can activate ( click ) the link programmatically.
   */
 class nsLinkableAccessible : public nsHyperTextAccessibleWrap
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -72,16 +72,18 @@
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif
 
 //=============================//
 // nsDocAccessible  //
 //=============================//
 
+PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
+
 //-----------------------------------------------------
 // construction
 //-----------------------------------------------------
 nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
   mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE)
 {
   // For GTK+ native window, we do nothing here.
@@ -746,21 +748,16 @@ NS_IMETHODIMP nsDocAccessible::FireAncho
 
   if (currentAnchor.Equals(lastAnchor)) {
     mIsAnchorJumped = PR_FALSE;
   } else {
     mIsAnchorJumped = PR_TRUE;
     lastAnchor.Assign(currentAnchor);
   }
 
-  if (mIsAnchorJumped) {
-    nsAccUtils::
-      FireAccEvent(nsIAccessibleEvent::EVENT_DOCUMENT_ATTRIBUTES_CHANGED, this);
-  }
-
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
 {
   if (!mDocument || !mWeakShell) {
     return NS_OK;  // Document has been shut down
   }
@@ -914,16 +911,33 @@ NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(ns
 NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsDocAccessible)
 NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsDocAccessible)
 
 void
 nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
                                   PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                   PRInt32 aModType, PRUint32 aStateMask)
 {
+  AttributeChangedImpl(aContent, aNameSpaceID, aAttribute);
+
+  // If it was the focused node, cache the new state
+  nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(aContent);
+  if (targetNode == gLastFocusedNode) {
+    nsCOMPtr<nsIAccessible> focusedAccessible;
+    GetAccService()->GetAccessibleFor(targetNode, getter_AddRefs(focusedAccessible));
+    if (focusedAccessible) {
+      gLastFocusedAccessiblesState = State(focusedAccessible);
+    }
+  }
+}
+
+
+void
+nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID, nsIAtom* aAttribute)
+{
   // Fire accessible event after short timer, because we need to wait for
   // DOM attribute & resulting layout to actually change. Otherwise,
   // assistive technology will retrieve the wrong state/value/selection info.
 
   // XXX todo
   // We still need to handle special HTML cases here
   // For example, if an <img>'s usemap attribute is modified
   // Otherwise it may just be a state change, for example an object changing
@@ -1082,31 +1096,43 @@ nsDocAccessible::ARIAAttributeChanged(ns
   if (!HasRoleAttribute(aContent)) {
     // We don't care about these other ARIA attribute changes unless there is
     // an ARIA role set for the element
     // XXX: we should check the role map to see if the changed property is
     // relevant for that particular role.
     return;
   }
 
-  if (aAttribute == nsAccessibilityAtoms::checked) {
+  if (aAttribute == nsAccessibilityAtoms::checked ||
+      aAttribute == nsAccessibilityAtoms::pressed) {
+    const PRUint32 kState = (aAttribute == nsAccessibilityAtoms::checked) ?
+                            nsIAccessibleStates::STATE_CHECKED : 
+                            nsIAccessibleStates::STATE_PRESSED;
     nsCOMPtr<nsIAccessibleStateChangeEvent> event =
-      new nsAccStateChangeEvent(targetNode,
-                                nsIAccessibleStates::STATE_CHECKED,
-                                PR_FALSE);
+      new nsAccStateChangeEvent(targetNode, kState, PR_FALSE);
     FireDelayedAccessibleEvent(event);
-    return;
-  }
-
-  if (aAttribute == nsAccessibilityAtoms::pressed) {
-    nsCOMPtr<nsIAccessibleStateChangeEvent> event =
-      new nsAccStateChangeEvent(targetNode,
-                                nsIAccessibleStates::STATE_PRESSED,
-                                PR_FALSE);
-    FireDelayedAccessibleEvent(event);
+    if (targetNode == gLastFocusedNode) {
+      // State changes for MIXED state currently only supported for focused item, because
+      // otherwise we would need access to the old attribute value in this listener.
+      // This is because we don't know if the previous value of aaa:checked or aaa:pressed was "mixed"
+      // without caching that info.
+      nsCOMPtr<nsIAccessible> accessible;
+      event->GetAccessible(getter_AddRefs(accessible));
+      if (accessible) {
+        PRBool wasMixed = (gLastFocusedAccessiblesState & nsIAccessibleStates::STATE_MIXED) != 0;
+        PRBool isMixed  = (State(accessible) & nsIAccessibleStates::STATE_MIXED) != 0;
+        if (wasMixed != isMixed) {
+          nsCOMPtr<nsIAccessibleStateChangeEvent> event =
+            new nsAccStateChangeEvent(targetNode,
+                                      nsIAccessibleStates::STATE_MIXED,
+                                      PR_FALSE, isMixed);
+          FireDelayedAccessibleEvent(event);
+        }
+      }
+    }
     return;
   }
 
   if (aAttribute == nsAccessibilityAtoms::expanded) {
     nsCOMPtr<nsIAccessibleStateChangeEvent> event =
       new nsAccStateChangeEvent(targetNode,
                                 nsIAccessibleStates::STATE_EXPANDED,
                                 PR_FALSE);
@@ -1771,28 +1797,25 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
     // the assistive technology may receive the event and then retrieve
     // nsIAccessibleStates::STATE_INVISIBLE for the event's accessible object.
     PRUint32 additionEvent = isAsynch ? nsIAccessibleEvent::EVENT_ASYNCH_SHOW :
                                         nsIAccessibleEvent::EVENT_DOM_CREATE;
     FireDelayedToolkitEvent(additionEvent, childNode, nsnull,
                             eCoalesceFromSameSubtree, isAsynch);
 
     // Check to see change occured in an ARIA menu, and fire an EVENT_MENUPOPUP_START if it did
-    nsAutoString role;
-    if (GetRoleAttribute(aChild, role) &&
-        StringEndsWith(role, NS_LITERAL_STRING(":menu"), nsCaseInsensitiveStringComparator())) {
+    if (ARIARoleEquals(aChild, "menu")) {
       FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
                               childNode, nsnull, eAllowDupes, isAsynch);
     }
 
     // Check to see if change occured inside an alert, and fire an EVENT_ALERT if it did
     nsIContent *ancestor = aChild;
     while (ancestor) {
-      if (GetRoleAttribute(ancestor, role) &&
-          StringEndsWith(role, NS_LITERAL_STRING(":alert"), nsCaseInsensitiveStringComparator())) {
+      if (ARIARoleEquals(ancestor, "alert")) {
         nsCOMPtr<nsIDOMNode> alertNode(do_QueryInterface(ancestor));
         FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_ALERT, alertNode, nsnull,
                                 eRemoveDupes, isAsynch);
         break;
       }
       ancestor = ancestor->GetParent();
     }
   }
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -144,17 +144,26 @@ class nsDocAccessible : public nsHyperTe
     virtual nsresult AddEventListeners();
     virtual nsresult RemoveEventListeners();
     void AddScrollListener();
     void RemoveScrollListener();
     void RefreshNodes(nsIDOMNode *aStartNode);
     static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
 
     /**
-     * Fires accessible events when ARIA attribute is chaned.
+     * Fires accessible events when attribute is changed.
+     *
+     * @param aContent - node that attribute is changed for
+     * @param aNameSpaceID - namespace of changed attribute
+     * @param aAttribute - changed attribute
+     */
+    void AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID, nsIAtom* aAttribute);
+
+    /**
+     * Fires accessible events when ARIA attribute is changed.
      *
      * @param aContent - node that attribute is changed for
      * @param aAttribute - changed attribute
      */
     void ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute);
 
     /**
      * Fire text changed event for character data changed. The method is used
@@ -190,15 +199,16 @@ class nsDocAccessible : public nsHyperTe
     nsCOMPtr<nsITimer> mFireEventTimer;
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
     PRPackedBool mIsContentLoaded;
     nsCOMArray<nsIAccessibleEvent> mEventsToFire;
 
 protected:
     PRBool mIsAnchor;
     PRBool mIsAnchorJumped;
+    static PRUint32 gLastFocusedAccessiblesState;
 
 private:
     static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
     nsCOMPtr<nsITimer> mDocLoadTimer;
 };
 
 #endif  
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -81,16 +81,34 @@ NS_IMETHODIMP nsOuterDocAccessible::GetR
 NS_IMETHODIMP
 nsOuterDocAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   nsAccessible::GetState(aState, aExtraState);
   *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                      nsIAccessible **aAccessible)
+{
+  NS_ENSURE_ARG_POINTER(aAccessible);
+  *aAccessible = nsnull;
+  if (!mDOMNode) {
+    return NS_ERROR_FAILURE;
+  }
+  PRInt32 docX, docY, docWidth, docHeight;
+  GetBounds(&docX, &docY, &docWidth, &docHeight);
+  if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return GetFirstChild(aAccessible);  // Always return the inner doc unless bounds outside of it
+}
+
 void nsOuterDocAccessible::CacheChildren()
 {  
   // An outer doc accessible usually has 1 nsDocAccessible child,
   // but could have none if we can't get to the inner documnet
   if (!mWeakShell) {
     mAccChildCount = eChildCountUninitialized;
     return;   // This outer doc node has been shut down
   }
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/base/nsOuterDocAccessible.h
@@ -50,12 +50,14 @@ class nsOuterDocAccessible : public nsAc
 
   public:
     nsOuterDocAccessible(nsIDOMNode* aNode, 
                          nsIWeakReference* aShell);
 
     NS_IMETHOD GetName(nsAString& aName);
     NS_IMETHOD GetRole(PRUint32 *aRole);
     NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+    NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                               nsIAccessible **aAccessible);
     void CacheChildren();
 };
 
 #endif  
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -437,16 +437,22 @@ PRBool nsRootAccessible::FireAccessibleF
       // which points to the actual anonymous child with focus, so to be safe 
       // we need to reset the selection listener every time.
       // This happens because when some bindings handle focus, they retarget
       // focus to the appropriate child inside of themselves, but DOM focus
       // stays outside on that binding parent.
       nsCOMPtr<nsIDOMEventTarget> domEventTarget;
       nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
       nsCOMPtr<nsIDOMNode> realFocusedNode(do_QueryInterface(domEventTarget));
+      if (!realFocusedNode) {
+        // When FireCurrentFocusEvent() synthesizes a focus event,
+        // the orignal target does not exist, so use the passed-in node
+        // which is the relevant focused node
+        realFocusedNode = aNode;
+      }
       if (realFocusedNode) {
         mCaretAccessible->SetControlSelectionListener(realFocusedNode);
       }
     }
   }
 
   // Check for aaa:activedescendant, which changes which element has focus
   nsCOMPtr<nsIDOMNode> finalFocusNode = aNode;
@@ -476,16 +482,17 @@ PRBool nsRootAccessible::FireAccessibleF
     }
   }
 
   // Fire focus only if it changes, but always fire focus events when aForceEvent == PR_TRUE
   if (gLastFocusedNode == finalFocusNode && !aForceEvent) {
     return PR_FALSE;
   }
 
+  gLastFocusedAccessiblesState = State(finalFocusAccessible);
   PRUint32 role = Role(finalFocusAccessible);
   if (role == nsIAccessibleRole::ROLE_MENUITEM) {
     if (!mCurrentARIAMenubar) {  // Entering menus
       PRUint32 naturalRole; // The natural role is the role that this type of element normally has
       finalFocusAccessible->GetRole(&naturalRole);
       if (role != naturalRole) { // Must be a DHTML menuitem
         mCurrentARIAMenubar =
           nsAccUtils::GetAncestorWithRole(finalFocusAccessible, nsIAccessibleRole::ROLE_MENUBAR);
--- a/accessible/src/html/nsHTMLAreaAccessible.h
+++ b/accessible/src/html/nsHTMLAreaAccessible.h
@@ -51,11 +51,13 @@ public:
   nsHTMLAreaAccessible(nsIDOMNode *domNode, nsIAccessible *accParent, nsIWeakReference* aShell);
   NS_IMETHOD GetName(nsAString & _retval); 
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
   NS_IMETHOD GetLastChild(nsIAccessible **_retval);
   NS_IMETHOD GetChildCount(PRInt32 *_retval);
   NS_IMETHOD GetDescription(nsAString& _retval);
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
+  NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
+    { *aAccessible = this; return NS_OK; } // Don't walk into these
 };
 
 #endif  
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -389,32 +389,38 @@ nsHTMLSelectListAccessible::CacheOptSibl
                                              nsIContent *aParentContent,
                                              nsIAccessible *aLastGoodAccessible,
                                              PRInt32 *aChildCount)
 {
   // Recursive helper for CacheChildren()
 
   PRUint32 numChildren = aParentContent->GetChildCount();
   nsCOMPtr<nsIAccessible> lastGoodAccessible(aLastGoodAccessible);
+  nsCOMPtr<nsIAccessible> newAccessible;
 
   for (PRUint32 count = 0; count < numChildren; count ++) {
     nsIContent *childContent = aParentContent->GetChildAt(count);
     if (!childContent->IsNodeOfType(nsINode::eHTML)) {
       continue;
     }
     nsCOMPtr<nsIAtom> tag = childContent->Tag();
     if (tag == nsAccessibilityAtoms::option || tag == nsAccessibilityAtoms::optgroup) {
-      lastGoodAccessible = AccessibleForOption(aAccService,
-                                               childContent,
-                                               lastGoodAccessible,
-                                               aChildCount);
+      newAccessible = AccessibleForOption(aAccService,
+                                           childContent,
+                                           lastGoodAccessible,
+                                           aChildCount);
+      if (newAccessible) {
+        lastGoodAccessible = newAccessible;
+      }
       if (tag == nsAccessibilityAtoms::optgroup) {
-        lastGoodAccessible = CacheOptSiblings(aAccService, childContent,
-                                              lastGoodAccessible,
-                                              aChildCount);
+        newAccessible = CacheOptSiblings(aAccService, childContent,
+                                         lastGoodAccessible, aChildCount);
+        if (newAccessible) {
+          lastGoodAccessible = newAccessible;
+        }
       }
     }
   }
   if (lastGoodAccessible) {
     nsCOMPtr<nsPIAccessible> privateLastAcc =
       do_QueryInterface(lastGoodAccessible);
     privateLastAcc->SetNextSibling(nsnull);
     NS_ADDREF(aLastGoodAccessible = lastGoodAccessible);
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -53,16 +53,17 @@
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFontMetrics.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPlaintextEditor.h"
+#include "nsISelection2.h"
 #include "nsIServiceManager.h"
 #include "nsTextFragment.h"
 #include "gfxSkipChars.h"
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 // ------------
 // nsHyperTextAccessible
@@ -100,17 +101,22 @@ nsresult nsHyperTextAccessible::QueryInt
       *aInstancePtr = static_cast<nsIAccessibleText*>(this);
       NS_ADDREF_THIS();
       return NS_OK;
     }
 
     if (aIID.Equals(NS_GET_IID(nsIAccessibleHyperText))) {
       if (role == nsIAccessibleRole::ROLE_ENTRY ||
           role == nsIAccessibleRole::ROLE_PASSWORD_TEXT) {
-        return NS_ERROR_NO_INTERFACE;
+        nsCOMPtr<nsIEditor> editor;
+        GetAssociatedEditor(getter_AddRefs(editor));
+        nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
+        if (peditor) {
+          return NS_ERROR_NO_INTERFACE; // No embedded objects ever in plain text
+        }
       }
       *aInstancePtr = static_cast<nsIAccessibleHyperText*>(this);
       NS_ADDREF_THIS();
       return NS_OK;
     }
 
     if (aIID.Equals(NS_GET_IID(nsIAccessibleEditableText))) {
       *aInstancePtr = static_cast<nsIAccessibleEditableText*>(this);
@@ -319,16 +325,23 @@ nsIntRect nsHyperTextAccessible::GetBoun
  */
 nsIFrame*
 nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset,
                                      nsAString *aText, nsIFrame **aEndFrame,
                                      nsIntRect *aBoundsRect,
                                      nsIAccessible **aStartAcc,
                                      nsIAccessible **aEndAcc)
 {
+  if (aStartOffset < 0) {
+    GetCharacterCount(&aStartOffset);
+  }
+  if (aEndOffset < 0) {
+    GetCharacterCount(&aEndOffset);
+  }
+
   PRInt32 startOffset = aStartOffset;
   PRInt32 endOffset = aEndOffset;
 
   // Clear out parameters and set up loop
   if (aText) {
     aText->Truncate();
   }
   if (endOffset < 0) {
@@ -347,24 +360,25 @@ nsHyperTextAccessible::GetPosAndText(PRI
     aBoundsRect->Empty();
   }
   if (aStartAcc)
     *aStartAcc = nsnull;
   if (aEndAcc)
     *aEndAcc = nsnull;
 
   nsIntRect unionRect;
-  nsCOMPtr<nsIAccessible> accessible;
+  nsCOMPtr<nsIAccessible> accessible, lastAccessible;
 
   gfxSkipChars skipChars;
   gfxSkipCharsIterator iter;
 
   // Loop through children and collect valid offsets, text and bounds
   // depending on what we need for out parameters
   while (NextChild(accessible)) {
+    lastAccessible = accessible;
     nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible));
     nsIFrame *frame = accessNode->GetFrame();
     if (!frame) {
       continue;
     }
     nsIFrame *primaryFrame = frame;
     if (IsText(accessible)) {
       // We only need info up to rendered offset -- that is what we're
@@ -468,20 +482,23 @@ nsHyperTextAccessible::GetPosAndText(PRI
       }
       -- endOffset;
     }
     if (endOffset <= 0 && startFrame) {
       break; // If we don't have startFrame yet, get that in next loop iteration
     }
   }
 
+  if (aStartAcc && !*aStartAcc) {
+    NS_IF_ADDREF(*aStartAcc = lastAccessible);
+  }
   if (aEndFrame && !*aEndFrame) {
     *aEndFrame = startFrame;
     if (aStartAcc && aEndAcc)
-      NS_ADDREF(*aEndAcc = *aStartAcc);
+      NS_IF_ADDREF(*aEndAcc = *aStartAcc);
   }
 
   return startFrame;
 }
 
 NS_IMETHODIMP nsHyperTextAccessible::GetText(PRInt32 aStartOffset, PRInt32 aEndOffset, nsAString &aText)
 {
   if (!mDOMNode) {
@@ -528,17 +545,18 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
     return NS_ERROR_FAILURE;
   }
   *aCharacter = text.First();
   return NS_OK;
 }
 
 nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset,
                                                           PRInt32* aHyperTextOffset,
-                                                          nsIAccessible **aFinalAccessible)
+                                                          nsIAccessible **aFinalAccessible,
+                                                          PRBool aIsEndOffset)
 {
   // Turn a DOM Node and offset into an offset into this hypertext.
   // On failure, return null. On success, return the DOM node which contains the offset.
   NS_ENSURE_ARG_POINTER(aHyperTextOffset);
   *aHyperTextOffset = 0;
   NS_ENSURE_ARG_POINTER(aNode);
   if (aFinalAccessible) {
     *aFinalAccessible = nsnull;
@@ -604,20 +622,29 @@ nsresult nsHyperTextAccessible::DOMPoint
       childAccessible = descendantAccessible;
       break;
     }
     // This offset no longer applies because the passed-in text object is not a child
     // of the hypertext. This happens when there are nested hypertexts, e.g.
     // <div>abc<h1>def</h1>ghi</div>
     // If the passed-in DOM point was not on a direct child of the hypertext, we will
     // return the offset for that entire hypertext
-    // If the offset was after the first character of the passed in object, we will now use 1 for
+    if (aIsEndOffset) {
+      // Not inclusive, the indicated char comes at index before this offset
+      // If the end offset is after the first character of the passed in object, use 1 for
     // addTextOffset, to put us after the embedded object char. We'll only treat the offset as
     // before the embedded object char if we end at the very beginning of the child.
     addTextOffset = addTextOffset > 0;
+    }
+    else {
+      // Start offset, inclusive
+      // Make sure the offset lands on the embedded object character in order to indicate
+      // the true inner offset is inside the subtree for that link
+      addTextOffset = (TextLength(descendantAccessible) == addTextOffset) ? 1 : 0;
+    }
     descendantAccessible = parentAccessible;
   }  
 
   // Loop through, adding offsets until we reach childAccessible
   // If childAccessible is null we will end up adding up the entire length of
   // the hypertext, which is good -- it just means our offset node
   // came after the last accessible child's node
   nsCOMPtr<nsIAccessible> accessible;
@@ -694,17 +721,19 @@ nsHyperTextAccessible::GetRelativeOffset
   }
 
   // Turn the resulting node and offset into a hyperTextOffset
   PRInt32 hyperTextOffset;
   nsCOMPtr<nsIDOMNode> resultNode = do_QueryInterface(pos.mResultContent);
   NS_ENSURE_TRUE(resultNode, -1);
 
   nsCOMPtr<nsIAccessible> finalAccessible;
-  rv = DOMPointToHypertextOffset(resultNode, pos.mContentOffset, &hyperTextOffset, getter_AddRefs(finalAccessible));
+  rv = DOMPointToHypertextOffset(resultNode, pos.mContentOffset, &hyperTextOffset,
+                                 getter_AddRefs(finalAccessible),
+                                 aDirection == eDirNext);
   // If finalAccessible == nsnull, then DOMPointToHypertextOffset() searched through the hypertext
   // children without finding the node/offset position
   NS_ENSURE_SUCCESS(rv, -1);
 
   if (!finalAccessible && aDirection == eDirPrevious) {
     // If we reached the end during search, this means we didn't find the DOM point
     // and we're actually at the start of the paragraph
     hyperTextOffset = 0;
@@ -772,17 +801,26 @@ nsresult nsHyperTextAccessible::GetTextH
   // Convert offsets to frame-relative
   nsCOMPtr<nsIAccessible> startAcc;
   nsIFrame *startFrame = GetPosAndText(startOffset, endOffset, nsnull, nsnull,
                                        nsnull, getter_AddRefs(startAcc));
 
   if (!startFrame) {
     PRInt32 textLength;
     GetCharacterCount(&textLength);
-    return (aOffset < 0 || aOffset > textLength) ? NS_ERROR_FAILURE : NS_OK;
+    if (aBoundaryType == BOUNDARY_LINE_START && aOffset > 0 && aOffset == textLength) {
+      // Asking for start of line, while on last character
+      nsCOMPtr<nsPIAccessNode> startAccessNode = do_QueryInterface(startAcc);
+      if (startAccessNode) {
+        startFrame = startAccessNode->GetFrame();
+      }
+    }
+    if (!startFrame) {
+      return (aOffset < 0 || aOffset > textLength) ? NS_ERROR_FAILURE : NS_OK;
+    }
   }
 
   nsSelectionAmount amount;
   PRBool needsStart = PR_FALSE;
   switch (aBoundaryType)
   {
   case BOUNDARY_CHAR:
     amount = eSelectCharacter;
@@ -861,37 +899,41 @@ nsresult nsHyperTextAccessible::GetTextH
                                        nsnull, getter_AddRefs(endAcc));
     if (!endFrame) {
       return NS_ERROR_FAILURE;
     }
     finalEndOffset = GetRelativeOffset(presShell, endFrame, endOffset, endAcc,
                                        amount, eDirNext, needsStart);
     NS_ENSURE_TRUE(endOffset >= 0, NS_ERROR_FAILURE);
     if (finalEndOffset == aOffset) {
-      // This happens sometimes when current character at finalStartOffset 
-      // is an embedded object character representing another hypertext, that
-      // the AT really needs to dig into separately
-      ++ finalEndOffset;
+      if (aType == eGetAt && amount == eSelectWord) { 
+        // Fix word error for the first character in word: PeekOffset() will return the previous word when 
+        // aOffset points to the first character of the word, but accessibility APIs want the current word 
+        // that the first character is in
+        return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
+      }
+      PRInt32 textLength;
+      GetCharacterCount(&textLength);
+      if (finalEndOffset < textLength) {
+        // This happens sometimes when current character at finalStartOffset 
+        // is an embedded object character representing another hypertext, that
+        // the AT really needs to dig into separately
+        ++ finalEndOffset;
+      }
     }
   }
 
-  // Fix word error for the first character in word: PeekOffset() will return the previous word when 
-  // aOffset points to the first character of the word, but accessibility APIs want the current word 
-  // that the first character is in
-  if (aType == eGetAt && amount == eSelectWord && aOffset == endOffset) { 
-    return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
-  }
-
   *aStartOffset = finalStartOffset;
   *aEndOffset = finalEndOffset;
 
   NS_ASSERTION((finalStartOffset < aOffset && finalEndOffset >= aOffset) || aType != eGetBefore, "Incorrect results for GetTextHelper");
   NS_ASSERTION((finalStartOffset <= aOffset && finalEndOffset > aOffset) || aType == eGetBefore, "Incorrect results for GetTextHelper");
 
-  return GetPosAndText(finalStartOffset, finalEndOffset, &aText) ? NS_OK : NS_ERROR_FAILURE;
+  GetPosAndText(finalStartOffset, finalEndOffset, &aText);
+  return NS_OK;
 }
 
 /**
   * nsIAccessibleText impl.
   */
 NS_IMETHODIMP nsHyperTextAccessible::GetTextBeforeOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
                                                          PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
 {
@@ -1367,120 +1409,169 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 caretOffset;
   domSel->GetFocusOffset(&caretOffset);
 
   return DOMPointToHypertextOffset(caretNode, caretOffset, aCaretOffset);
 }
 
-nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon, nsISelection **aDomSel)
+nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
+                                              nsISelection **aDomSel,
+                                              nsCOMArray<nsIDOMRange>* aRanges)
 {
+  if (!mDOMNode) {
+    return NS_ERROR_FAILURE;
+  }
   if (aSelCon) {
     *aSelCon = nsnull;
   }
   if (aDomSel) {
     *aDomSel = nsnull;
   }
+  if (aRanges) {
+    aRanges->Clear();
+  }
   
+  nsCOMPtr<nsISelection> domSel;
+  nsCOMPtr<nsISelectionController> selCon;
+
   nsCOMPtr<nsIEditor> editor;
   GetAssociatedEditor(getter_AddRefs(editor));
-  if (editor) {
+  nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
+  if (peditor) {
+    // Case 1: plain text editor
+    // This is for form controls which have their own
+    // selection controller separate from the document, for example
+    // HTML:input, HTML:textarea, XUL:textbox, etc.
     if (aSelCon) {
-      editor->GetSelectionController(aSelCon);
+      editor->GetSelectionController(getter_AddRefs(selCon));
       NS_ENSURE_TRUE(*aSelCon, NS_ERROR_FAILURE);
     }
 
-    if (aDomSel) {
-      editor->GetSelection(aDomSel);
-      NS_ENSURE_TRUE(*aDomSel, NS_ERROR_FAILURE);
+    editor->GetSelection(getter_AddRefs(domSel));
+    NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
     }
+  else {
+    // Case 2: rich content subtree (can be rich editor)
+    // This uses the selection controller from the entire document
+    nsIFrame *frame = GetFrame();
+    NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
-    return NS_OK;
+    // Get the selection and selection controller
+    frame->GetSelectionController(GetPresContext(),
+                                  getter_AddRefs(selCon));
+    NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
+    selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
+                         getter_AddRefs(domSel));
+    NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
   }
 
-  nsIFrame *frame = GetFrame();
-  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
-  // Get the selection and selection controller
-  nsCOMPtr<nsISelectionController> selCon;
-  frame->GetSelectionController(GetPresContext(),
-                                getter_AddRefs(selCon));
-  NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
   if (aSelCon) {
     NS_ADDREF(*aSelCon = selCon);
   }
+  if (aDomSel) {
+    NS_ADDREF(*aDomSel = domSel);
+  }
+  if (aRanges) {
+    nsCOMPtr<nsISelection2> selection2(do_QueryInterface(domSel));
+    NS_ENSURE_TRUE(selection2, NS_ERROR_FAILURE);
 
-  if (aDomSel) {
-    nsCOMPtr<nsISelection> domSel;
-    selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
-    NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
-    NS_ADDREF(*aDomSel = domSel);
+    nsCOMPtr<nsIDOMNodeList> childNodes;
+    nsresult rv = mDOMNode->GetChildNodes(getter_AddRefs(childNodes));
+    NS_ENSURE_SUCCESS(rv, rv);
+    PRUint32 numChildren; 
+    rv = childNodes->GetLength(&numChildren);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = selection2->GetRangesForIntervalCOMArray(mDOMNode, 0,
+                                                  mDOMNode, numChildren,
+                                                  PR_TRUE, aRanges);
+    NS_ENSURE_SUCCESS(rv, rv);
+    // Remove collapsed ranges
+    PRInt32 numRanges = aRanges->Count();
+    for (PRInt32 count = 0; count < numRanges; count ++) {
+      PRBool isCollapsed;
+      (*aRanges)[count]->GetCollapsed(&isCollapsed);
+      if (isCollapsed) {
+        aRanges->RemoveObjectAt(count);
+        -- numRanges;
+        -- count;
+      }
+    }
   }
 
   return NS_OK;
 }
 
 /*
  * Gets the number of selected regions.
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
 {
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsCOMArray<nsIDOMRange> ranges;
+  nsresult rv = GetSelections(nsnull, nsnull, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  PRBool isSelectionCollapsed;
-  rv = domSel->GetIsCollapsed(&isSelectionCollapsed);
-  NS_ENSURE_SUCCESS(rv, rv);
+  *aSelectionCount = ranges.Count();
 
-  if (isSelectionCollapsed) {
-    *aSelectionCount = 0;
-    return NS_OK;
-  }
-  return domSel->GetRangeCount(aSelectionCount);
+  return NS_OK;
 }
 
 /*
  * Gets the start and end offset of the specified selection.
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum, PRInt32 *aStartOffset, PRInt32 *aEndOffset)
 {
   *aStartOffset = *aEndOffset = 0;
 
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsCOMArray<nsIDOMRange> ranges;
+  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel), &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  PRInt32 rangeCount;
-  domSel->GetRangeCount(&rangeCount);
+  PRInt32 rangeCount = ranges.Count();
   if (aSelectionNum < 0 || aSelectionNum >= rangeCount)
     return NS_ERROR_INVALID_ARG;
 
-  nsCOMPtr<nsIDOMRange> range;
-  rv = domSel->GetRangeAt(aSelectionNum, getter_AddRefs(range));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDOMRange> range = ranges[aSelectionNum];
 
+  // Get start point
   nsCOMPtr<nsIDOMNode> startNode;
   range->GetStartContainer(getter_AddRefs(startNode));
   PRInt32 startOffset;
   range->GetStartOffset(&startOffset);
-  rv = DOMPointToHypertextOffset(startNode, startOffset, aStartOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
 
+  // Get end point
   nsCOMPtr<nsIDOMNode> endNode;
   range->GetEndContainer(getter_AddRefs(endNode));
   PRInt32 endOffset;
   range->GetEndOffset(&endOffset);
-  if (startNode == endNode && startOffset == endOffset) {
-    // Shortcut for collapsed selection case (caret)
-    *aEndOffset = *aStartOffset;
-    return NS_OK;
+
+  PRInt16 rangeCompareResult;
+  rv = range->CompareBoundaryPoints(nsIDOMRange::START_TO_END, range, &rangeCompareResult);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (rangeCompareResult < 0) {
+    // Make sure start is before end, by swapping offsets
+    // This occurs when the user selects backwards in the text
+    startNode.swap(endNode);
+    PRInt32 tempOffset = startOffset;
+    startOffset = endOffset;
+    endOffset = tempOffset;
   }
-  return DOMPointToHypertextOffset(endNode, endOffset, aEndOffset);
+
+  nsCOMPtr<nsIAccessible> startAccessible;
+  rv = DOMPointToHypertextOffset(startNode, startOffset, aStartOffset, getter_AddRefs(startAccessible));
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!startAccessible) {
+    *aStartOffset = 0; // Could not find start point within this hypertext, so starts before
+  }
+
+  return DOMPointToHypertextOffset(endNode, endOffset, aEndOffset, nsnull, PR_TRUE);
 }
 
 /*
  * Changes the start and end offset of the specified selection.
  */
 NS_IMETHODIMP nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum, PRInt32 aStartOffset, PRInt32 aEndOffset)
 {
   nsCOMPtr<nsISelection> domSel;
@@ -1500,45 +1591,66 @@ NS_IMETHODIMP nsHyperTextAccessible::Set
     return NS_ERROR_INVALID_ARG;
   }
   else {
     domSel->GetRangeAt(aSelectionNum, getter_AddRefs(range));
     NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
   }
 
   nsIFrame *endFrame;
-  nsIFrame *startFrame = GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrame);
-  NS_ENSURE_TRUE(startFrame, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIAccessible> startAcc, endAcc;
+  nsIFrame *startFrame = GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrame, nsnull,
+                                       getter_AddRefs(startAcc), getter_AddRefs(endAcc));
 
   nsCOMPtr<nsIPresShell> shell = GetPresShell();
 
-  nsIContent *startParentContent = startFrame->GetContent();
-  PRInt32 startOffset;
-  if (startFrame->GetType() != nsAccessibilityAtoms::textFrame) {
-    nsIContent *newParent = startParentContent->GetParent();
-    startOffset = newParent->IndexOf(startParentContent);
-    startParentContent = newParent;
+  if (!startFrame) { // past the end of the hyper text
+    nsCOMPtr<nsIAccessNode> startAccessNode = do_QueryInterface(startAcc);
+    NS_ENSURE_TRUE(startAccessNode, NS_ERROR_FAILURE);
+    nsCOMPtr<nsIDOMNode> node;
+    startAccessNode->GetDOMNode(getter_AddRefs(node));
+    NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
+    rv = range->SetStartAfter(node);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
   else {
-    // We have a rendered offset into the text frame, and it needs to be
-    // a content offset for us to set the caret
-    nsIFrame *startPrimaryFrame =
-      shell->GetPrimaryFrameFor(startFrame->GetContent());
-    rv = RenderedToContentOffset(startPrimaryFrame, aStartOffset, &startOffset);
+    nsIContent *startParentContent = startFrame->GetContent();
+    PRInt32 startOffset;
+    if (startFrame->GetType() != nsAccessibilityAtoms::textFrame) {
+      nsIContent *newParent = startParentContent->GetParent();
+      startOffset = newParent->IndexOf(startParentContent);
+      startParentContent = newParent;
+    }
+    else {
+      // We have a rendered offset into the text frame, and it needs to be
+      // a content offset for us to set the caret
+      nsIFrame *startPrimaryFrame =
+        shell->GetPrimaryFrameFor(startFrame->GetContent());
+      rv = RenderedToContentOffset(startPrimaryFrame, aStartOffset, &startOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    nsCOMPtr<nsIDOMNode> startParentNode(do_QueryInterface(startParentContent));
+    NS_ENSURE_TRUE(startParentNode, NS_ERROR_FAILURE);
+    rv = range->SetStart(startParentNode, startOffset);
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  nsCOMPtr<nsIDOMNode> startParentNode(do_QueryInterface(startParentContent));
-  NS_ENSURE_TRUE(startParentNode, NS_ERROR_FAILURE);
-  rv = range->SetStart(startParentNode, startOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
 
   if (isOnlyCaret) { 
     rv = range->Collapse(PR_TRUE);
     NS_ENSURE_SUCCESS(rv, rv);
   }
+  else if (!endFrame) {  // past the end of the hyper text
+    nsCOMPtr<nsIAccessNode> endAccessNode = do_QueryInterface(endAcc);
+    NS_ENSURE_TRUE(endAccessNode, NS_ERROR_FAILURE);
+    nsCOMPtr<nsIDOMNode> node;
+    endAccessNode->GetDOMNode(getter_AddRefs(node));
+    NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
+    rv = range->SetEndAfter(node);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
   else {
     nsIContent *endParentContent = endFrame->GetContent();
     PRInt32 endOffset;
     if (endFrame->GetType() != nsAccessibilityAtoms::textFrame) {
       nsIContent *newParent = endParentContent->GetParent();
       endOffset = newParent->IndexOf(endParentContent);
       endParentContent = newParent;
     }
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -105,20 +105,28 @@ public:
     *                      if >=0 and aNode is text, this represents a char offset
     *                      if >=0 and aNode is not text, this represents a child node offset
     * @param aResultOffset - the character offset into the current
     *                        nsHyperTextAccessible
     * @param aFinalAccessible [optional] - returns the accessible child which
     *                                      contained the offset, if it is within
     *                                      the current nsHyperTextAccessible,
     *                                      otherwise it is set to nsnull.
+    * @param aIsEndOffset - if PR_TRUE, then then this offset is not inclusive. The character
+    *                       indicated by the offset returned is at [offset - 1]. This means
+    *                       if the passed-in offset is really in a descendant, then the offset returned
+    *                       will come just after the relevant embedded object characer.
+    *                       If PR_FALSE, then the offset is inclusive. The character indicated
+    *                       by the offset returned is at [offset]. If the passed-in offset in inside a
+    *                       descendant, then the returned offset will be on the relevant embedded object char.
     */
   nsresult DOMPointToHypertextOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset,
                                      PRInt32 *aHypertextOffset,
-                                     nsIAccessible **aFinalAccessible = nsnull);
+                                     nsIAccessible **aFinalAccessible = nsnull,
+                                     PRBool aIsEndOffset = PR_FALSE);
 
 protected:
   /*
    * This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
    * @param aType, eGetBefore, eGetAt, eGetAfter
    * @param aBoundaryType, char/word-start/word-end/line-start/line-end/paragraph/attribute
    * @param aOffset, offset into the hypertext to start from
    * @param *aStartOffset, the resulting start offset for the returned substring
@@ -179,17 +187,26 @@ protected:
                           nsIFrame **aEndFrame = nsnull,
                           nsIntRect *aBoundsRect = nsnull,
                           nsIAccessible **aStartAcc = nsnull,
                           nsIAccessible **aEndAcc = nsnull);
 
   nsIntRect GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset, PRUint32 aEndRenderedOffset);
 
   // Selection helpers
-  nsresult GetSelections(nsISelectionController **aSelCon, nsISelection **aDomSel);
+
+  /**
+   * Get the relevant selection interfaces and ranges for the current hyper text
+   * @param aSelCon      The selection controller for the current hyper text, or nsnull if not needed
+   * @param aDomSel      The selection interface for the current hyper text, or nsnull if not needed
+   * @param aRanges      The selected ranges within the current subtree, or nsnull if not needed
+   */
+  nsresult GetSelections(nsISelectionController **aSelCon,
+                         nsISelection **aDomSel = nsnull,
+                         nsCOMArray<nsIDOMRange>* aRanges = nsnull);
   nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,
                               NS_HYPERTEXTACCESSIBLE_IMPL_CID)
 
 #endif  // _nsHyperTextAccessible_H_
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -328,78 +328,88 @@ nsAccessibleWrap::get_accDescription(VAR
     return E_FAIL;
 
   // For items that are a choice in a list of choices, use MSAA description
   // field to shoehorn positional info, it's becoming a defacto standard use for
   // the field.
 
   nsAutoString description;
 
-  // Try nsIAccessible::groupPosition to make a positional description string.
-  PRInt32 groupLevel;
-  PRInt32 similarItemsInGroup;
-  PRInt32 positionInGroup;
+  // Try to get group attributes to make a positional description string. We
+  // can't use nsIAccessible::groupPosition because the method isn't supposed
+  // to work with elements exposing 'level' attribute only (like HTML headings).
+  nsCOMPtr<nsIPersistentProperties> attributes;
+  nsresult rv = xpAccessible->GetAttributes(getter_AddRefs(attributes));
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!attributes)
+    return NS_ERROR_FAILURE;
 
-  nsresult rv = xpAccessible->GroupPosition(&groupLevel, &similarItemsInGroup,
-                                            &positionInGroup);
-  if (NS_SUCCEEDED(rv)) {
-    if (positionInGroup > 0) {
-      if (groupLevel > 0) {
-        // XXX: How do we calculate the number of children? Now we append
-        // " with [numChildren]c" for tree item. In the future we may need to
-        // use the ARIA owns property to calculate that if it's present.
-        PRInt32 numChildren = 0;
+  PRInt32 groupLevel = 0;
+  PRInt32 itemsInGroup = 0;
+  PRInt32 positionInGroup = 0;
+  nsAccUtils::GetAccGroupAttrs(attributes, &groupLevel, &positionInGroup,
+                               &itemsInGroup);
+
+  if (positionInGroup > 0) {
+    if (groupLevel > 0) {
+      // XXX: How do we calculate the number of children? Now we append
+      // " with [numChildren]c" for tree item. In the future we may need to
+      // use the ARIA owns property to calculate that if it's present.
+      PRInt32 numChildren = 0;
 
-        PRUint32 currentRole = 0;
-        rv = xpAccessible->GetFinalRole(&currentRole);
-        if (NS_SUCCEEDED(rv) &&
-            currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
-          nsCOMPtr<nsIAccessible> child;
-          xpAccessible->GetFirstChild(getter_AddRefs(child));
-          while (child) {
-            child->GetFinalRole(&currentRole);
-            if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
-              nsCOMPtr<nsIAccessible> groupChild;
-              child->GetFirstChild(getter_AddRefs(groupChild));
-              while (groupChild) {
-                groupChild->GetFinalRole(&currentRole);
-                numChildren +=
-                  (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
-                nsCOMPtr<nsIAccessible> nextGroupChild;
-                groupChild->GetNextSibling(getter_AddRefs(nextGroupChild));
-                groupChild.swap(nextGroupChild);
-              }
-              break;
+      PRUint32 currentRole = 0;
+      rv = xpAccessible->GetFinalRole(&currentRole);
+      if (NS_SUCCEEDED(rv) &&
+          currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
+        nsCOMPtr<nsIAccessible> child;
+        xpAccessible->GetFirstChild(getter_AddRefs(child));
+        while (child) {
+          child->GetFinalRole(&currentRole);
+          if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
+            nsCOMPtr<nsIAccessible> groupChild;
+            child->GetFirstChild(getter_AddRefs(groupChild));
+            while (groupChild) {
+              groupChild->GetFinalRole(&currentRole);
+              numChildren +=
+                (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
+              nsCOMPtr<nsIAccessible> nextGroupChild;
+              groupChild->GetNextSibling(getter_AddRefs(nextGroupChild));
+              groupChild.swap(nextGroupChild);
             }
-            nsCOMPtr<nsIAccessible> nextChild;
-            child->GetNextSibling(getter_AddRefs(nextChild));
-            child.swap(nextChild);
+            break;
           }
+          nsCOMPtr<nsIAccessible> nextChild;
+          child->GetNextSibling(getter_AddRefs(nextChild));
+          child.swap(nextChild);
         }
-
-        if (numChildren) {
-          nsTextFormatter::ssprintf(description,
-                                    NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
-                                    groupLevel, positionInGroup,
-                                    similarItemsInGroup + 1, numChildren);
-        } else {
-          nsTextFormatter::ssprintf(description,
-                                    NS_LITERAL_STRING("L%d, %d of %d").get(),
-                                    groupLevel, positionInGroup,
-                                    similarItemsInGroup + 1);
-        }
-      } else { // Position has no level
-        nsTextFormatter::ssprintf(description,
-                                  NS_LITERAL_STRING("%d of %d").get(),
-                                  positionInGroup, similarItemsInGroup + 1);
       }
 
-      *pszDescription = ::SysAllocString(description.get());
-      return S_OK;
+      if (numChildren) {
+        nsTextFormatter::ssprintf(description,
+                                  NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
+                                  groupLevel, positionInGroup, itemsInGroup,
+                                  numChildren);
+      } else {
+        nsTextFormatter::ssprintf(description,
+                                  NS_LITERAL_STRING("L%d, %d of %d").get(),
+                                  groupLevel, positionInGroup, itemsInGroup);
+      }
+    } else { // Position has no level
+      nsTextFormatter::ssprintf(description,
+                                NS_LITERAL_STRING("%d of %d").get(),
+                                positionInGroup, itemsInGroup);
     }
+  } else if (groupLevel > 0) {
+    nsTextFormatter::ssprintf(description, NS_LITERAL_STRING("L%d").get(),
+                              groupLevel);
+  }
+
+  if (!description.IsEmpty()) {
+    *pszDescription = ::SysAllocString(description.get());
+    return S_OK;
   }
 
   xpAccessible->GetDescription(description);
   if (!description.IsEmpty()) {
     // Signal to screen readers that this description is speakable
     // and is not a formatted positional information description
     // Don't localize the "Description: " part of this string, it will be
     // parsed out by assistive technologies.
@@ -461,17 +471,17 @@ STDMETHODIMP nsAccessibleWrap::get_accRo
 
   accessNode->GetDOMNode(getter_AddRefs(domNode));
   nsIContent *content = GetRoleContent(domNode);
   if (!content)
     return E_FAIL;
 
   if (content->IsNodeOfType(nsINode::eELEMENT)) {
     nsAutoString roleString;
-    if (msaaRole != ROLE_SYSTEM_CLIENT && !GetRoleAttribute(content, roleString)) {
+    if (msaaRole != ROLE_SYSTEM_CLIENT && !GetARIARole(content, roleString)) {
       nsINodeInfo *nodeInfo = content->NodeInfo();
       nodeInfo->GetName(roleString);
       nsAutoString nameSpaceURI;
       nodeInfo->GetNamespaceURI(nameSpaceURI);
       if (!nameSpaceURI.IsEmpty()) {
         // Only append name space if different from that of current document
         roleString += NS_LITERAL_STRING(", ") + nameSpaceURI;
       }
@@ -966,17 +976,17 @@ STDMETHODIMP nsAccessibleWrap::accHitTes
         // Has already been shut down
         pvarChild->vt = VT_EMPTY;
         return E_FAIL;
       }
     }
   } else {
     // no child at that point
     pvarChild->vt = VT_EMPTY;
-    return E_FAIL;
+    return S_FALSE;
   }
 
   return S_OK;
 }
 
 STDMETHODIMP nsAccessibleWrap::accDoDefaultAction(
       /* [optional][in] */ VARIANT varChild)
 {
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -92,16 +92,19 @@ nsXULColorPickerTileAccessible::GetState
 
 NS_IMETHODIMP nsXULColorPickerTileAccessible::GetName(nsAString& _retval)
 {
   return GetXULName(_retval);
 }
 
 NS_IMETHODIMP nsXULColorPickerTileAccessible::GetValue(nsAString& _retval)
 {
+  if (!mDOMNode)
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
   NS_ASSERTION(element, "No XUL Element for colorpicker");
   return element->GetAttribute(NS_LITERAL_STRING("color"), _retval);
 }
 
 /**
   * XUL Color Picker
   */
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -43,34 +43,112 @@
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULTextboxElement.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsCaseTreatment.h"
 
-/**
-  * Selects, Listboxes and Comboboxes, are made up of a number of different
-  *  widgets, some of which are shared between the two. This file contains
-  *  all of the widgets for both of the Selects, for XUL only.
-  *  (except nsXULRadioGroupAccessible which inherits
-  *   nsXULSelectableAccessible so that it supports nsIAccessibleSelectable)
-  *
-  *  Listbox:
-  *     - nsXULListboxAccessible              <richlistbox/>
-  *         - nsXULListitemAccessible         <richlistitem/>
-  *
-  *  Comboboxes:
-  *     - nsXULComboboxAccessible             <menulist/>
-  *        - nsXULMenuAccessible              <menupopup/>
-  *            - nsXULMenuitemAccessible      <menuitem/>
-  */
+////////////////////////////////////////////////////////////////////////////////
+// nsXULColumnsAccessible
+
+nsXULColumnsAccessible::
+  nsXULColumnsAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
+  nsAccessibleWrap(aDOMNode, aShell)
+{
+}
+
+NS_IMETHODIMP
+nsXULColumnsAccessible::GetRole(PRUint32 *aRole)
+{
+  NS_ENSURE_ARG_POINTER(aRole);
+
+  *aRole = nsIAccessibleRole::ROLE_LIST;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULColumnsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
+{
+  NS_ENSURE_ARG_POINTER(aState);
+
+  if (aExtraState)
+    *aExtraState = 0;
+
+  *aState = nsIAccessibleStates::STATE_READONLY;
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULColumnItemAccessible
+
+nsXULColumnItemAccessible::
+  nsXULColumnItemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
+  nsLeafAccessible(aDOMNode, aShell)
+{
+}
+
+NS_IMETHODIMP
+nsXULColumnItemAccessible::GetRole(PRUint32 *aRole)
+{
+  NS_ENSURE_ARG_POINTER(aRole);
+
+  *aRole = nsIAccessibleRole::ROLE_COLUMNHEADER;
+  return NS_OK;
+}
 
-/** ----- nsXULListboxAccessible ----- */
+NS_IMETHODIMP
+nsXULColumnItemAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
+{
+  NS_ENSURE_ARG_POINTER(aState);
+
+  if (aExtraState)
+    *aExtraState = 0;
+
+  *aState = nsIAccessibleStates::STATE_READONLY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULColumnItemAccessible::GetName(nsAString& aName)
+{
+  return GetXULName(aName);
+}
+
+NS_IMETHODIMP
+nsXULColumnItemAccessible::GetNumActions(PRUint8 *aNumActions)
+{
+  NS_ENSURE_ARG_POINTER(aNumActions);
+
+  *aNumActions = 1;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULColumnItemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  aName.AssignLiteral("click");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
+{
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  return DoCommand();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULListboxAccessible
 
 /** Constructor */
 nsXULListboxAccessible::nsXULListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
 nsXULSelectableAccessible(aDOMNode, aShell)
 {
 }
 
 /**
@@ -141,16 +219,19 @@ nsXULMenuitemAccessible(aDOMNode, aShell
 NS_IMPL_ISUPPORTS_INHERITED0(nsXULListitemAccessible, nsAccessible)
 
 /**
   * If there is a Listcell as a child ( not anonymous ) use it, otherwise
   *   default to getting the name from GetXULName
   */
 NS_IMETHODIMP nsXULListitemAccessible::GetName(nsAString& _retval)
 {
+  if (!mDOMNode)
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIDOMNode> child;
   if (NS_SUCCEEDED(mDOMNode->GetFirstChild(getter_AddRefs(child)))) {
     nsCOMPtr<nsIDOMElement> childElement (do_QueryInterface(child));
     if (childElement) {
       nsAutoString tagName;
       childElement->GetLocalName(tagName);
       if (tagName.EqualsLiteral("listcell")) {
         childElement->GetAttribute(NS_LITERAL_STRING("label"), _retval);
@@ -334,16 +415,19 @@ NS_IMETHODIMP nsXULComboboxAccessible::G
     return focusedOptionAccessible->GetDescription(aDescription);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
 {
+  if (!mDOMNode)
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
 
   if (content->NodeInfo()->Equals(nsAccessibilityAtoms::textbox, kNameSpaceID_XUL) ||
       content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::editable,
                            nsAccessibilityAtoms::_true, eIgnoreCase)) {
     // Both the XUL <textbox type="autocomplete"> and <menulist editable="true"> widgets
     // use nsXULComboboxAccessible. We need to walk the anonymous children for these
     // so that the entry field is a child
--- a/accessible/src/xul/nsXULSelectAccessible.h
+++ b/accessible/src/xul/nsXULSelectAccessible.h
@@ -35,23 +35,59 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef __nsXULSelectAccessible_h__
 #define __nsXULSelectAccessible_h__
 
 #include "nsCOMPtr.h"
 #include "nsXULMenuAccessible.h"
+#include "nsBaseWidgetAccessible.h"
 
 class nsIWeakReference;
 
 /**
-  * Selects, Listboxes and Comboboxes, are made up of a number of different
-  *  widgets, some of which are shared between the two. This file contains 
-  *  all of the widgets for both of the Selects, for XUL only.
+ * nsXULColumnsAccessible are accessible for list and tree columns elements
+ * (xul:treecols and xul:listcols).
+ */
+class nsXULColumnsAccessible : public nsAccessibleWrap
+{
+public:
+  nsXULColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
+
+  // nsIAccessible
+  NS_IMETHOD GetRole(PRUint32 *aRole);
+  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+};
+
+/**
+ * nsXULColumnAccessible are accessibles for list and tree column elements
+ * (xul:listcol and xul:treecol).
+ */
+class nsXULColumnItemAccessible : public nsLeafAccessible
+{
+public:
+  nsXULColumnItemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
+
+  // nsIAccessible
+  NS_IMETHOD GetRole(PRUint32 *aRole);
+  NS_IMETHOD GetName(nsAString& aName);
+  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+
+  NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+  NS_IMETHOD DoAction(PRUint8 aIndex);
+
+  enum { eAction_Click = 0 };
+};
+
+/**
+  * Listboxes (xul:listbox) and Comboboxes (xul:menulist) are made up of a
+  * number of different widgets, some of which are shared between the two.
+  * This file contains all of the widgets for both of them, for XUL only.
   *
   *  Listbox:
   *     - nsXULListboxAccessible
   *        - nsXULSelectOptionAccessible
   *
   *  Comboboxes:
   *     - nsXULComboboxAccessible      <menulist />
   *        - nsXULMenuAccessible          <menupopup />
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -499,18 +499,22 @@ NS_IMETHODIMP nsXULTreeAccessible::Selec
       if (selection)
         selection->SelectAll();
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeAccessible::GetCachedTreeitemAccessible(PRInt32 aRow, nsITreeColumn* aColumn, nsIAccessible** aAccessible)
+NS_IMETHODIMP
+nsXULTreeAccessible::GetCachedTreeitemAccessible(PRInt32 aRow,
+                                                 nsITreeColumn* aColumn,
+                                                 nsIAccessible** aAccessible)
 {
+  NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   NS_ASSERTION(mAccessNodeCache, "No accessibility cache for tree");
   NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
 
   nsCOMPtr<nsITreeColumn> col;
 #ifdef MOZ_ACCESSIBILITY_ATK
   col = aColumn;
@@ -519,18 +523,22 @@ NS_IMETHODIMP nsXULTreeAccessible::GetCa
 
   if (!col && mTree) {
     nsCOMPtr<nsITreeColumns> cols;
     mTree->GetColumns(getter_AddRefs(cols));
     if (cols)
       cols->GetKeyColumn(getter_AddRefs(col));
   }
 
-  if (col)
-     col->GetIndex(&columnIndex);
+  // Do not create accessible for treeitem if there is no column in the tree
+  // because it doesn't render treeitems properly.
+  if (!col)
+    return NS_OK;
+
+  col->GetIndex(&columnIndex);
 
   nsCOMPtr<nsIAccessNode> accessNode;
   GetCacheEntry(*mAccessNodeCache, (void*)(aRow * kMaxTreeColumns + columnIndex), getter_AddRefs(accessNode));
   if (!accessNode)
   {
     accessNode = new nsXULTreeitemAccessibleWrap(this, mDOMNode, mWeakShell, aRow, col);
     nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(accessNode));
     if (!privateAccessNode)
@@ -1036,60 +1044,28 @@ NS_IMETHODIMP nsXULTreeitemAccessible::G
   } else { 
 #endif
     return nsAccessible::GetAccessibleRelated(aRelationType, aRelated);
 #ifdef MOZ_ACCESSIBILITY_ATK
   }
 #endif
 }
 
-// ---------- nsXULTreeColumnsAccessible ----------
-
-nsXULTreeColumnsAccessible::nsXULTreeColumnsAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
-nsAccessibleWrap(aDOMNode, aShell)
+////////////////////////////////////////////////////////////////////////////////
+//  nsXULTreeColumnsAccessible
+nsXULTreeColumnsAccessible::
+  nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
+  nsXULColumnsAccessible(aDOMNode, aShell)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeColumnsAccessible, nsAccessible)
-
 NS_IMETHODIMP
-nsXULTreeColumnsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
-{
-  if (aExtraState)
-    *aExtraState = 0;
-
-  *aState = nsIAccessibleStates::STATE_READONLY;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::GetRole(PRUint32 *_retval)
+nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSibling)
 {
-  *_retval = nsIAccessibleRole::ROLE_LIST;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::GetNumActions(PRUint8 *_retval)
-{
-  *_retval = 1;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
-{
-  if (aIndex == eAction_Click) {
-    aName.AssignLiteral("click");
-    return NS_OK;
-  }
-
-  return NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSibling) 
-{
-  nsresult ret = nsAccessible::GetNextSibling(aNextSibling);
+  nsresult ret = nsXULColumnsAccessible::GetNextSibling(aNextSibling);
 
   if (*aNextSibling == nsnull) { // if there is not other sibling, use the first row as its sibling
     nsCOMPtr<nsITreeBoxObject> tree;
     nsCOMPtr<nsITreeView> treeView;
 
     nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
     if (tree) {
       tree->GetView(getter_AddRefs(treeView));
@@ -1101,78 +1077,11 @@ NS_IMETHODIMP nsXULTreeColumnsAccessible
           nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
           NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
           ret = treeCache->GetCachedTreeitemAccessible(0, column, aNextSibling);
         }
       }
     }
   }
 
-  return ret;  
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling) 
-{  
-  return nsAccessible::GetPreviousSibling(aPreviousSibling);
-}
-
-NS_IMETHODIMP nsXULTreeColumnsAccessible::DoAction(PRUint8 index)
-{
-  if (index == eAction_Click)
-    return NS_OK;
-
-  return NS_ERROR_INVALID_ARG;
-}
-
-// ---------- nsXULTreeColumnitemAccessible ----------
-
-nsXULTreeColumnitemAccessible::nsXULTreeColumnitemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
-nsLeafAccessible(aDOMNode, aShell)
-{
-}
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeColumnitemAccessible, nsLeafAccessible)
-
-NS_IMETHODIMP
-nsXULTreeColumnitemAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
-{
-  if (aExtraState)
-    *aExtraState = 0;
-
-  *aState = nsIAccessibleStates::STATE_READONLY;
-  return NS_OK;
+  return ret;
 }
 
-NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetName(nsAString& _retval)
-{
-  return GetXULName(_retval);
-}
-
-NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetRole(PRUint32 *_retval)
-{
-  *_retval = nsIAccessibleRole::ROLE_COLUMNHEADER;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetNumActions(PRUint8 *_retval)
-{
-  *_retval = 1;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
-{
-  if (aIndex == eAction_Click) {
-    aName.AssignLiteral("click");
-    return NS_OK;
-  }
-
-  return NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP nsXULTreeColumnitemAccessible::DoAction(PRUint8 index)
-{
-  if (index == eAction_Click) {
-    return DoCommand();
-  }
-
-  return NS_ERROR_INVALID_ARG;
-}
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -33,17 +33,16 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef __nsXULTreeAccessible_h__
 #define __nsXULTreeAccessible_h__
 
-#include "nsBaseWidgetAccessible.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeView.h"
 #include "nsITreeColumns.h"
 #include "nsXULSelectAccessible.h"
 #include "nsIAccessibleTreeCache.h"
 
 
 /*
@@ -130,51 +129,18 @@ public:
 protected:
   PRBool IsExpandable();
   nsCOMPtr<nsITreeBoxObject> mTree;
   nsCOMPtr<nsITreeView> mTreeView;
   PRInt32 mRow;
   nsCOMPtr<nsITreeColumn> mColumn;
 };
 
-class nsXULTreeColumnsAccessible : public nsAccessibleWrap
+class nsXULTreeColumnsAccessible : public nsXULColumnsAccessible
 {
 public:
-  enum { eAction_Click = 0 };
-
-  NS_DECL_ISUPPORTS_INHERITED
-
   nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsXULTreeColumnsAccessible() {}
-
-  /* ----- nsIAccessible ----- */
-  NS_IMETHOD GetRole(PRUint32 *_retval);
-  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-  NS_IMETHOD GetNumActions(PRUint8 *_retval);
-  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
-
-  NS_IMETHOD GetNextSibling(nsIAccessible **_retval); 
-  NS_IMETHOD GetPreviousSibling(nsIAccessible **_retval); 
-
-  NS_IMETHOD DoAction(PRUint8 index);
-};
 
-class nsXULTreeColumnitemAccessible : public nsLeafAccessible
-{
-public:
-  enum { eAction_Click = 0 };
-
-  NS_DECL_ISUPPORTS_INHERITED
-
-  nsXULTreeColumnitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsXULTreeColumnitemAccessible() {}
-
-  /* ----- nsIAccessible ----- */
-  NS_IMETHOD GetName(nsAString& _retval);
-  NS_IMETHOD GetRole(PRUint32 *_retval);
-  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-  NS_IMETHOD GetNumActions(PRUint8 *_retval);
-  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
-
-  NS_IMETHOD DoAction(PRUint8 index);
+  // nsIAccessible
+  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
 };
 
 #endif
--- a/browser/Makefile.in
+++ b/browser/Makefile.in
@@ -37,17 +37,17 @@
 
 DEPTH		= ..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(topsrcdir)/config/config.mk
 
-DIRS = base components locales themes app fuel
+DIRS = base components locales themes fuel app
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT)
 ifdef MOZ_INSTALLER
 DIRS += installer/windows
 
 ifdef MOZ_BRANDING_DIRECTORY
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -199,19 +199,18 @@ var PlacesCommandHook = {
   /**
    * Adds a bookmark to the page loaded in the current tab. 
    */
   bookmarkCurrentPage: function PCH_bookmarkCurrentPage(aShowEditUI, aParent) {
     // dock the panel to the star icon if it is visible, otherwise dock
     // it to the content area
     var starIcon = document.getElementById("star-button");
     if (starIcon && isElementVisible(starIcon)) {
-      var dockTo = document.getElementById("go-button-bottom");
       this.bookmarkPage(getBrowser().selectedBrowser, aParent, aShowEditUI,
-                        dockTo, "after_start");
+                        starIcon, "after_start");
     }
     else {
       this.bookmarkPage(getBrowser().selectedBrowser, aParent, aShowEditUI,
                         getBrowser(), "overlap");
     }
   },
 
   /**
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -255,16 +255,17 @@
     <key id="key_findPrevious" key="&findAgainCmd.commandkey;" command="cmd_findPrevious" modifiers="accel,shift"/>
     <key keycode="&findAgainCmd.commandkey2;" command="cmd_findAgain"/>
     <key keycode="&findAgainCmd.commandkey2;"  command="cmd_findPrevious" modifiers="shift"/>
 
     <key id="addBookmarkAsKb" key="&addCurPageAsCmd.commandkey;" command="Browser:AddBookmarkAs" modifiers="accel"/>
 # Accel+Shift+A-F are reserved on GTK2
 #ifndef MOZ_WIDGET_GTK2
     <key id="bookmarkAllTabsKb" key="&addCurPageAsCmd.commandkey;" command="Browser:BookmarkAllTabs" modifiers="accel,shift"/>
+    <key id="manBookmarkKb" key="&bookmarksSidebarCmd.commandkey;" command="Browser:ShowBookmarks" modifiers="accel,shift"/>
 #endif
     <key id="viewBookmarksSidebarKb" key="&bookmarksSidebarCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
 #ifdef XP_WIN
 # Cmd+I is conventially mapped to Info on MacOS X, thus it should not be 
 # overridden for other purposes there. 
     <key id="viewBookmarksSidebarWinKb" key="&bookmarksSidebarWinCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
 #endif
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -72,32 +72,29 @@ const BROWSER_ADD_BM_FEATURES = "centers
 #endif
 
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_XUL = "application/vnd.mozilla.xul+xml";
 
 // We use this once, for Clear Private Data
 const GLUE_CID = "@mozilla.org/browser/browserglue;1";
 
-var gRDF = null;
 var gGlobalHistory = null;
 var gURIFixup = null;
-var gPageStyleButton = null;
 var gCharsetMenu = null;
 var gLastBrowserCharset = null;
 var gPrevCharset = null;
 var gURLBar = null;
 var gFindBar = null;
 var gProxyButton = null;
 var gProxyFavIcon = null;
 var gProxyDeck = null;
 var gNavigatorBundle = null;
 var gIsLoadingBlank = false;
 var gLastValidURLStr = "";
-var gLastValidURL = null;
 var gMustLoadSidebar = false;
 var gProgressMeterPanel = null;
 var gProgressCollapseTimer = null;
 var gPrefService = null;
 var appCore = null;
 var gBrowser = null;
 var gNavToolbox = null;
 var gSidebarCommand = "";
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -278,17 +278,18 @@
             </hbox>
           </stack>
         </hbox>
       </toolbaritem>
 
       <toolbaritem id="search-container" title="&searchItem.title;" 
                    align="center" class="chromeclass-toolbar-additional"
                    flex="100" persist="width">
-        <searchbar id="searchbar" flex="1" chromedir="&locale.dir;"/>
+        <searchbar id="searchbar" flex="1" chromedir="&locale.dir;"
+                   newlines="replacewithspaces"/>
       </toolbaritem>
 
       <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&printButton.label;" command="cmd_print"
                      tooltiptext="&printButton.tooltip;"/>
 
       <toolbaritem id="throbber-box" title="&throbberItem.title;" align="center" pack="center">
         <button id="navigator-throbber" disabled="true"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -636,41 +636,46 @@ nsContextMenu.prototype = {
   openLinkInTab: function() {
     openNewTabWith(this.linkURL, this.target.ownerDocument, null, null, false);
   },
 
   // Open frame in a new tab.
   openFrameInTab: function() {
     var doc = this.target.ownerDocument;
     var frameURL = doc.documentURIObject.spec;
+    var referrer = doc.referrer;
 
-    openNewTabWith(frameURL, null, null, null, false, makeURI(doc.referrer));
+    openNewTabWith(frameURL, null, null, null, false,
+                   referrer ? makeURI(referrer) : null);
   },
 
   // Reload clicked-in frame.
   reloadFrame: function() {
     this.target.ownerDocument.location.reload();
   },
 
   // Open clicked-in frame in its own window.
   openFrame: function() {
     var doc = this.target.ownerDocument;
     var frameURL = doc.documentURIObject.spec;
+    var referrer = doc.referrer;
 
-    openNewWindowWith(frameURL, null, null, false, makeURI(doc.referrer));
+    openNewWindowWith(frameURL, null, null, false,
+                      referrer ? makeURI(referrer) : null);
   },
 
   // Open clicked-in frame in the same window.
   showOnlyThisFrame: function() {
     var doc = this.target.ownerDocument;
     var frameURL = doc.documentURIObject.spec;
 
     urlSecurityCheck(frameURL, this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-    this.browser.loadURI(frameURL, makeURI(doc.referrer));
+    var referrer = doc.referrer;
+    this.browser.loadURI(frameURL, referrer ? makeURI(referrer) : null);
   },
 
   // View Partial Source
   viewPartialSource: function(aContext) {
     var focusedWindow = document.commandDispatcher.focusedWindow;
     if (focusedWindow == window)
       focusedWindow = content;
 
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -86,17 +86,17 @@
 
     <!-- permissions tab -->
     <command id="cmd_imageDef"      oncommand="onCheckboxClick('image');"/>
     <command id="cmd_popupDef"      oncommand="onCheckboxClick('popup');"/>
     <command id="cmd_cookieDef"     oncommand="onCheckboxClick('cookie');"/>
     <command id="cmd_installDef"    oncommand="onCheckboxClick('install');"/>
     <command id="cmd_imageToggle"   oncommand="onRadioClick('image');"/>
     <command id="cmd_popupToggle"   oncommand="onRadioClick('popup');"/>
-    <command id="cmd_cookieToggle"  oncommand="onRadioClick('cookies');"/>
+    <command id="cmd_cookieToggle"  oncommand="onRadioClick('cookie');"/>
     <command id="cmd_installToggle" oncommand="onRadioClick('install');"/>
   </commandset>
 
   <keyset>
     <key key="&closeWindow.key;" modifiers="accel" command="cmd_close"/>
     <key keycode="VK_ESCAPE"                       command="cmd_close"/>
 #ifdef XP_MACOSX
     <key key="."                 modifiers="meta"  command="cmd_close"/>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -61,17 +61,17 @@
     <resources>
       <stylesheet src="chrome://browser/skin/browser.css"/>
     </resources>
 
     <content>
       <xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
       <xul:tabbox anonid="tabbox" flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
                   onselect="if (!('updateCurrentBrowser' in this.parentNode) || event.target.localName != 'tabpanels') return; this.parentNode.updateCurrentBrowser();">
-        <xul:hbox class="tab-drop-indicator-bar">
+        <xul:hbox class="tab-drop-indicator-bar" collapsed="true" chromedir="&locale.dir;">
           <xul:hbox class="tab-drop-indicator" mousethrough="always"/>
         </xul:hbox>
         <xul:hbox class="tabbrowser-strip" collapsed="true" tooltip="_child" context="_child"
                   anonid="strip"
                   ondraggesture="nsDragAndDrop.startDrag(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragover="nsDragAndDrop.dragOver(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragdrop="nsDragAndDrop.drop(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragexit="nsDragAndDrop.dragExit(event, this.parentNode.parentNode); event.stopPropagation();">
@@ -1270,17 +1270,21 @@
 
               if (aPostData === undefined)
                 aPostData = null;
               const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
               var flags = nsIWebNavigation.LOAD_FLAGS_NONE;
               if (aAllowThirdPartyFixup) {
                 flags = nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
               }
-              b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
+              try {
+                b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
+              }
+              catch (ex) {
+              }
             }
 
             // |setTimeout| here to ensure we're post reflow
             var _delayedUpdate = function(aTabContainer) {
               aTabContainer.adjustTabstrip();
 
               if (aTabContainer.selectedItem != t)
                 aTabContainer._notifyBackgroundTab(t);
@@ -1744,24 +1748,25 @@
         <parameter name="aDragSession"/>
         <body>
           <![CDATA[
             if (aDragSession.sourceNode &&
                 aDragSession.sourceNode.parentNode == this.mTabContainer &&
                 (aEvent.screenX >= aDragSession.sourceNode.boxObject.screenX &&
                  aEvent.screenX <= (aDragSession.sourceNode.boxObject.screenX +
                                     aDragSession.sourceNode.boxObject.width)))
-                return false;
+              return false;
             return true;
           ]]>
         </body>
       </method>
 
       <field name="mDragTime">0</field>
       <field name="mDragOverDelay">350</field>
+
       <method name="onDragOver">
         <parameter name="aEvent"/>
         <parameter name="aFlavour"/>
         <parameter name="aDragSession"/>
         <body>
           <![CDATA[
             var tabStrip = this.mTabContainer.mTabstrip;
 
@@ -1788,108 +1793,69 @@
               if (!this.mDragTime) 
                 this.mDragTime = Date.now();
               if (Date.now() >= this.mDragTime + this.mDragOverDelay)
                 this.mTabContainer.selectedItem = aEvent.target;
               return;
             }
 
             var newIndex = this.getNewIndex(aEvent);
-
             var ib = this.mTabDropIndicatorBar;
             var ind = ib.firstChild;
-            ib.setAttribute('dragging',
-               aDragSession.canDrop ? 'true' : 'false');
-
             var tabStripBoxObject = tabStrip.scrollBoxObject;
-            var halfIndWidth = Math.floor((ind.boxObject.width + 1) / 2);
-            if (window.getComputedStyle(this.parentNode, null)
-                      .direction == "ltr") {
-              var newMarginLeft;
-              var minMarginLeft = tabStripBoxObject.x - halfIndWidth -
-                                  ib.boxObject.x;
-              // make sure we don't place the tab drop indicator past the
-              // edge, or the containing box will flex and stretch
-              // the tab drop indicator bar, which will flex the url bar.  
-              // XXX todo
-              // just use first value if you can figure out how to get
-              // the tab drop indicator to crop instead of flex and stretch
-              // the tab drop indicator bar.
-              var maxMarginLeft = Math.min(
-                (minMarginLeft + tabStripBoxObject.width), 
-                (ib.boxObject.x + ib.boxObject.width - ind.boxObject.width));
-
+            var minMargin = tabStripBoxObject.x - this.boxObject.x;
+            // make sure we don't place the tab drop indicator past the
+            // edge, or the containing box will flex and stretch
+            // the tab drop indicator bar, which will flex the url bar.  
+            // XXX todo
+            // just use first value if you can figure out how to get
+            // the tab drop indicator to crop instead of flex and stretch
+            // the tab drop indicator bar.
+            var maxMargin = Math.min(minMargin + tabStripBoxObject.width, 
+                                     ib.boxObject.x + ib.boxObject.width -
+                                     ind.boxObject.width);
+            var newMargin, tabBoxObject;
+            var ltr = (window.getComputedStyle(this.parentNode, null).direction
+                       == "ltr");
+            if (pixelsToScroll) {
               // if we are scrolling, put the drop indicator at the edge
               // so that it doesn't jump while scrolling
-              if (pixelsToScroll > 0)
-                newMarginLeft = maxMarginLeft;
-              else if (pixelsToScroll < 0)
-                newMarginLeft = minMarginLeft;
-              else {
+              newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
+            }
+            else {
               if (newIndex == this.mTabs.length) {
-                  newMarginLeft = this.mTabs[newIndex-1].boxObject.screenX +
-                                  this.mTabs[newIndex-1].boxObject.width - 
-                                  this.boxObject.screenX - halfIndWidth;
-              } else {
-                  newMarginLeft = this.mTabs[newIndex].boxObject.screenX - 
-                                  this.boxObject.screenX - halfIndWidth;
-              }
-
-              // ensure we never place the drop indicator beyond
-              // our limits
-              if (newMarginLeft < minMarginLeft)
-                newMarginLeft = minMarginLeft;
-              else if (newMarginLeft > maxMarginLeft)
-                newMarginLeft = maxMarginLeft;
+                tabBoxObject =  this.mTabs[newIndex-1].boxObject;
+                if (ltr)
+                  newMargin = tabBoxObject.screenX - this.boxObject.screenX
+                              + tabBoxObject.width;
+                else
+                  newMargin = this.boxObject.screenX - tabBoxObject.screenX
+                              + this.boxObject.width;
               }
-              ind.style.marginLeft = newMarginLeft + 'px';
-            } else {
-              var newMarginRight;
-              var minMarginRight = tabStripBoxObject.x - halfIndWidth -
-                                   ib.boxObject.x;
-              // make sure we don't place the tab drop indicator past the
-              // edge, or the containing box will flex and stretch
-              // the tab drop indicator bar, which will flex the url bar.  
-              // XXX todo
-              // just use first value if you can figure out how to get
-              // the tab drop indicator to crop instead of flex and stretch
-              // the tab drop indicator bar.
-              var maxMarginRight = Math.min(
-                (minMarginRight + tabStripBoxObject.width), 
-                (ib.boxObject.x + ib.boxObject.width - ind.boxObject.width));
-
-              // if we are scrolling, put the drop indicator at the edge
-              // so that it doesn't jump while scrolling
-              if (pixelsToScroll > 0)
-                newMarginRight = maxMarginRight;
-              else if (pixelsToScroll < 0)
-                newMarginRight = minMarginRight;
               else {
-                if (newIndex == this.mTabs.length) {
-                    newMarginRight = this.boxObject.width + 
-                                     this.boxObject.screenX -
-                                     this.mTabs[newIndex-1].boxObject.screenX -
-                                     halfIndWidth;
-                } else {
-                    newMarginRight = this.boxObject.width + 
-                                     this.boxObject.screenX -
-                                     this.mTabs[newIndex].boxObject.screenX -
-                                     this.mTabs[newIndex].boxObject.width -
-                                     halfIndWidth;
-                }
-
-                // ensure we never place the drop indicator beyond
-                // our limits
-                if (newMarginRight < minMarginRight)
-                  newMarginRight = minMarginRight;
-                else if (newMarginRight > maxMarginRight)
-                  newMarginRight = maxMarginRight;
+                tabBoxObject =  this.mTabs[newIndex].boxObject;
+                if (ltr)
+                  newMargin = tabBoxObject.screenX - this.boxObject.screenX;
+                else
+                  newMargin = this.boxObject.screenX - tabBoxObject.screenX
+                              + this.boxObject.width - tabBoxObject.width;
               }
-              ind.style.marginRight = newMarginRight + 'px';
+              // ensure we never place the drop indicator beyond our limits
+              if (newMargin < minMargin)
+                newMargin = minMargin;
+              else if (newMargin > maxMargin)
+                newMargin = maxMargin;
             }
+
+            if (ltr)
+              ind.style.marginLeft = newMargin + 'px';
+            else
+              ind.style.marginRight = newMargin + 'px';
+
+            ib.collapsed = !aDragSession.canDrop;
           ]]>
         </body>
       </method>
 
       <method name="onDrop">
         <parameter name="aEvent"/>
         <parameter name="aXferData"/>
         <parameter name="aDragSession"/>
@@ -1954,24 +1920,17 @@
                 aDragSession.sourceNode.parentNode == this.mTabContainer &&
                 aDragSession.canDrop) {
               var target = aEvent.relatedTarget;
               while (target && target != this.mStrip)
                 target = target.parentNode;
               if (target)
                 return;
             }
-            this.mTabDropIndicatorBar.setAttribute('dragging','false');
-
-            // FIXME: bug 390979 - we need to reset the horizontal margins on the
-            // tab-drop indicator here to avoid impacting tabbar resizing. This
-            // shouldn't be necessary once we can collapse the indicator.
-            var dropIndicator = this.mTabDropIndicatorBar.firstChild;
-            dropIndicator.style.marginRight = "0px";
-            dropIndicator.style.marginLeft = "0px";
+            this.mTabDropIndicatorBar.collapsed = true;
           ]]>
         </body>
       </method>
 
       <method name="getSupportedFlavours">
         <body>
         <![CDATA[
           var flavourSet = new FlavourSet();
@@ -2024,21 +1983,20 @@
         <body>
           <![CDATA[
             var i;
             if (window.getComputedStyle(this.parentNode, null).direction == "ltr") {
               for (i = aEvent.target.localName == "tab" ? aEvent.target._tPos : 0; i < this.mTabs.length; i++)
                 if (aEvent.screenX < this.mTabs[i].boxObject.screenX + this.mTabs[i].boxObject.width / 2) 
                   return i;
             } else {
-               for (i = aEvent.target.localName == "tab" ? aEvent.target._tPos : 0; i < this.mTabs.length; i++)
+              for (i = aEvent.target.localName == "tab" ? aEvent.target._tPos : 0; i < this.mTabs.length; i++)
                 if (aEvent.screenX > this.mTabs[i].boxObject.screenX + this.mTabs[i].boxObject.width / 2)
                   return i;
             }
-
             return this.mTabs.length;
           ]]>
         </body>
       </method>
 
 
       <method name="moveTabForward">
         <body>
@@ -2081,17 +2039,17 @@
       </method>
 
       <method name="moveTabToEnd">
         <body>
           <![CDATA[
             var tabPos = this.mCurrentTab._tPos;
             if (tabPos < this.browsers.length - 1) {
               this.moveTabTo(this.mCurrentTab,
-                                        this.browsers.length - 1);
+                             this.browsers.length - 1);
               this.mCurrentTab.focus();
             }
           ]]>
         </body>
       </method>
 
       <method name="moveTabOver">
         <parameter name="aEvent"/>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -42,10 +42,16 @@ relativesrcdir  = browser/base/content/t
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = 	test_feed_discovery.html \
 	   feed_discovery.html \
     $(NULL)
 
+_BROWSER_FILES = browser_bug321000.js \
+    $(NULL)
+
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs::	$(_BROWSER_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug321000.js
@@ -0,0 +1,25 @@
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+function testPaste(name, element, expected) {
+  element.focus();
+  EventUtils.synthesizeKey("v", { accelKey: true });
+  is(element.value, expected, name);
+}
+
+// test bug 23485 and bug 321000
+// urlbar should strip newlines,
+// search bar should replace newlines with spaces
+function test() {
+  var testString = "  hello hello  \n  world\nworld  ";
+  // Put a multi-line string in the clipboard
+  Components.classes["@mozilla.org/widget/clipboardhelper;1"]
+            .getService(Components.interfaces.nsIClipboardHelper)
+            .copyString(testString);
+  testPaste('urlbar strips newlines and surrounding whitespace', 
+            document.getElementById('urlbar'),
+            testString.replace(/\s*\n\s*/g,''));
+  testPaste('searchbar replaces newlines with spaces', 
+            document.getElementById('searchbar'),
+            testString.replace('\n',' ','g'));
+}
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -38,20 +38,21 @@
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK ***** */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
 function LOG(str) {
-  var prefB = 
-    Cc["@mozilla.org/preferences-service;1"].
-    getService(Ci.nsIPrefBranch);
+  var prefB = Cc["@mozilla.org/preferences-service;1"].
+              getService(Ci.nsIPrefBranch);
 
   var shouldLog = false;
   try {
     shouldLog = prefB.getBoolPref("feeds.log");
   } 
   catch (ex) {
   }
 
@@ -70,110 +71,99 @@ function makeURI(aURLSpec, aCharset) {
             getService(Ci.nsIIOService);
   try {
     return ios.newURI(aURLSpec, aCharset, null);
   } catch (ex) { }
 
   return null;
 }
 
-
 const XML_NS = "http://www.w3.org/XML/1998/namespace"
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
 
 const PREF_SELECTED_APP = "browser.feeds.handlers.application";
 const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
 const PREF_SELECTED_ACTION = "browser.feeds.handler";
 const PREF_SELECTED_READER = "browser.feeds.handler.default";
 const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
 
-const FW_CLASSID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
-const FW_CLASSNAME = "Feed Writer";
-const FW_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
-
 const TITLE_ID = "feedTitleText";
 const SUBTITLE_ID = "feedSubtitleText";
 
-const NH_CONTRACTID = "@mozilla.org/browser/nav-history-service;1";
-const FAV_CONTRACTID = "@mozilla.org/browser/favicon-service;1";
-
-function FeedWriter() {
-}
+function FeedWriter() {}
 FeedWriter.prototype = {
   _getPropertyAsBag: function FW__getPropertyAsBag(container, property) {
     return container.fields.getProperty(property).
                      QueryInterface(Ci.nsIPropertyBag2);
   },
-  
+
   _getPropertyAsString: function FW__getPropertyAsString(container, property) {
     try {
       return container.fields.getPropertyAsAString(property);
     }
     catch (e) {
     }
     return "";
   },
-  
+
   _setContentText: function FW__setContentText(id, text) {
     var element = this._document.getElementById(id);
     while (element.hasChildNodes())
       element.removeChild(element.firstChild);
     element.appendChild(this._document.createTextNode(text));
   },
-  
+
   /**
    * Safely sets the href attribute on an anchor tag, providing the URI 
    * specified can be loaded according to rules. 
    * @param   element
    *          The element to set a URI attribute on
    * @param   attribute
    *          The attribute of the element to set the URI to, e.g. href or src
    * @param   uri
    *          The URI spec to set as the href
    */
   _safeSetURIAttribute: 
   function FW__safeSetURIAttribute(element, attribute, uri) {
-    var secman = 
-        Cc["@mozilla.org/scriptsecuritymanager;1"].
-        getService(Ci.nsIScriptSecurityManager);    
+    var secman = Cc["@mozilla.org/scriptsecuritymanager;1"].
+                 getService(Ci.nsIScriptSecurityManager);    
     const flags = Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL;
     try {
       secman.checkLoadURIStr(this._window.location.href, uri, flags);
       // checkLoadURIStr will throw if the link URI should not be loaded per 
       // the rules specified in |flags|, so we'll never "linkify" the link...
       element.setAttribute(attribute, uri);
     }
     catch (e) {
       // Not allowed to load this link because secman.checkLoadURIStr threw
     }
   },
 
   __faviconService: null,
   get _faviconService() {
-    if (!this.__faviconService) {
-      this.__faviconService =
-        Cc[FAV_CONTRACTID].getService(Ci.nsIFaviconService);
-    }
+    if (!this.__faviconService)
+      this.__faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
+                              getService(Ci.nsIFaviconService);
 
     return this.__faviconService;
   },
 
   __bundle: null,
   get _bundle() {
     if (!this.__bundle) {
       this.__bundle = Cc["@mozilla.org/intl/stringbundle;1"].
                       getService(Ci.nsIStringBundleService).
                       createBundle(URI_BUNDLE);
     }
     return this.__bundle;
   },
-  
+
   _getFormattedString: function FW__getFormattedString(key, params) {
     return this._bundle.formatStringFromName(key, params, params.length);
   },
   
   _getString: function FW__getString(key) {
     return this._bundle.GetStringFromName(key);
   },
 
@@ -256,57 +246,56 @@ FeedWriter.prototype = {
    * @param   container
    *          The feed container
    */
   _setTitleText: function FW__setTitleText(container) {
     if (container.title) {
       this._setContentText(TITLE_ID, container.title.plainText());
       this._document.title = container.title.plainText();
     }
-    
+
     var feed = container.QueryInterface(Ci.nsIFeed);
     if (feed && feed.subtitle)
       this._setContentText(SUBTITLE_ID, container.subtitle.plainText());
   },
-  
+
   /**
    * Writes the title image into the preview document if one is present.
    * @param   container
    *          The feed container
    */
   _setTitleImage: function FW__setTitleImage(container) {
     try {
       var parts = container.image;
       
       // Set up the title image (supplied by the feed)
       var feedTitleImage = this._document.getElementById("feedTitleImage");
       this._safeSetURIAttribute(feedTitleImage, "src", 
                                 parts.getPropertyAsAString("url"));
-      
+
       // Set up the title image link
       var feedTitleLink = this._document.getElementById("feedTitleLink");
-      
-      var titleText = 
-        this._getFormattedString("linkTitleTextFormat", 
-                                 [parts.getPropertyAsAString("title")]);
+
+      var titleText = this._getFormattedString("linkTitleTextFormat", 
+                                               [parts.getPropertyAsAString("title")]);
       feedTitleLink.setAttribute("title", titleText);
       this._safeSetURIAttribute(feedTitleLink, "href", 
                                 parts.getPropertyAsAString("link"));
 
       // Fix the margin on the main title, so that the image doesn't run over
       // the underline
       var feedTitleText = this._document.getElementById("feedTitleText");
       var titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
       feedTitleText.style.marginRight = titleImageWidth + "px";
     }
     catch (e) {
       LOG("Failed to set Title Image (this is benign): " + e);
     }
   },
-  
+
   /**
    * Writes all entries contained in the feed.
    * @param   container
    *          The container of entries in the feed
    */
   _writeFeedContent: function FW__writeFeedContent(container) {
     // Build the actual feed content
     var feedContent = this._document.getElementById("feedContent");
@@ -368,30 +357,30 @@ FeedWriter.prototype = {
       body.className = "feedEntryContent";
       entryContainer.appendChild(body);
       feedContent.appendChild(entryContainer);
       var clearDiv = this._document.createElementNS(HTML_NS, "div");
       clearDiv.style.clear = "both";
       feedContent.appendChild(clearDiv);
     }
   },
-  
+
   /**
    * Gets a valid nsIFeedContainer object from the parsed nsIFeedResult.
    * Displays error information if there was one.
    * @param   result
    *          The parsed feed result
    * @returns A valid nsIFeedContainer object containing the contents of
    *          the feed.
    */
   _getContainer: function FW__getContainer(result) {
     var feedService = 
         Cc["@mozilla.org/browser/feeds/result-service;1"].
         getService(Ci.nsIFeedResultService);
- 
+
     try {
       var result = 
         feedService.getFeedResult(this._getOriginalURI(this._window));
     }
     catch (e) {
       LOG("Subscribe Preview: feed not available?!");
     }
     
@@ -403,17 +392,17 @@ FeedWriter.prototype = {
       var container = result.doc;
     }
     catch (e) {
       LOG("Subscribe Preview: no result.doc? Why didn't the original reload?");
       return null;
     }
     return container;
   },
-  
+
   /**
    * Get the human-readable display name of a file. This could be the 
    * application name.
    * @param   file
    *          A nsIFile to look up the name of
    * @returns The display name of the application represented by the file.
    */
   _getFileDisplayName: function FW__getFileDisplayName(file) {
@@ -536,19 +525,17 @@ FeedWriter.prototype = {
       if (handlersMenuList) {
         var handlerName = this._getSelectedItemFromMenulist(handlersMenuList)
                               .getAttribute("label");
         checkbox.setAttribute("label", this._getFormattedString("alwaysUse", [handlerName]));
       }
     }
   },
 
-  /**
-   * See nsIDOMEventListener
-   */
+  // nsIDomEventListener
   handleEvent: function(event) {
     // see comments in the write method
     event = new XPCNativeWrapper(event);
     if (event.target.ownerDocument != this._document) {
       LOG("FeedWriter.handleEvent: Someone passed the feed writer as a listener to the events of another document!");
       return;
     }
 
@@ -586,17 +573,17 @@ FeedWriter.prototype = {
         Cc["@mozilla.org/preferences-service;1"].
         getService(Ci.nsIPrefBranch);
 
     var handler = "bookmarks";
     try {
       handler = prefs.getCharPref(PREF_SELECTED_READER);
     }
     catch (ex) { }
-    
+
     switch (handler) {
       case "web": {
         var handlersMenuList = this._document.getElementById("handlersMenuList");
         if (handlersMenuList) {
           var url = prefs.getComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString).data;
           var handlers =
             handlersMenuList.getElementsByAttribute("webhandlerurl", url);
           if (handlers.length == 0) {
@@ -629,27 +616,25 @@ FeedWriter.prototype = {
                 defaultHandlerMenuItem.file.path == selectedApp.path;
             }
             break;
           }
         }
       }
       case "bookmarks":
       default: {
-        var liveBookmarksMenuItem =
-          this._document.getElementById("liveBookmarksMenuItem");
+        var liveBookmarksMenuItem = this._document.getElementById("liveBookmarksMenuItem");
         if (liveBookmarksMenuItem)
           liveBookmarksMenuItem.doCommand();
       } 
     }
   },
 
   _initSubscriptionUI: function FW__initSubscriptionUI() {
-    var handlersMenuPopup =
-      this._document.getElementById("handlersMenuPopup");
+    var handlersMenuPopup = this._document.getElementById("handlersMenuPopup");
     if (!handlersMenuPopup)
       return;
 
     // Last-selected application
     var selectedApp;
     menuItem = this._document.createElementNS(XUL_NS, "menuitem");
     menuItem.id = "selectedAppMenuItem";
     menuItem.className = "menuitem-iconic";
@@ -658,19 +643,18 @@ FeedWriter.prototype = {
 
     var selectedApplicationItem = this.selectedApplicationItemWrapped;
     try {
       var prefs = Cc["@mozilla.org/preferences-service;1"].
                   getService(Ci.nsIPrefBranch);
       selectedApp = prefs.getComplexValue(PREF_SELECTED_APP,
                                           Ci.nsILocalFile);
 
-      if (selectedApp.exists()) {
+      if (selectedApp.exists())
         this._initMenuItemWithFile(selectedApplicationItem, selectedApp);
-      }
       else {
         // Hide the menuitem if the last selected application doesn't exist
         selectedApplicationItem.hidden = true;
       }
     }
     catch(ex) {
       // Hide the menuitem until an application is selected
       selectedApplicationItem.hidden = true;
@@ -702,23 +686,23 @@ FeedWriter.prototype = {
     menuItem.id = "chooseApplicationMenuItem";
     menuItem.setAttribute("label", this._getString("chooseApplicationMenuItem"));
     handlersMenuPopup.appendChild(menuItem);
 
     // separator
     handlersMenuPopup.appendChild(this._document.createElementNS(XUL_NS,
                                   "menuseparator"));
 
-    var historySvc = Cc[NH_CONTRACTID].getService(Ci.nsINavHistoryService);
+    var historySvc = Cc["@mozilla.org/browser/nav-history-service;1"].
+                     getService(Ci.nsINavHistoryService);
     historySvc.addObserver(this, false);
 
     // List of web handlers
-    var wccr = 
-      Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
-      getService(Ci.nsIWebContentConverterService);
+    var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
+               getService(Ci.nsIWebContentConverterService);
     var handlers = wccr.getContentHandlers(TYPE_MAYBE_FEED, {});
     if (handlers.length != 0) {
       for (var i = 0; i < handlers.length; ++i) {
         menuItem = this._document.createElementNS(XUL_NS, "menuitem");
         menuItem.className = "menuitem-iconic";
         menuItem.setAttribute("label", handlers[i].name);
         menuItem.setAttribute("handlerType", "web");
         menuItem.setAttribute("webhandlerurl", handlers[i].uri);
@@ -745,43 +729,42 @@ FeedWriter.prototype = {
     // We update the "Always use.." checkbox label whenever the selected item
     // in the list is changed
     handlersMenuPopup.addEventListener("command", this, false);
 
     // Set up the "Subscribe Now" button
     this._document
         .getElementById("subscribeButton")
         .addEventListener("command", this, false);
-    
+
     // first-run ui
     var showFirstRunUI = true;
     try {
       showFirstRunUI = prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
     }
     catch (ex) { }
     if (showFirstRunUI) {
       var feedHeader = this._document.getElementById("feedHeader");
       if (feedHeader)
         feedHeader.setAttribute("firstrun", "true");
 
       prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
     }
   },
-  
+
   /**
    * Returns the original URI object of the feed and ensures that this
    * component is only ever invoked from the preview document.  
    * @param aWindow 
    *        The window of the document invoking the BrowserFeedWriter
    */
   _getOriginalURI: function FW__getOriginalURI(aWindow) {
-    var chan = 
-        aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
-        getInterface(Ci.nsIWebNavigation).
-        QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
+    var chan = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
+               getInterface(Ci.nsIWebNavigation).
+               QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
 
     const SUBSCRIBE_PAGE_URI = "chrome://browser/content/feeds/subscribe.xhtml";
     var uri = makeURI(SUBSCRIBE_PAGE_URI);
     var resolvedURI = Cc["@mozilla.org/chrome/chrome-registry;1"].
                       getService(Ci.nsIChromeRegistry).
                       convertChromeURL(uri);
 
     if (resolvedURI.equals(chan.URI))
@@ -789,19 +772,17 @@ FeedWriter.prototype = {
 
     return null;
   },
 
   _window: null,
   _document: null,
   _feedURI: null,
 
-  /**
-   * See nsIFeedWriter
-   */
+  // nsIFeedWriter
   init: function FW_init(aWindow) {
     // Explicitly wrap |window| in an XPCNativeWrapper to make sure
     // it's a real native object! This will throw an exception if we
     // get a non-native object.
     var window = new XPCNativeWrapper(aWindow);
     this._feedURI = this._getOriginalURI(window);
     if (!this._feedURI)
       return;
@@ -816,82 +797,74 @@ FeedWriter.prototype = {
     var prefs = Cc["@mozilla.org/preferences-service;1"].
                 getService(Ci.nsIPrefBranch2);
     prefs.addObserver(PREF_SELECTED_ACTION, this, false);
     prefs.addObserver(PREF_SELECTED_READER, this, false);
     prefs.addObserver(PREF_SELECTED_WEB, this, false);
     prefs.addObserver(PREF_SELECTED_APP, this, false);
   },
 
-  /**
-   * See nsIFeedWriter
-   */
   writeContent: function FW_writeContent() {
     if (!this._window)
       return;
 
     try {
       // Set up the feed content
       var container = this._getContainer();
       if (!container)
         return;
-      
+
       this._setTitleText(container);
       this._setTitleImage(container);
       this._writeFeedContent(container);
     }
     finally {
       this._removeFeedFromCache();
     }
   },
 
-  /**
-   * See nsIFeedWriter
-   */
   close: function FW_close() {
     this._document
         .getElementById("handlersMenuPopup")
         .removeEventListener("command", this, false);
     this._document
         .getElementById("subscribeButton")
         .removeEventListener("command", this, false);
     this._document = null;
     this._window = null;
-    var prefs =   
-        Cc["@mozilla.org/preferences-service;1"].
-        getService(Ci.nsIPrefBranch2);
+    var prefs = Cc["@mozilla.org/preferences-service;1"].
+                getService(Ci.nsIPrefBranch2);
     prefs.removeObserver(PREF_SELECTED_ACTION, this);
     prefs.removeObserver(PREF_SELECTED_READER, this);
     prefs.removeObserver(PREF_SELECTED_WEB, this);
     prefs.removeObserver(PREF_SELECTED_APP, this);
     this._removeFeedFromCache();
     this.__faviconService = null;
     this.__bundle = null;
     this._selectedApplicationItemWrapped = null;
     this._defaultSystemReaderItemWrapped = null;
     this._FeedURI = null;
-    var historySvc = Cc[NH_CONTRACTID].getService(Ci.nsINavHistoryService);
+    var historySvc = Cc["@mozilla.org/browser/nav-history-service;1"].
+                     getService(Ci.nsINavHistoryService);
     historySvc.removeObserver(this);
   },
 
   _removeFeedFromCache: function FW__removeFeedFromCache() {
     if (this._feedURI) {
-      var feedService = 
-          Cc["@mozilla.org/browser/feeds/result-service;1"].
-          getService(Ci.nsIFeedResultService);
+      var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
+                        getService(Ci.nsIFeedResultService);
       feedService.removeFeedResult(this._feedURI);
       this._feedURI = null;
     }
   },
 
   subscribe: function FW_subscribe() {
     // Subscribe to the feed using the selected handler and save prefs
-    var prefs =   
-        Cc["@mozilla.org/preferences-service;1"].
-        getService(Ci.nsIPrefBranch);
+    var prefs = Cc["@mozilla.org/preferences-service;1"].
+                getService(Ci.nsIPrefBranch);
     var defaultHandler = "reader";
     var useAsDefault = this._document.getElementById("alwaysUse")
                                      .getAttribute("checked");
 
     var handlersMenuList = this._document.getElementById("handlersMenuList");
     var selectedItem = this._getSelectedItemFromMenulist(handlersMenuList);
 
     // Show the file picker before subscribing if the
@@ -908,26 +881,24 @@ FeedWriter.prototype = {
       prefs.setCharPref(PREF_SELECTED_READER, "web");
 
       var supportsString = Cc["@mozilla.org/supports-string;1"].
                            createInstance(Ci.nsISupportsString);
       supportsString.data = webURI;
       prefs.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
                             supportsString);
 
-      var wccr = 
-        Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
-        getService(Ci.nsIWebContentConverterService);
+      var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
+                 getService(Ci.nsIWebContentConverterService);
       var handler = wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
       if (handler) {
         if (useAsDefault)
           wccr.setAutoHandler(TYPE_MAYBE_FEED, handler);
 
-        this._window.location.href =
-          handler.getHandlerURI(this._window.location.href);
+        this._window.location.href = handler.getHandlerURI(this._window.location.href);
       }
     }
     else {
       switch (selectedItem.id) {
         case "selectedAppMenuItem":
           prefs.setCharPref(PREF_SELECTED_READER, "client");
           prefs.setComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile, 
                                 this.selectedApplicationItemWrapped.file);
@@ -942,35 +913,32 @@ FeedWriter.prototype = {
           prefs.setCharPref(PREF_SELECTED_READER, "bookmarks");
           break;
       }
       var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
                         getService(Ci.nsIFeedResultService);
 
       // Pull the title and subtitle out of the document
       var feedTitle = this._document.getElementById(TITLE_ID).textContent;
-      var feedSubtitle =
-        this._document.getElementById(SUBTITLE_ID).textContent;
+      var feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
       feedService.addToClientReader(this._window.location.href,
                                     feedTitle, feedSubtitle);
     }
 
     // If "Always use..." is checked, we should set PREF_SELECTED_ACTION
     // to either "reader" (If a web reader or if an application is selected),
     // or to "bookmarks" (if the live bookmarks option is selected).
     // Otherwise, we should set it to "ask"
     if (useAsDefault)
       prefs.setCharPref(PREF_SELECTED_ACTION, defaultHandler);
     else
       prefs.setCharPref(PREF_SELECTED_ACTION, "ask");
   },
 
-  /**
-   * See nsIObserver
-   */
+  // nsIObserver
   observe: function FW_observe(subject, topic, data) {
     if (!this._window) {
       // this._window is null unless this.write was called with a trusted
       // window object.
       return;
     }
 
     if (topic == "nsPref:changed") {
@@ -1014,19 +982,17 @@ FeedWriter.prototype = {
         aMenuItem.setAttribute("image", dataURI);
         return true;
       }
     }
 
     return false;
   },
 
-  /**
-   * See nsINavHistoryService
-   */
+   // nsINavHistoryService
    onPageChanged: function FW_onPageChanged(aURI, aWhat, aValue) {
      if (aWhat == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
        // Go through the readers menu and look for the corresponding
        // reader menu-item for the page if any.
        var spec = aURI.spec;
        var handlersMenulist = this._document.getElementById("handlersMenuList");
        var possibleHandlers = handlersMenulist.firstChild.childNodes;
        for (var i=0; i < possibleHandlers.length ; i++) {
@@ -1041,85 +1007,29 @@ FeedWriter.prototype = {
    onBeginUpdateBatch: function() { },
    onEndUpdateBatch: function() { },
    onVisit: function() { },
    onTitleChanged: function() { },
    onDeleteURI: function() { },
    onClearHistory: function() { },
    onPageExpired: function() { },
 
-  /**
-   * See nsIClassInfo
-   */
-  getInterfaces: function WCCR_getInterfaces(countRef) {
-    var interfaces = 
-        [Ci.nsIFeedWriter, Ci.nsIClassInfo, Ci.nsISupports];
+  // nsIClassInfo
+  getInterfaces: function FW_getInterfaces(countRef) {
+    var interfaces = [Ci.nsIFeedWriter, Ci.nsIClassInfo, Ci.nsISupports];
     countRef.value = interfaces.length;
     return interfaces;
   },
-  getHelperForLanguage: function WCCR_getHelperForLanguage(language) {
-    return null;
-  },
-  contractID: FW_CONTRACTID,
-  classDescription: FW_CLASSNAME,
-  classID: FW_CLASSID,
+  getHelperForLanguage: function FW_getHelperForLanguage(language) null,
+  contractID: "@mozilla.org/browser/feeds/result-writer;1",
+  classDescription: "Feed Writer",
+  classID: Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}"),
   implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
   flags: Ci.nsIClassInfo.DOM_OBJECT,
-
-  QueryInterface: function FW_QueryInterface(iid) {
-    if (iid.equals(Ci.nsIFeedWriter) ||
-        iid.equals(Ci.nsIClassInfo) ||
-        iid.equals(Ci.nsIDOMEventListener) ||
-        iid.equals(Ci.nsIObserver) ||
-        iid.equals(Ci.nsINavHistoryObserver) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
+  _xpcom_categories: [{ category: "JavaScript global constructor",
+                        entry: "BrowserFeedWriter"}],
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedWriter, Ci.nsIClassInfo,
+                                         Ci.nsIDOMEventListener, Ci.nsIObserver,
+                                         Ci.nsINavHistoryObserver])
 };
 
-var Module = {
-  QueryInterface: function M_QueryInterface(iid) {
-    if (iid.equals(Ci.nsIModule) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-  getClassObject: function M_getClassObject(cm, cid, iid) {
-    if (!iid.equals(Ci.nsIFactory))
-      throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-    
-    if (cid.equals(FW_CLASSID))
-      return new GenericComponentFactory(FeedWriter);
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-  
-  registerSelf: function M_registerSelf(cm, file, location, type) {
-    var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
-    
-    cr.registerFactoryLocation(FW_CLASSID, FW_CLASSNAME, FW_CONTRACTID,
-                               file, location, type);
-    
-    var catman = 
-        Cc["@mozilla.org/categorymanager;1"].
-        getService(Ci.nsICategoryManager);
-    catman.addCategoryEntry("JavaScript global constructor",
-                            "BrowserFeedWriter", FW_CONTRACTID, true, true);
-  },
-
-  unregisterSelf: function M_unregisterSelf(cm, location, type) {
-    var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
-    cr.unregisterFactoryLocation(FW_CLASSID, location);
-  },
-
-  canUnload: function M_canUnload(cm) {
-    return true;
-  }
-};
-
-function NSGetModule(cm, file) {
-  return Module;
-}
-
-#include ../../../../toolkit/content/debug.js
-#include GenericFactory.js
+function NSGetModule(cm, file)
+  XPCOMUtils.generateModule([FeedWriter]);
--- a/browser/components/microsummaries/src/nsMicrosummaryService.js
+++ b/browser/components/microsummaries/src/nsMicrosummaryService.js
@@ -54,20 +54,20 @@ const NS_ERROR_DOM_BAD_URI = NS_ERROR_MO
 // How often to check for microsummaries that need updating, in milliseconds.
 const CHECK_INTERVAL = 15 * 1000; // 15 seconds
 // How often to check for generator updates, in seconds
 const GENERATOR_INTERVAL = 7 * 86400; // 1 week
 
 const MICSUM_NS = new Namespace("http://www.mozilla.org/microsummaries/0.1");
 const XSLT_NS = new Namespace("http://www.w3.org/1999/XSL/Transform");
 
-const FIELD_MICSUM_GEN_URI    = "microsummary/generatorURI";
-const FIELD_MICSUM_EXPIRATION = "microsummary/expiration";
-const FIELD_STATIC_TITLE      = "bookmarks/staticTitle";
-const FIELD_CONTENT_TYPE      = "bookmarks/contentType";
+const ANNO_MICSUM_GEN_URI    = "microsummary/generatorURI";
+const ANNO_MICSUM_EXPIRATION = "microsummary/expiration";
+const ANNO_STATIC_TITLE      = "bookmarks/staticTitle";
+const ANNO_CONTENT_TYPE      = "bookmarks/contentType";
 
 const MAX_SUMMARY_LENGTH = 4096;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function MicrosummaryService() { this._init() }
 
 MicrosummaryService.prototype = {
@@ -219,23 +219,23 @@ MicrosummaryService.prototype = {
     var bookmarks = this._getBookmarks();
 
     var now = Date.now();
     var updateInterval = this._updateInterval;
     for ( var i = 0; i < bookmarks.length; i++ ) {
       var bookmarkID = bookmarks[i];
 
       // Skip this page if its microsummary hasn't expired yet.
-      if (this._hasField(bookmarkID, FIELD_MICSUM_EXPIRATION) &&
-          this._getField(bookmarkID, FIELD_MICSUM_EXPIRATION) > now)
+      if (this._ans.itemHasAnnotation(bookmarkID, ANNO_MICSUM_EXPIRATION) &&
+          this._ans.getItemAnnotation(bookmarkID, ANNO_MICSUM_EXPIRATION) > now)
         continue;
 
       // Reset the expiration time immediately, so if the refresh is failing
       // we don't try it every 15 seconds, potentially overloading the server.
-      this._setField(bookmarkID, FIELD_MICSUM_EXPIRATION, now + updateInterval);
+      this._setAnnotation(bookmarkID, ANNO_MICSUM_EXPIRATION, now + updateInterval);
 
       // Try to update the microsummary, but trap errors, so an update
       // that throws doesn't prevent us from updating the rest of them.
       try {
         this.refreshMicrosummary(bookmarkID);
       }
       catch(ex) {
         Cu.reportError(ex);
@@ -249,44 +249,44 @@ MicrosummaryService.prototype = {
     if (!generators || !update)
       return;
 
     for (let uri in generators)
       generators[uri].update();
   },
 
   _updateMicrosummary: function MSS__updateMicrosummary(bookmarkID, microsummary) {
-    var title = this._getTitle(bookmarkID);
+    var title = this._bms.getItemTitle(bookmarkID);
 
     // Ensure the user-given title is cached
-    if (!this._hasField(bookmarkID, FIELD_STATIC_TITLE))
-      this._setField(bookmarkID, FIELD_STATIC_TITLE, title);
+    if (!this._ans.itemHasAnnotation(bookmarkID, ANNO_STATIC_TITLE))
+      this._setAnnotation(bookmarkID, ANNO_STATIC_TITLE, title);
 
     // A string identifying the bookmark to use when logging the update.
     var bookmarkIdentity = bookmarkID;
 
     // Update if the microsummary differs from the current title.
     if (!title || title != microsummary.content) {
-      this._setTitle(bookmarkID, microsummary.content);
+      this._bms.setItemTitle(bookmarkID, microsummary.content);
       var subject = new LiveTitleNotificationSubject(bookmarkID, microsummary);
       LOG("updated live title for " + bookmarkIdentity +
           " from '" + (title == null ? "<no live title>" : title) +
           "' to '" + microsummary.content + "'");
       this._obs.notifyObservers(subject, "microsummary-livetitle-updated", title);
     }
     else {
       LOG("didn't update live title for " + bookmarkIdentity + "; it hasn't changed");
     }
 
     // Whether or not the title itself has changed, we still save any changes
     // to the update interval, since the interval represents how long to wait
     // before checking again for updates, and that can vary across updates,
     // even when the title itself hasn't changed.
-    this._setField(bookmarkID, FIELD_MICSUM_EXPIRATION,
-                   Date.now() + (microsummary.updateInterval || this._updateInterval));
+    this._setAnnotation(bookmarkID, ANNO_MICSUM_EXPIRATION,
+                  Date.now() + (microsummary.updateInterval || this._updateInterval));
   },
 
   /**
    * Load local generators into the cache.
    * 
    */
   _cacheLocalGenerators: function MSS__cacheLocalGenerators() {
     // Load generators from the application directory.
@@ -489,17 +489,17 @@ MicrosummaryService.prototype = {
       var generator = this._localGenerators[genURISpec];
 
       if (generator.appliesToURI(pageURI)) {
         var microsummary = new Microsummary(pageURI, generator);
 
         // If this is the current microsummary for this bookmark, load the content
         // from the datastore so it shows up immediately in microsummary picking UI.
         if (bookmarkID != -1 && this.isMicrosummary(bookmarkID, microsummary))
-          microsummary._content = this._getTitle(bookmarkID);
+          microsummary._content = this._bms.getItemTitle(bookmarkID);
 
         microsummaries.AppendElement(microsummary);
       }
     }
 
     // If a bookmark identifier has been provided, list its microsummary
     // synchronously, if any.
     if (bookmarkID != -1 && this.hasMicrosummary(bookmarkID)) {
@@ -552,19 +552,19 @@ MicrosummaryService.prototype = {
    *
    */
   _changeField: function MSS__changeField(fieldName, oldValue, newValue) {
     var bookmarks = this._getBookmarks();
 
     for ( var i = 0; i < bookmarks.length; i++ ) {
       var bookmarkID = bookmarks[i];
 
-      if (this._hasField(bookmarkID, fieldName) &&
-          this._getField(bookmarkID, fieldName) == oldValue)
-        this._setField(bookmarkID, fieldName, newValue);
+      if (this._ans.itemHasAnnotation(bookmarkID, fieldName) &&
+          this._ans.getItemAnnotation(bookmarkID, fieldName) == oldValue)
+        this._setAnnotation(bookmarkID, fieldName, newValue);
     }
   },
 
   /**
    * Get the set of bookmarks with microsummaries.
    *
    * This is the internal version of this method, which is not accessible
    * via XPCOM but is more performant; inside this component, use this version.
@@ -573,57 +573,33 @@ MicrosummaryService.prototype = {
    * @returns an array of place: uris representing bookmarks items
    *
    */
   _getBookmarks: function MSS__getBookmarks() {
     var bookmarks;
 
     // This try/catch block is a temporary workaround for bug 336194.
     try {
-      bookmarks = this._ans.getItemsWithAnnotation(FIELD_MICSUM_GEN_URI, {});
+      bookmarks = this._ans.getItemsWithAnnotation(ANNO_MICSUM_GEN_URI, {});
     }
     catch(e) {
       bookmarks = [];
     }
 
     return bookmarks;
   },
 
-  _getField: function MSS__getField(aBookmarkId, aFieldName) {
-    return this._ans.getItemAnnotation(aBookmarkId, aFieldName);
-  },
-
-  _setField: function MSS__setField(aBookmarkId, aFieldName, aFieldValue) {
+  _setAnnotation: function MSS__setAnnotation(aBookmarkId, aFieldName, aFieldValue) {
     this._ans.setItemAnnotation(aBookmarkId,
                                 aFieldName,
                                 aFieldValue,
                                 0,
                                 this._ans.EXPIRE_NEVER);
   },
 
-  _getTitle: function MSS_getTitle(aBookmarkId) {
-    return this._bms.getItemTitle(aBookmarkId);
-  },
-
-  _setTitle: function MSS_setTitle(aBookmarkId, aValue) {
-    this._bms.setItemTitle(aBookmarkId, aValue);
-  },
-
-  _clearField: function MSS__clearField(aBookmarkId, aFieldName) {
-    this._ans.removeItemAnnotation(aBookmarkId, aFieldName);
-  },
-
-  _hasField: function MSS__hasField(aBookmarkId, fieldName) {
-    return this._ans.itemHasAnnotation(aBookmarkId, fieldName);
-  },
-
-  _getPageForBookmark: function MSS__getPageForBookmark(aBookmarkId) {
-    return this._bms.getBookmarkURI(aBookmarkId);
-  },
-
   /**
    * Get the set of bookmarks with microsummaries.
    *
    * This is the external version of this method and is accessible via XPCOM.
    * Use it outside this component. Inside the component, use _getBookmarks
    * (with underscore prefix) instead for performance.
    *
    * @returns an nsISimpleEnumerator enumeration of bookmark IDs
@@ -642,18 +618,19 @@ MicrosummaryService.prototype = {
    * @returns the current microsummary for the bookmark, or null
    *          if the bookmark does not have a current microsummary
    *
    */
   getMicrosummary: function MSS_getMicrosummary(bookmarkID) {
     if (!this.hasMicrosummary(bookmarkID))
       return null;
 
-    var pageURI = this._getPageForBookmark(bookmarkID);
-    var generatorURI = this._uri(this._getField(bookmarkID, FIELD_MICSUM_GEN_URI));
+    var pageURI = this._bms.getBookmarkURI(bookmarkID);
+    var generatorURI = this._uri(this._ans.getItemAnnotation(bookmarkID,
+                                                             ANNO_MICSUM_GEN_URI));
     var generator = this.getGenerator(generatorURI);
 
     return new Microsummary(pageURI, generator);
   },
 
   /**
    * Get a microsummary for a given page URI and generator URI.
    *
@@ -677,63 +654,60 @@ MicrosummaryService.prototype = {
    * @param   bookmarkID
    *          the bookmark for which to set the current microsummary
    *
    * @param   microsummary
    *          the microsummary to set as the current one
    *
    */
   setMicrosummary: function MSS_setMicrosummary(bookmarkID, microsummary) {
-    this._setField(bookmarkID, FIELD_MICSUM_GEN_URI, microsummary.generator.uri.spec);
+    this._setAnnotation(bookmarkID, ANNO_MICSUM_GEN_URI, microsummary.generator.uri.spec);
 
-    if (microsummary.content) {
+    if (microsummary.content)
       this._updateMicrosummary(bookmarkID, microsummary);
-    }
-    else {
-      // Use the bookmark's title for now and attempt an update
+    else
       this.refreshMicrosummary(bookmarkID);
-    }
   },
 
   /**
    * Remove the current microsummary for the given bookmark.
    *
    * @param   bookmarkID
    *          the bookmark for which to remove the current microsummary
    *
    */
   removeMicrosummary: function MSS_removeMicrosummary(bookmarkID) {
     // Restore the user's title
-    if (this._hasField(bookmarkID, FIELD_STATIC_TITLE))
-      this._setTitle(bookmarkID, this._getField(bookmarkID, FIELD_STATIC_TITLE));
+    if (this._ans.itemHasAnnotation(bookmarkID, ANNO_STATIC_TITLE))
+      this._bms.setItemTitle(bookmarkID, this._ans.getItemAnnotation(bookmarkID, ANNO_STATIC_TITLE));
 
-    var fields = [FIELD_MICSUM_GEN_URI,
-                  FIELD_MICSUM_EXPIRATION,
-                  FIELD_STATIC_TITLE,
-                  FIELD_CONTENT_TYPE];
+    var fields = [ANNO_MICSUM_GEN_URI,
+                  ANNO_MICSUM_EXPIRATION,
+                  ANNO_STATIC_TITLE,
+                  ANNO_CONTENT_TYPE];
 
     for (let i = 0; i < fields.length; i++) {
       var field = fields[i];
-      if (this._hasField(bookmarkID, field))
-        this._clearField(bookmarkID, field);
+      if (this._ans.itemHasAnnotation(bookmarkID, field))
+        this._ans.removeItemAnnotation(bookmarkID, field);
     }
   },
 
   /**
    * Whether or not the given bookmark has a current microsummary.
    *
    * @param   bookmarkID
    *          the bookmark for which to set the current microsummary
    *
    * @returns a boolean representing whether or not the given bookmark
    *          has a current microsummary
    *
    */
   hasMicrosummary: function MSS_hasMicrosummary(bookmarkID) {
-    return this._hasField(bookmarkID, FIELD_MICSUM_GEN_URI);
+    return this._ans.itemHasAnnotation(bookmarkID, ANNO_MICSUM_GEN_URI);
   },
 
   /**
    * Whether or not the given microsummary is the current microsummary
    * for the given bookmark.
    *
    * @param   bookmarkID
    *          the bookmark to check
@@ -774,20 +748,21 @@ MicrosummaryService.prototype = {
    *
    * @returns the microsummary being refreshed
    *
    */
   refreshMicrosummary: function MSS_refreshMicrosummary(bookmarkID) {
     if (!this.hasMicrosummary(bookmarkID))
       throw "bookmark " + bookmarkID + " does not have a microsummary";
 
-    var pageURI = this._getPageForBookmark(bookmarkID);
+    var pageURI = this._bms.getBookmarkURI(bookmarkID);
     if (!pageURI)
       throw("can't get URL for bookmark with ID " + bookmarkID);
-    var generatorURI = this._uri(this._getField(bookmarkID, FIELD_MICSUM_GEN_URI));
+    var generatorURI = this._uri(this._ans.getItemAnnotation(bookmarkID,
+                                                             ANNO_MICSUM_GEN_URI));
 
     var generator = this._localGenerators[generatorURI.spec] ||
                     new MicrosummaryGenerator(generatorURI);
 
     var microsummary = new Microsummary(pageURI, generator);
 
     // A microsummary observer that calls the microsummary service
     // to update the datastore when the microsummary finishes loading.
--- a/browser/components/migration/src/nsSafariProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSafariProfileMigrator.cpp
@@ -59,17 +59,17 @@
 #include "nsIRDFService.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsISupportsArray.h"
 #include "nsISupportsPrimitives.h"
 #include "nsSafariProfileMigrator.h"
 #include "nsToolkitCompsCID.h"
 #include "nsNetUtil.h"
-#include "nsAutoBuffer.h"
+#include "nsTArray.h"
 
 #include <Carbon/Carbon.h>
 
 #define SAFARI_PREFERENCES_FILE_NAME      NS_LITERAL_STRING("com.apple.Safari.plist")
 #define SAFARI_BOOKMARKS_FILE_NAME        NS_LITERAL_STRING("Bookmarks.plist")
 #define SAFARI_HISTORY_FILE_NAME          NS_LITERAL_STRING("History.plist")
 #define SAFARI_COOKIES_FILE_NAME          NS_LITERAL_STRING("Cookies.plist")
 #define SAFARI_COOKIE_BEHAVIOR_FILE_NAME  NS_LITERAL_STRING("com.apple.WebFoundation.plist")
@@ -306,56 +306,56 @@ FreeNullTerminatedString(char* aString)
 }
 
 PRBool
 GetDictionaryStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
                          nsAString& aResult)
 {
   CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
   if (value) {
-    nsAutoBuffer<UniChar, 1024> buffer;
+    nsAutoTArray<UniChar, 1024> buffer;
     CFIndex valueLength = ::CFStringGetLength(value);
-    buffer.EnsureElemCapacity(valueLength);
+    buffer.SetLength(valueLength);
 
-    ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.get());
-    aResult.Assign(buffer.get(), valueLength);
+    ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
+    aResult.Assign(buffer.Elements(), valueLength);
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 PRBool
 GetDictionaryCStringValue(CFDictionaryRef aDictionary, CFStringRef aKey,
                           nsACString& aResult, CFStringEncoding aEncoding)
 {
   CFStringRef value = (CFStringRef)::CFDictionaryGetValue(aDictionary, aKey);
   if (value) {
-    nsAutoBuffer<char, 1024> buffer;
+    nsAutoTArray<char, 1024> buffer;
     CFIndex valueLength = ::CFStringGetLength(value);
-    buffer.EnsureElemCapacity(valueLength + 1);
+    buffer.SetLength(valueLength + 1);
 
-    if (::CFStringGetCString(value, buffer.get(), valueLength + 1, aEncoding)) {
-      aResult = buffer.get();
+    if (::CFStringGetCString(value, buffer.Elements(), valueLength + 1, aEncoding)) {
+      aResult = buffer.Elements();
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 PRBool
 GetArrayStringValue(CFArrayRef aArray, PRInt32 aIndex, nsAString& aResult)
 {
   CFStringRef value = (CFStringRef)::CFArrayGetValueAtIndex(aArray, aIndex);
   if (value) {
-    nsAutoBuffer<UniChar, 1024> buffer;
+    nsAutoTArray<UniChar, 1024> buffer;
     CFIndex valueLength = ::CFStringGetLength(value);
-    buffer.EnsureElemCapacity(valueLength);
+    buffer.SetLength(valueLength);
 
-    ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.get());
-    aResult.Assign(buffer.get(), valueLength);
+    ::CFStringGetCharacters(value, CFRangeMake(0, valueLength), buffer.Elements());
+    aResult.Assign(buffer.Elements(), valueLength);
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 #define _SPM(type) nsSafariProfileMigrator::type
 
 static
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -46,32 +46,36 @@ const nsICommandLineHandler  = Component
 const nsIContentHandler      = Components.interfaces.nsIContentHandler;
 const nsIDocShellTreeItem    = Components.interfaces.nsIDocShellTreeItem;
 const nsIDOMChromeWindow     = Components.interfaces.nsIDOMChromeWindow;
 const nsIDOMWindow           = Components.interfaces.nsIDOMWindow;
 const nsIFactory             = Components.interfaces.nsIFactory;
 const nsIFileURL             = Components.interfaces.nsIFileURL;
 const nsIHttpProtocolHandler = Components.interfaces.nsIHttpProtocolHandler;
 const nsIInterfaceRequestor  = Components.interfaces.nsIInterfaceRequestor;
+const nsINetUtil             = Components.interfaces.nsINetUtil;
 const nsIPrefBranch          = Components.interfaces.nsIPrefBranch;
 const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
 const nsISupportsString      = Components.interfaces.nsISupportsString;
 const nsIURIFixup            = Components.interfaces.nsIURIFixup;
 const nsIWebNavigation       = Components.interfaces.nsIWebNavigation;
 const nsIWindowMediator      = Components.interfaces.nsIWindowMediator;
 const nsIWindowWatcher       = Components.interfaces.nsIWindowWatcher;
 const nsICategoryManager     = Components.interfaces.nsICategoryManager;
 const nsIWebNavigationInfo   = Components.interfaces.nsIWebNavigationInfo;
 const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
 const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
 
 const NS_BINDING_ABORTED = 0x804b0002;
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
 const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
 
+const URI_INHERITS_SECURITY_CONTEXT = nsIHttpProtocolHandler
+                                        .URI_INHERITS_SECURITY_CONTEXT;
+
 function shouldLoadURI(aURI) {
   if (aURI && !aURI.schemeIs("chrome"))
     return true;
 
   dump("*** Preventing external load of chrome: URI into browser window\n");
   dump("    Use -chrome <uri> instead\n");
   return false;
 }
@@ -425,22 +429,31 @@ var nsBrowserContentHandler = {
     }
 
     var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
     if (chromeParam) {
 
       // Handle the old preference dialog URL separately (bug 285416)
       if (chromeParam == "chrome://browser/content/pref/pref.xul") {
         openPreferences();
-      } else {
+        cmdLine.preventDefault = true;
+      } else try {
+        // only load URIs which do not inherit chrome privs
         var features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
-        openWindow(null, chromeParam, "_blank", features, "");
+        var uri = resolveURIInternal(cmdLine, chromeParam);
+        var netutil = Components.classes["@mozilla.org/network/util;1"]
+                                .getService(nsINetUtil);
+        if (!netutil.URIChainHasFlags(uri, URI_INHERITS_SECURITY_CONTEXT)) {
+          openWindow(null, uri.spec, "_blank", features, "");
+          cmdLine.preventDefault = true;
+        }
       }
-
-      cmdLine.preventDefault = true;
+      catch (e) {
+        Components.utils.reportError(e);
+      }
     }
     if (cmdLine.handleFlag("preferences", false)) {
       openPreferences();
       cmdLine.preventDefault = true;
     }
     if (cmdLine.handleFlag("silent", false))
       cmdLine.preventDefault = true;
 
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -79,19 +79,19 @@ InsertionPoint.prototype.toString = func
 /**
  * Places Controller
  */
 
 function PlacesController(aView) {
   this._view = aView;
 }
 
-PlacesController.prototype = {  
+PlacesController.prototype = {
   /**
-   * The places view. 
+   * The places view.
    */
   _view: null,
 
   isCommandEnabled: function PC_isCommandEnabled(aCommand) {
     switch (aCommand) {
     case "cmd_undo":
       return PlacesUtils.tm.numberOfUndoItems > 0;
     case "cmd_redo":
@@ -345,56 +345,46 @@ PlacesController.prototype = {
       var root = this._view.getResultNode();
       for (var i = 0; i < nodes.length; ++i) {
         if (nodes[i] == root)
           return true;      
       }
     }
     return false;
   },
-  
+
   /**
    * Looks at the data on the clipboard to see if it is paste-able. 
    * Paste-able data is:
    *   - in a format that the view can receive
    * @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
                        - clipboard data is of type TEXT_UNICODE and
                          is a valid URI.
    */
   _isClipboardDataPasteable: function PC__isClipboardDataPasteable() {
     // if the clipboard contains TYPE_X_MOZ_PLACE_* data, it is definitely
     // pasteable, with no need to unwrap all the nodes.
-    
-    var placeTypes = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
-                      PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
-                      PlacesUtils.TYPE_X_MOZ_PLACE];
-    var flavors = Cc["@mozilla.org/supports-array;1"].
-                    createInstance(Ci.nsISupportsArray);
-    for (var i = 0; i < placeTypes.length; ++i) {
-      var cstring = Cc["@mozilla.org/supports-cstring;1"].
-                      createInstance(Ci.nsISupportsCString);
-      cstring.data = placeTypes[i];
-      flavors.AppendElement(cstring);
-    }
-    var clipboard = Cc["@mozilla.org/widget/clipboard;1"].
-                      getService(Ci.nsIClipboard);
-    var hasPlacesData = clipboard.hasDataMatchingFlavors(flavors,
-                                            Ci.nsIClipboard.kGlobalClipboard);
+
+    var flavors = PlacesUtils.placesFlavors;
+    var clipboard = PlacesUtils.clipboard;
+    var hasPlacesData =
+      clipboard.hasDataMatchingFlavors(flavors,
+                                       Ci.nsIClipboard.kGlobalClipboard);
     if (hasPlacesData)
       return this._view.insertionPoint != null;
-      
+
     // if the clipboard doesn't have TYPE_X_MOZ_PLACE_* data, we also allow
     // pasting of valid "text/unicode" and "text/x-moz-url" data
     var xferable = Cc["@mozilla.org/widget/transferable;1"].
-                     createInstance(Ci.nsITransferable);
+                   createInstance(Ci.nsITransferable);
 
     xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_URL);
     xferable.addDataFlavor(PlacesUtils.TYPE_UNICODE);
     clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
-    
+
     try {
       // getAnyTransferData will throw if no data is available.
       var data = { }, type = { };
       xferable.getAnyTransferData(type, data, { });
       data = data.value.QueryInterface(Ci.nsISupportsString).data;
       if (type.value != PlacesUtils.TYPE_X_MOZ_URL &&
           type.value != PlacesUtils.TYPE_UNICODE)
         return false;
@@ -1374,22 +1364,37 @@ var PlacesControllerDragHelper = {
     }
 
     var txn = PlacesUtils.ptm.aggregateTransactions("DropItems", transactions);
     PlacesUtils.ptm.commitTransaction(txn);
   }
 };
 
 function goUpdatePlacesCommands() {
-  goUpdateCommand("placesCmd_open");
-  goUpdateCommand("placesCmd_open:window");
-  goUpdateCommand("placesCmd_open:tab");
-  goUpdateCommand("placesCmd_new:folder");
-  goUpdateCommand("placesCmd_new:bookmark");
-  goUpdateCommand("placesCmd_new:livemark");
-  goUpdateCommand("placesCmd_new:separator");
-  goUpdateCommand("placesCmd_show:info");
-  goUpdateCommand("placesCmd_moveBookmarks");
-  goUpdateCommand("placesCmd_setAsBookmarksToolbarFolder");
-  goUpdateCommand("placesCmd_reload");
-  goUpdateCommand("placesCmd_reloadMicrosummary");
-  goUpdateCommand("placesCmd_sortBy:name");
+  var placesController;
+  try {
+    // Or any other command...
+    placesController = top.document.commandDispatcher
+                          .getControllerForCommand("placesCmd_open");
+  }
+  catch(ex) { return; }
+
+  function updatePlacesCommand(aCommand) {
+    var enabled = false;
+    if (placesController)
+      enabled = placesController.isCommandEnabled(aCommand);
+    goSetCommandEnabled(aCommand, enabled);
+  }
+
+  updatePlacesCommand("placesCmd_open");
+  updatePlacesCommand("placesCmd_open:window");
+  updatePlacesCommand("placesCmd_open:tab");
+  updatePlacesCommand("placesCmd_new:folder");
+  updatePlacesCommand("placesCmd_new:bookmark");
+  updatePlacesCommand("placesCmd_new:livemark");
+  updatePlacesCommand("placesCmd_new:separator");
+  updatePlacesCommand("placesCmd_show:info");
+  updatePlacesCommand("placesCmd_moveBookmarks");
+  updatePlacesCommand("placesCmd_setAsBookmarksToolbarFolder");
+  updatePlacesCommand("placesCmd_reload");
+  updatePlacesCommand("placesCmd_reloadMicrosummary");
+  updatePlacesCommand("placesCmd_sortBy:name");
 }
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -623,16 +623,19 @@
           var node = this.selectedNode;
           return node && PlacesUtils.nodeIsURI(node) ? node : null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
+          if (this._cachedInsertionPoint !== undefined)
+            return this._cachedInsertionPoint;
+
           // By default, the insertion point is at the top level, at the end.
           var index = -1;
           var folderId = 0;
           if (PlacesUtils.nodeIsFolder(this._resultNode))
             folderId = this._resultNode.itemId;
 
           if (this.hasSelection) {
             if (PlacesUtils.nodeIsFolder(this.selectedNode)) {
@@ -640,17 +643,18 @@
               // end of the folder.
               folderId = this.selectedNode.itemId;
             } else {
               // If there is another type of node selected, the insertion point
               // is after that node.
               index = PlacesUtils.getIndexOfNode(this.selectedNode)
             }
           }
-          return new InsertionPoint(folderId, index);
+          this._cachedInsertionPoint = new InsertionPoint(folderId, index);
+          return this._cachedInsertionPoint;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <field name="peerDropTypes">PlacesUtils.GENERIC_VIEW_DROP_TYPES</field>
 
       <!-- nsIPlacesView -->
       <field name="childDropTypes">PlacesUtils.GENERIC_VIEW_DROP_TYPES</field>
@@ -830,16 +834,17 @@
             this._self.childNodes[i].removeAttribute("dragover-top");
             this._self.childNodes[i].removeAttribute("dragover-bottom");
             this._self.childNodes[i].removeAttribute("dragover-into");
           }
         },
 
         onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
           this._self._selection = event.target.node;
+          this._self._cachedInsertionPoint = undefined;
           if (event.ctrlKey)
             dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
           xferData.data = this._self._controller.getTransferData(dragAction.action);
         },
 
         canDrop: function TBV_DO_canDrop(event, session) {
           return PlacesControllerDragHelper.canDrop(this._self, -1);
         },
@@ -951,27 +956,30 @@
 
       <!-- Set selected node on DOMMenuItemActive/contextmenu events
            so that they're set up when command and click events fire. -->
       <handler event="DOMMenuItemActive"><![CDATA[
         if (event.target.parentNode == this) {
           // Set the selection to the node that was activated.  If that
           // node has a command but no data associated with it, it should
           // act on the entire menu.
+          this._cachedInsertionPoint = undefined;
           this._selection = event.target.node || this._resultNode;
         }
       ]]></handler>
       <handler event="contextmenu"><![CDATA[
         // DOMMenuItemActive is not dispatched for disabled menuitems and
         // menuseparators. Set the selection here manually.
         var popupNode = document.popupNode;
         // |popupNode == this| happens when the area between menuseparators
         // is clicked.
-        if (popupNode == this || popupNode.parentNode == this)
+        if (popupNode == this || popupNode.parentNode == this) {
           this._selection = popupNode.node || this._resultNode;
+          this._cachedInsertionPoint = undefined;
+        }
       ]]></handler>
 
       <handler event="draggesture"><![CDATA[
         if (event.target.localName == "menuitem")
           // TODO--allow menu drag if shift (or alt??) key is down
           nsDragAndDrop.startDrag(event, this._DNDObserver);
       ]]></handler>
       <handler event="dragover"><![CDATA[
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -62,17 +62,17 @@ var PlacesOrganizer = {
   
   _init: function PO__init() {
     this._places = document.getElementById("placesList");
     this._content = document.getElementById("placeContent");
 
     OptionsFilter.init(Groupers);
     Groupers.init();
 
-    // Select the specified place in the places list. 
+    // Select the specified place in the places list.
     var placeURI = "place:";
     if ("arguments" in window)
       placeURI = window.arguments[0];
 
     selectPlaceURI(placeURI);
 
     var view = this._content.treeBoxObject.view;
     if (view.rowCount > 0)
@@ -86,31 +86,74 @@ var PlacesOrganizer = {
     // Set up the advanced query builder UI
     PlacesQueryBuilder.init();
   },
 
   destroy: function PO_destroy() {
     OptionsFilter.destroy();
   },
 
+  _location: null,
+  get location() {
+    return this._location;
+  },
+
+  set location(aLocation) {
+    LOG("Node URI: " + aLocation);
+
+    if (!aLocation)
+      return aLocation;
+
+    if (this.location)
+      this._backHistory.unshift(this.location);
+
+    this._content.place = this._location = aLocation;
+
+    // update navigation commands
+    if (this._backHistory.length == 0)
+      document.getElementById("OrganizerCommand:Back").setAttribute("disabled", true);
+    else
+      document.getElementById("OrganizerCommand:Back").removeAttribute("disabled");
+    if (this._forwardHistory.length == 0)
+      document.getElementById("OrganizerCommand:Forward").setAttribute("disabled", true);
+    else
+      document.getElementById("OrganizerCommand:Forward").removeAttribute("disabled");
+
+    return aLocation;
+  },
+
+  _backHistory: [],
+  _forwardHistory: [],
+  back: function PO_back() {
+    this._forwardHistory.unshift(this.location);
+    var historyEntry = this._backHistory.shift();
+    this._location = null;
+    this.location = historyEntry;
+  },
+  forward: function PO_forward() {
+    var historyEntry = this._forwardHistory.shift();
+    this.location = historyEntry;
+  },
+
   HEADER_TYPE_SHOWING: 1,
   HEADER_TYPE_SEARCH: 2,
   HEADER_TYPE_ADVANCED_SEARCH: 3,
 
   /**
    * Updates the text shown in the heading banner above the content view. 
    * @param   type
    *          The type of information being shown - normal (built-in history or
    *          other query, bookmark folder), search results from the toolbar
    *          search box, or advanced search.
    * @param   text
    *          The text (if any) to display
    */
   setHeaderText: function PO_setHeaderText(type, text) {
     NS_ASSERT(type == 1 || type == 2 || type == 3, "Invalid Header Type");
+
     var prefix = document.getElementById("showingPrefix");
     prefix.setAttribute("value",
                         PlacesUtils.getString("headerTextPrefix" + type));
 
     var contentTitle = document.getElementById("contentTitle");
     contentTitle.setAttribute("value", text);
     
     // Hide the advanced search controls when the user hasn't searched
@@ -137,29 +180,41 @@ var PlacesOrganizer = {
     if (!dp.hidden)
       document.getElementById("placeURI").focus();
   },
 
   /**
    * Loads the place URI entered in the debug 
    */
   loadPlaceURI: function PO_loadPlaceURI() {
+
+    // clear forward history
+    this._forwardHistory.splice(0);
+
     var placeURI = document.getElementById("placeURI");
+
     var queriesRef = { }, optionsRef = { };
     PlacesUtils.history.queryStringToQueries(placeURI.value, 
                                              queriesRef, { }, optionsRef);
     
+    // for debug panel
     var autoFilterResults = document.getElementById("autoFilterResults");
     if (autoFilterResults.checked) {
       var options = 
         OptionsFilter.filter(queriesRef.value, optionsRef.value, null);
     }
     else
       options = optionsRef.value;
-    this._content.load(queriesRef.value, options);
+
+    this.location =
+      PlacesUtils.history.queriesToQueryString(queriesRef.value,
+                                               queriesRef.value.length,
+                                               options);
+    
+    placeURI.value = this.location;
 
     this.setHeaderText(this.HEADER_TYPE_SHOWING, "Debug results for: " + placeURI.value);
 
     this.updateLoadedURI();
 
     placeURI.focus();
   },
 
@@ -180,27 +235,31 @@ var PlacesOrganizer = {
    * Called when a place folder is selected in the left pane.
    * @param   resetSearchBox
    *          true if the search box should also be reset, false if it should
    *          be left alone.
    */
   onPlaceSelected: function PO_onPlaceSelected(resetSearchBox) {
     if (!this._places.hasSelection)
       return;
+
     var node = asQuery(this._places.selectedNode);
-    LOG("Node URI: " + node.uri);
+
     var queries = node.getQueries({});
 
     // Items are only excluded on the left pane
     var options = node.queryOptions.clone();
     options.excludeItems = false;
 
-    this._content.load(queries, 
-                       OptionsFilter.filter(queries, options, null));
-    
+    // clear forward history
+    this._forwardHistory.splice(0);
+
+    // update location
+    this.location = PlacesUtils.history.queriesToQueryString(queries, queries.length, options);
+   
     // Make sure the query builder is hidden.
     PlacesQueryBuilder.hide();
     if (resetSearchBox) {
       var searchFilter = document.getElementById("searchFilter");
       searchFilter.reset();
     }
 
     this.setHeaderText(this.HEADER_TYPE_SHOWING, node.title);
@@ -392,23 +451,20 @@ var PlacesOrganizer = {
     fp.init(window, PlacesUtils.getString("bookmarksBackupTitle"),
             Ci.nsIFilePicker.modeSave);
     fp.appendFilters(Ci.nsIFilePicker.filterHTML);
   
     var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
       getService(Ci.nsIProperties);
     var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
     fp.displayDirectory = backupsDir;
-  
-    var dateService = Cc["@mozilla.org/intl/scriptabledateformat;1"].
-      getService(Ci.nsIScriptableDateFormat);
 
-    var d = new Date();
-    var date = dateService.FormatDate("", dateService.dateFormatShort,
-                           d.getFullYear(), d.getMonth() + 1, d.getDate());
+    // Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
+    // and makes the alphabetical order of multiple backup files more useful.
+    var date = (new Date).toLocaleFormat("%Y-%m-%d");
     fp.defaultString = PlacesUtils.getFormattedString("bookmarksBackupFilename",
                                                       [date]);
   
     if (fp.show() != Ci.nsIFilePicker.returnCancel) {
       var ieSvc = Cc["@mozilla.org/browser/places/import-export-service;1"].
         getService(Ci.nsIPlacesImportExportService);
       ieSvc.exportHTMLToFile(fp.file);
     }
@@ -437,32 +493,16 @@ var PlacesOrganizer = {
   
     if (fp.show() != Ci.nsIFilePicker.returnCancel) {
       var ieSvc = Cc["@mozilla.org/browser/places/import-export-service;1"].
                      getService(Ci.nsIPlacesImportExportService);
       ieSvc.importHTMLFromFile(fp.file, true);
     }
   },
 
-  updateStatusBarForView: function PO_updateStatusBarForView(aView) {
-    var statusText = "";
-    var selectedNode = aView.selectedNode;
-    if (selectedNode) {
-      if (PlacesUtils.nodeIsFolder(selectedNode)) {
-        var childsCount = 
-          PlacesUtils.getFolderContents(selectedNode.itemId).root.childCount;
-        statusText = PlacesUtils.getFormattedString("status_foldercount",
-                                                    [childsCount]);
-      }
-      else if (PlacesUtils.nodeIsBookmark(selectedNode))
-        statusText = selectedNode.uri;
-    }
-    document.getElementById("status").label = statusText;
-  },
-
   onContentTreeSelect: function PO_onContentTreeSelect() {
     var contentTree = document.getElementById("placeContent");
     var deck = document.getElementById("infoDeck");
     this.updateStatusBarForView(contentTree);
     if (contentTree.hasSingleSelection) {
       var selectedNode = contentTree.selectedNode;
       if (selectedNode.itemId != -1 &&
           !PlacesUtils.nodeIsSeparator(selectedNode)) {
@@ -738,17 +778,17 @@ var PlacesQueryBuilder = {
 
   /**
    * Hides the query builder, and the match rule UI if visible.
    */
   hide: function PQB_hide() {
     var advancedSearch = document.getElementById("advancedSearch");
     // Need to collapse the advanced search box.
     advancedSearch.collapsed = true;
-    
+
     var titleDeck = document.getElementById("titleDeck");
     titleDeck.setAttribute("selectedIndex", 0);
   },
   
   /**
    * Shows the query builder
    */
   show: function PQB_show() {
@@ -773,16 +813,17 @@ var PlacesQueryBuilder = {
       this._setRowId(element.childNodes[i], rowId);
     }
   },
 
   _updateUIForRowChange: function PQB__updateUIForRowChange() {
     // Titlebar should show "match any/all" iff there are > 1 queries visible.
     var titleDeck = document.getElementById("titleDeck");
     titleDeck.setAttribute("selectedIndex", (this._numRows <= 1) ? 0 : 1);
+
     const asType = PlacesOrganizer.HEADER_TYPE_ADVANCED_SEARCH;
     PlacesOrganizer.setHeaderText(asType, "");
 
     // Update the "can add more criteria" command to make sure various +
     // buttons are disabled.
     var command = document.getElementById("OrganizerCommand_find:moreCriteria");
     if (this._numRows >= this._maxRows)
       command.setAttribute("disabled", "true");
@@ -1258,17 +1299,17 @@ var ViewMenu = {
         popup.appendChild(menuitem);      
     }
     event.stopPropagation();
   },
   
   /**
    * Set up the content of the view menu.
    */
-  populate: function VM_populate(event) {
+  populateSortMenu: function VM_populateSortMenu(event) {
     this.fillWithColumns(event, "viewUnsorted", "directionSeparator", "radio", "view.sortBy.");
 
     var sortColumn = this._getSortColumn();
     var viewSortAscending = document.getElementById("viewSortAscending");
     var viewSortDescending = document.getElementById("viewSortDescending");
     // We need to remove an existing checked attribute because the unsorted 
     // menu item is not rebuilt every time we open the menu like the others.
     var viewUnsorted = document.getElementById("viewUnsorted");
@@ -1445,17 +1486,17 @@ function GroupingConfig(substr, onLabel,
 /**
  * Handles Grouping within the Content View, and the commands that support it. 
  */
 var Groupers = {
   defaultGrouper: null,
   annotationGroupers: [],
 
   /**
-   * Initializes groupings for various vie types. 
+   * Initializes groupings for various view types. 
    */
   init: function G_init() {
     this.defaultGrouper = 
       new GroupingConfig(null, PlacesUtils.getString("defaultGroupOnLabel"),
                          PlacesUtils.getString("defaultGroupOnAccesskey"),
                          PlacesUtils.getString("defaultGroupOffLabel"),
                          PlacesUtils.getString("defaultGroupOffAccesskey"),
                          "Groupers.groupBySite()",
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -39,44 +39,49 @@
 # ***** END LICENSE BLOCK ***** 
 
 <?xml-stylesheet href="chrome://browser/content/places/places.css"?>
 <?xml-stylesheet href="chrome://browser/content/places/organizer.css"?>
 
 <?xml-stylesheet href="chrome://global/skin/"?>
 <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
 
+#ifdef XP_MACOSX
+<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
+#else
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
+#endif
 
 <!DOCTYPE window [
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
 <!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
 %editMenuOverlayDTD;
 ]>
 
 <window id="places"
-        title="&places.bm.title;" 
+        title="&places.organizer.title;" 
         windowtype="Places:Organizer" 
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="PlacesOrganizer.init();"
         onunload="PlacesOrganizer.destroy();"
         width="700" height="500" screenX="10" screenY="10"
         persist="width height screenX screenY sizemode">
 
   <script type="application/x-javascript"
           src="chrome://browser/content/places/places.js"/>
-  
-  <stringbundleset id="stringbundleset"/>
 
+#ifdef XP_MACOSX
+#include ../../../base/content/browserMountPoints.inc
+#else
   <commandset id="editMenuCommands"/>
-  <commandset id="baseMenuCommandSet"/>
   <commandset id="placesCommands"/>
+#endif
   
   <commandset id="organizerCommandSet">
     <command id="OrganizerCommand_find:all"
              label="&cmd.findInBookmarks.label;"
              accesskey="&cmd.findInBookmarks.accesskey;"
              oncommand="PlacesSearchBox.findAll();"/>
     <command id="OrganizerCommand_find:current"
              label="&cmd.findCurrent.label;"
@@ -89,25 +94,28 @@
     <command id="OrganizerCommand_backup"
              oncommand="PlacesOrganizer.backupBookmarks();"/>
     <command id="OrganizerCommand_restoreFromFile"
              oncommand="PlacesOrganizer.restoreFromFile();"/>
     <command id="OrganizerCommand_search:save"
              oncommand="PlacesOrganizer.saveSearch();"/>
     <command id="OrganizerCommand_search:moreCriteria"
              oncommand="PlacesQueryBuilder.addRow();"/>
+    <command id="OrganizerCommand:Back"
+             oncommand="PlacesOrganizer.back();"/>
+    <command id="OrganizerCommand:Forward"
+             oncommand="PlacesOrganizer.forward();"/>
   </commandset>
 
   <broadcasterset id="placesGroupingBroadcasters">
     <broadcaster id="placesBC_grouping:off"/>
     <broadcaster id="placesBC_grouping:on"/>
     <broadcaster id="placesBC_grouping:separator"/>
   </broadcasterset>
 
-  <keyset id="baseMenuKeyset"/>
   <keyset id="placesOrganizerKeyset">
     <!-- Instantiation Keys -->
     <key id="placesKey_close" key="&cmd.close.key;" modifiers="accel" 
          oncommand="close();"/>
 
     <key id="placesKey_show:debug"
          key="d" modifiers="accel,shift"
          oncommand="PlacesOrganizer.toggleDebugPanel();"/>
@@ -157,218 +165,227 @@
     <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
 #endif
   </keyset>
 
   <popupset id="placesPopupset">
     <popup id="placesContext"/>
   </popupset>
 
-  <toolbox>
-    <menubar id="placesMenubar">
-      <menu id="fileMenu" label="&file.label;" accesskey="&file.accesskey;">
-        <menupopup>
-          <menuitem id="fileNewBookmark"
+  <toolbox id="placesToolbox">
+    <toolbar class="chromeclass-toolbar" id="placesToolbar">
+      <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     command="OrganizerCommand:Back"
+                     tooltiptext="&backButton.tooltip;"
+                     accesskey="&backCmd.accesskey;"
+                     disabled="true"/>
+    
+      <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     command="OrganizerCommand:Forward"
+                     tooltiptext="&forwardButton.tooltip;"
+                     accesskey="&forwardCmd.accesskey;"
+                     disabled="true"/>
+
+      <toolbarbutton id="organizeButton" type="menu" label="&organize.label;">
+        <menupopup id="organizeButtonPopup">
+          <menuitem id="newbookmark"
                     command="placesCmd_new:bookmark"
                     label="&cmd.new_bookmark.label;"
                     accesskey="&cmd.new_bookmark.accesskey;"/>
-          <menuitem id="fileNewLivemark"
-                    command="placesCmd_new:livemark"
-                    label="&cmd.new_livemark.label;"
-                    accesskey="&cmd.new_livemark.accesskey;"/>
-          <menuitem id="fileNewFolder"
+          <menuitem id="newfolder"
                     command="placesCmd_new:folder"
                     label="&cmd.new_folder.label;"
                     accesskey="&cmd.new_folder.accesskey;"/>
-          <menuitem id="fileNewSeparator"
+          <menuitem id="newseparator"
                     command="placesCmd_new:separator"
                     label="&cmd.new_separator.label;"
                     accesskey="&cmd.new_separator.accesskey;"/>
-          <menuseparator/>
+
+          <menuseparator id="orgCutSeparator"/>
+          
+          <menuitem id="orgCut"
+                    command="cmd_cut"
+                    label="&cutCmd.label;"
+                    key="key_cut"
+                    accesskey="&cutCmd.accesskey;"
+                    selection="separator|link|folder|mixed"/>
+          <menuitem id="orgCopy"
+                    command="cmd_copy"
+                    label="&copyCmd.label;"
+                    key="key_copy"
+                    accesskey="&copyCmd.accesskey;"
+                    selection="separator|link|folder|mixed"/>
+          <menuitem id="orgPaste"
+                    command="cmd_paste"
+                    label="&pasteCmd.label;"
+                    key="key_paste"
+                    accesskey="&pasteCmd.accesskey;"
+                    selection="mutable"/>
+          <menuitem id="orgUndo"
+                    command="cmd_undo"
+                    label="&undoCmd.label;"
+                    key="key_undo"
+                    accesskey="&undoCmd.accesskey;"/>
+          <menuitem id="orgRedo"
+                    command="cmd_redo"
+                    label="&redoCmd.label;"
+                    key="key_redo"
+                    accesskey="&redoCmd.accesskey;"/>
+
+          <menuseparator id="selectAllSeparator"/>
+          
+          <menuitem id="orgSelectAll"
+                    command="cmd_selectAll"
+                    label="&selectAllCmd.label;"
+                    key="key_selectAll"
+                    accesskey="&selectAllCmd.accesskey;"/>
+
+          <menuseparator id="orgMoveSeparator"/>
+          
+          <menuitem id="orgDelete"
+                    command="cmd_delete"
+                    label="&deleteCmd.label;"
+                    key="key_delete"
+                    accesskey="&deleteCmd.accesskey;"/>
+          <menuitem id="orgRename"
+                    command="placesCmd_rename"
+                    label="&cmd.rename.label;"
+                    accesskey="&cmd.rename.accesskey;"/>
+          <menuitem id="orgProperties"
+                    command="placesCmd_show:info"
+                    label="&cmd.properties.label;"
+                    key="placesKey_show:info"
+                    accesskey="&cmd.properties.accesskey;"/>
+          
+          <menuseparator id="orgCloseSeparator"/>
+
+          <menuitem id="orgClose"
+                    key="placesKey_close" 
+                    label="&file.close.label;"
+                    accesskey="&file.close.accesskey;" 
+                    oncommand="close();"/>
+        </menupopup>
+      </toolbarbutton>
+
+      <toolbarbutton id="viewMenu" type="menu"
+                     label="&views.label;"
+                     accesskey="&view.accesskey;">
+        <menupopup id="viewMenuPopup">
+          <menuitem id="viewDetails"
+                    type="radio"
+#ifdef MACOSX
+                    label="&view.detailsMacOSX.label;"
+#else
+                    label="&view.details.label;"
+#endif
+                    accesskey="&view.details.label;">
+          </menuitem>
+
+          <menuseparator id="addonsSeparator"/>
+
+          <!--
+          <menuitem id="viewAddons"
+                    command=""
+                    label="&view.addons.label;"
+                    accesskey="&view.addons.label;"/>
+          <menuseparator id="sortingSeparator"/>
+          -->
+          <menu id="viewColumns" 
+                label="&view.columns.label;" accesskey="&view.columns.accesskey;">
+            <menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
+                       oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
+          </menu>
+          <menu id="viewSort" label="&view.sort.label;"
+                accesskey="&view.sort.accesskey;">
+            <menupopup onpopupshowing="ViewMenu.populateSortMenu(event);"
+                       oncommand="ViewMenu.setSortColumn(event.target.getAttribute('column'), null);">
+              <menuitem id="viewUnsorted" type="radio" name="columns" 
+                        label="&view.unsorted.label;" accesskey="&view.unsorted.accesskey;"
+                        oncommand="ViewMenu.setSortColumn(null, null);"/>
+              <menuseparator id="directionSeparator"/>
+              <menuitem id="viewSortAscending" type="radio" name="direction" 
+                        label="&view.sortAscending.label;" accesskey="&view.sortAscending.accesskey;"
+                        oncommand="ViewMenu.setSortColumn(null, 'ascending'); event.stopPropagation();"/>
+              <menuitem id="viewSortDescending" type="radio" name="direction" 
+                        label="&view.sortDescending.label;" accesskey="&view.sortDescending.accesskey;"
+                        oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
+            </menupopup>
+          </menu>
+          <!--
+          <menuseparator id="groupingSeparator" observes="placesBC_grouping:separator"/>
+
+          <menuitem id="viewGroupNone" type="radio" name="group"
+                    observes="placesBC_grouping:off"/>
+          <menuitem id="viewGroupGroup" type="radio" name="group"
+                    observes="placesBC_grouping:on"/>
+          -->
+        </menupopup>
+      </toolbarbutton>
+
+      <toolbarbutton id="maintenanceButton" style="min-width:0px !important;"
+                     type="menu" label="&maintenance.label;">
+        <menupopup id="maintenanceButtonPopup">
           <menuitem id="fileImport"
                     command="OrganizerCommand_import"
                     label="&cmd.import.label;"
                     accesskey="&cmd.import.accesskey;"/>
           <menuitem id="fileExport"
                     command="OrganizerCommand_export"
                     label="&cmd.export.label;"
                     accesskey="&cmd.export.accesskey;"/>
           <menuseparator/>
           <menuitem id="backupBookmarks"
                     command="OrganizerCommand_backup"
                     label="&cmd.backup.label;"
                     accesskey="&cmd.backup.accesskey;"/>
           <menu id="fileRestoreMenu" label="&cmd.restore.label;"
-                    accesskey="&cmd.export.accesskey;">
+                    accesskey="&cmd.restore.accesskey;">
             <menupopup id="fileRestorePopup" onpopupshowing="PlacesOrganizer.populateRestoreMenu();">
               <menuitem id="restoreFromFile"
                         command="OrganizerCommand_restoreFromFile"
                         label="&cmd.restoreFromFile.label;"
                         accesskey="&cmd.restoreFromFile.accesskey;"/>
             </menupopup>
           </menu>
-          <menuseparator/>
-          <menuitem id="fileClose"
-                    key="placesKey_close" 
-                    label="&file.close.label;"
-                    accesskey="&file.close.accesskey;" 
-                    oncommand="close();"/>
         </menupopup>
-      </menu>
-      <menu id="editMenu" label="&edit.label;" accesskey="&edit.accesskey;">
-        <menupopup>
-          <menuitem id="menu_undo"/>
-          <menuitem id="menu_redo"/>
-          <menuseparator/>
-          <menuitem id="menu_cut"/>
-          <menuitem id="menu_copy"/>
-          <menuitem id="menu_paste"/>
-          <menuitem id="menu_delete"/>
-          <menuseparator/>
-          <menuitem id="menu_selectAll"/>
-          <menuseparator/>
-          <menuitem id="editFindAll"
-                    command="OrganizerCommand_find:all"
-                    key="placesKey_find:all"/>
-          <menuitem id="editFindCurrent"
-                    command="OrganizerCommand_find:current"
-                    key="placesKey_find:current"/>
-          <menuseparator/>
-          <menuitem command="placesCmd_moveBookmarks"
-                    label="&cmd.moveBookmarks.menuLabel;"
-                    accesskey="&cmd.moveBookmarks.menuAccesskey;"/>
-          <menuitem command="placesCmd_setAsBookmarksToolbarFolder"
-                    label="&cmd.personalToolbarFolder.menuLabel;"
-                    accesskey="&cmd.personalToolbarFolder.menuAccesskey;"/>
-          <menuseparator/>
-          <menuitem id="editReload"
-                    command="placesCmd_reload"
-                    label="&cmd.reloadLivebookmark.label;"
-                    accesskey="&cmd.reloadLivebookmark.accesskey;"/>
-          <menuitem id="editReloadMicrosummary"
-                    command="placesCmd_reloadMicrosummary"
-                    label="&cmd.reloadMicrosummary.label;"
-                    accesskey="&cmd.reloadMicrosummary.accesskey;"/>
-          <menuseparator/>
-          <menuitem id="properties"
-                    command="placesCmd_show:info"
-                    key="placesKey_show:info"
-                    label="&cmd.properties.label;" 
-                    accesskey="&cmd.properties.accesskey;"/>
-        </menupopup>
-      </menu>
-      <menu id="viewMenu" label="&view.label;" accesskey="&view.accesskey;"
-            onpopupshowing="ViewMenu.populate(event);"
-            oncommand="ViewMenu.setSortColumn(event.target.getAttribute('column'), null);">
-        <menupopup>
-          <menuitem id="viewToolbar"
-                    type="checkbox"
-                    label="&view.toolbar.label;"
-                    accesskey="&view.toolbar.accesskey;"
-                    oncommand="goToggleToolbar('mainToolbar', 'viewToolbar'); event.stopPropagation();"
-                    checked="true"/>/>
-          <menu id="viewColumns" 
-                label="&view.columns.label;" accesskey="&view.columns.accesskey;">
-            <menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
-                       oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
-          </menu>
-          <menuseparator id="groupingSeparator" observes="placesBC_grouping:separator"/>
-          <menuitem id="viewGroupNone" type="radio" name="group"
-                    observes="placesBC_grouping:off"/>
-          <menuitem id="viewGroupGroup" type="radio" name="group"
-                    observes="placesBC_grouping:on"/>
-          <menuseparator id="columnSeparator"/>
-          <menuitem id="viewUnsorted" type="radio" name="columns" 
-                    label="&view.unsorted.label;" accesskey="&view.unsorted.accesskey;"
-                    oncommand="ViewMenu.setSortColumn(null, null);"/>
-          <menuseparator id="directionSeparator"/>
-          <menuitem id="viewSortAscending" type="radio" name="direction" 
-                    label="&view.sortAscending.label;" accesskey="&view.sortAscending.accesskey;"
-                    oncommand="ViewMenu.setSortColumn(null, 'ascending'); event.stopPropagation();"/>
-          <menuitem id="viewSortDescending" type="radio" name="direction" 
-                    label="&view.sortDescending.label;" accesskey="&view.sortDescending.accesskey;"
-                    oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
-        </menupopup>
-      </menu>
-#ifdef XP_MACOSX
-      <menu id="windowMenu"/>
-      <menupopup id="menu_ToolsPopup"/>
-#endif
-      <menu id="helpMenu"/>
-    </menubar>
+      </toolbarbutton>
 
-    <toolbar id="mainToolbar" class="chromeclass-toolbar">
-      <toolbarbutton id="newbookmark"
-                     command="placesCmd_new:bookmark"
-                     label="&cmd.new_bookmark.label;"
-                     accesskey="&cmd.new_bookmark.accesskey;"/>
-      <toolbarbutton id="newfolder"
-                     command="placesCmd_new:folder"
-                     label="&cmd.new_folder.label;"
-                     accesskey="&cmd.new_folder.accesskey;"/>
-      <toolbarbutton id="newseparator"
-                     command="placesCmd_new:separator"
-                     label="&cmd.new_separator.label;"
-                     accesskey="&cmd.new_separator.accesskey;"/>
-      <toolbarseparator/>
-      <toolbarbutton id="moveBookmark"
-                     command="placesCmd_moveBookmarks"
-                     label="&cmd.moveBookmarks.label;"
-                     accesskey="&cmd.moveBookmarks.accesskey;"/>
-      <toolbarseparator/>
-      <toolbarbutton id="properties"
-                     command="placesCmd_show:info"
-                     label="&cmd.properties.label;" 
-                     accesskey="&cmd.properties.accesskey;"/>
-      <toolbarbutton id="rename"
-                     command="placesCmd_rename"
-                     label="&cmd.rename.label;"
-                     accesskey="&cmd.rename.accesskey;"/>
-      <toolbarbutton id="delete"
-                     command="cmd_delete"
-                     label="&deleteCmd.label;"
-                     accesskey="&deleteCmd.accesskey;" />
-    </toolbar>
+      <spacer flex="1"/>
 
-    <toolbar class="chromeclass-toolbar">
       <textbox id="searchFilter" style="width: 23em;" timeout="500"
                oncommand="PlacesSearchBox.search(this.value);" 
                onreset="PlacesOrganizer.onPlaceSelected(false); return true;" 
                collection="bookmarks">
       </textbox>
-      <spacer flex="1"/>
-      <toolbarbutton id="toolbarGroupOff" type="radio" group="grouping" 
-                     observes="placesBC_grouping:off"/>
-      <toolbarbutton id="toolbarGroupOn" type="radio" group="grouping" 
-                     observes="placesBC_grouping:on" />
     </toolbar>
   </toolbox>
+
   <hbox flex="1" id="placesView">
     <tree id="placesList"
           class="placesTree"
           type="places"
           showRoot="true"
           place="place:folder=2&amp;group=3&amp;excludeItems=1&amp;queryType=1"
           hidecolumnpicker="true" context="placesContext"
-          onselect="PlacesOrganizer.onPlaceSelected(true);
-                    PlacesOrganizer.updateStatusBarForView(this);"
+          onselect="PlacesOrganizer.onPlaceSelected(true);"
           onclick="PlacesOrganizer.onTreeClick(event);"
           seltype="single"
-          persist="width">
+          persist="width"
+          width="160">
       <treecols>
         <treecol id="title" flex="1" primary="true" hideheader="true"/>
       </treecols>
       <treechildren id="placesListChildren" view="placesList"  flex="1"/>
     </tree>
     <splitter id="splitter" collapse="before" persist="state">
       <grippy/>
     </splitter>
     <vbox id="contentView" flex="4">
       <deck id="contentDeck" flex="1">
-        <vbox flex="1">
+        <vbox id="defaultView" flex="1">
           <hbox id="titlebar" align="center">
             <label id="showingPrefix"/>
             <deck id="titleDeck" flex="1">
               <label id="contentTitle" flex="1" crop="right"/>
               <hbox align="center" id="titlebarMatch" hidden="true">
                 <label value="&advancedSearch.match.label;"/>
                 <menulist id="advancedSearchType"
                           oncommand="PlacesQueryBuilder.doSearch();">
@@ -389,29 +406,28 @@
                       label="&moreCriteria.label;"
                       command="OrganizerCommand_search:moreCriteria"/>
             </hbox>
           </hbox>
 #include advancedSearch.inc          
           <tree id="placeContent" class="placesTree" context="placesContext" 
                 flex="1" type="places" 
                 ondblclick="this.controller.openSelectedNodeWithEvent(event);"
-                onclick="PlacesOrganizer.onTreeClick(event);"
-                onselect="PlacesOrganizer.updateStatusBarForView(this);">
+                onclick="PlacesOrganizer.onTreeClick(event);">
             <treecols id="placeContentColumns">
               <treecol label="&col.name.label;" id="title" flex="5" primary="true" 
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
               <treecol label="&col.tags.label;" id="tags" flex="2"
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
               <treecol label="&col.url.label;" id="url" flex="5" 
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
-              <treecol label="&col.lastvisit.label;" id="date" flex="1"
+              <treecol label="&col.lastvisit.label;" id="date" flex="1" hidden="true"
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
               <treecol label="&col.visitcount.label;" id="visitCount" flex="1" hidden="true"
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
               <treecol label="&col.keyword.label;" id="keyword" flex="1" hidden="true"
                        persist="width hidden ordinal sortActive sortDirection"/>
               <splitter class="tree-splitter"/>
@@ -458,12 +474,9 @@
               </rows>
             </grid>
             <separator class="thin"/>
           </vbox>
         </vbox>
       </deck>
     </vbox>
   </hbox>
-  <statusbar>
-    <statusbarpanel id="status" flex="1"/>
-  </statusbar>
 </window>
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -398,32 +398,36 @@
           var node = this.selectedNode;
           return node && PlacesUtils.nodeIsURI(node) ? node : null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
+          if (this._cachedInsertionPoint !== undefined)
+            return this._cachedInsertionPoint;
+
           // By default, the insertion point is at the top level, at the end. 
           var index = -1;
           var folderId = this._result.root.itemId;
 
           if (this.hasSelection) {
             if(PlacesUtils.nodeIsFolder(this.selectedNode)) {
               // If there is a folder selected, the insertion point is the
               // end of the folder.
               folderId = this.selectedNode.itemId;
             } else {
               // If there is another type of node selected, the insertion point
               // is after that node.
               index = PlacesUtils.getIndexOfNode(this.selectedNode)
             }
           }
-          return new InsertionPoint(folderId, index, 1);
+          this._cachedInsertionPoint = new InsertionPoint(folderId, index, 1);
+          return this._cachedInsertionPoint;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <field name="peerDropTypes">PlacesUtils.GENERIC_VIEW_DROP_TYPES</field>
 
       <!-- nsIPlacesView -->
       <field name="childDropTypes">PlacesUtils.GENERIC_VIEW_DROP_TYPES</field>
@@ -989,16 +993,17 @@
       <handler event="mousedown"><![CDATA[
         // When the user clicks down on a button, set it as the selection and 
         // tell the controller that we are the active view.
         if (event.target.localName == "toolbarbutton" ||
             event.target.localName == "toolbarseparator")
           this._selection = event.target.node;
         else
           this._selection = this.getResult().root;
+        this._cachedInsertionPoint = undefined;
       ]]></handler>
       <handler event="draggesture"><![CDATA[
         if (event.target.localName == "toolbarbutton")
           nsDragAndDrop.startDrag(event, this._DNDObserver);
       ]]></handler>
       <handler event="dragover"><![CDATA[
         if (!this.checkForMenuEvent(event, "dragOver"))
           nsDragAndDrop.dragOver(event, this._DNDObserver);
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -139,16 +139,17 @@
         <parameter name="queries"/>
         <parameter name="options"/>
         <body><![CDATA[
           var result = PlacesUtils.history.executeQueries(queries, queries.length, 
                                                           options);
           var treeView = new PlacesTreeView(this.showRoot);
           result.viewer = treeView;
           this.view = treeView;
+          this._cachedInsertionPoint = undefined;
         ]]></body>
       </method>
 
       <property name="showRoot">
         <getter><![CDATA[
           return this.getAttribute("showRoot") == "true";
         ]]></getter>
         <setter><![CDATA[
@@ -427,34 +428,41 @@
 
           // only URI nodes should be returned
           var node = this.getResultView().nodeForTreeIndex(min.value);
           if (PlacesUtils.nodeIsURI(node))
             return node;
           return null;
         ]]></getter>
       </property>
-      
+
+
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
+          // invalidated on selection and focus changes
+          if (this._cachedInsertionPoint !== undefined)
+            return this._cachedInsertionPoint;
+
           // there is no insertion point for history queries
           // so bail out now and save a lot of work when updating commands
           var resultNode = this.getResultNode();
           if (PlacesUtils.nodeIsQuery(resultNode)) {
             var options = asQuery(resultNode).queryOptions;
-            if (options.queryType == options.QUERY_TYPE_HISTORY) 
-              return null;
+            if (options.queryType == options.QUERY_TYPE_HISTORY)
+              return this._cachedInsertionPoint = null;
           }
 
           var orientation = NHRVO.DROP_AFTER;
           // If there is no selection, insert at the end of the container. 
           if (!this.hasSelection) {
             var index = this.view.rowCount - 1;
-            return this._getInsertionPoint(index, orientation);
+            this._cachedInsertionPoint =
+              this._getInsertionPoint(index, orientation);
+            return this._cachedInsertionPoint;
           }
 
           // This is a two-part process. The first part is determining the drop
           // orientation.
           // * The default orientation is to drop _after_ the selected item. 
           // * If the selected item is an open container, the default 
           //   orientation is to drop _into_ that container.
           //
@@ -479,17 +487,19 @@
           // If the sole selection is the bookmarks toolbar folder, we insert
           // into it even if it is not opened
           if (this.hasSingleSelection && resultView.isContainer(max.value) &&
               (resultView.isContainerOpen(max.value) ||
                resultView.nodeForTreeIndex(max.value)
                          .itemId == PlacesUtils.bookmarksRootId))
             orientation = NHRVO.DROP_ON;
 
-          return this._getInsertionPoint(max.value, orientation);
+          this._cachedInsertionPoint =
+            this._getInsertionPoint(max.value, orientation);
+          return this._cachedInsertionPoint;
         ]]></getter>
       </property>
       
       <method name="_disallowInsertion">
         <parameter name="aContainer"/>
         <body><![CDATA[
           // Disallow insertion of items under readonly folders
           // Disallow insertion of items under the places root
@@ -987,21 +997,25 @@
 
       <method name="destroyContextMenu">
         <parameter name="aPopup"/>
         <body/>
       </method>
     </implementation>
     <handlers>
       <handler event="focus"><![CDATA[
+        this._cachedInsertionPoint = undefined;
+
         // See select handler. We need the sidebar's places commandset to be
         // updated as well
         document.commandDispatcher.updateCommands("focus");
       ]]></handler>
       <handler event="select"><![CDATA[
+        this._cachedInsertionPoint = undefined;
+
         // This additional complexity is here for the sidebars
         var win = window;
         while (true) {
           win.document.commandDispatcher.updateCommands("focus");
           if (win == window.top)
             break;
 
           win = win.parent;
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -195,16 +195,25 @@ var PlacesUtils = {
   get ptm() {
     if (!this._ptm) {
       this._ptm = Cc["@mozilla.org/browser/placesTransactionsService;1"].
                   getService(Components.interfaces.nsIPlacesTransactionsService);
     }
     return this._ptm;
   },
 
+  _clipboard: null,
+  get clipboard() {
+    if (!this._clipboard) {
+      this._clipboard = Cc["@mozilla.org/widget/clipboard;1"].
+                        getService(Ci.nsIClipboard);
+    }
+    return this._clipboard;
+  },
+
   /**
    * Makes a URI from a spec.
    * @param   aSpec
    *          The string spec of the URI
    * @returns A URI object for the spec.
    */
   _uri: function PU__uri(aSpec) {
     NS_ASSERT(aSpec, "empty URL spec");
@@ -532,17 +541,17 @@ var PlacesUtils = {
                   childNodes.push(childObj);
               }
               var parent = node;
               node = { folder: parent,
                        children: childNodes,
                        type: self.TYPE_X_MOZ_PLACE_CONTAINER };
               bNode.containerOpen = wasOpen;
             }
-          } 
+          }
           return node;
         }
         return JSON.toString(gatherDataPlace(convertNode(aNode)));
 
       case this.TYPE_X_MOZ_URL:
         function gatherDataUrl(bNode) {
           if (self.nodeIsLivemarkContainer(bNode)) {
             var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec;
@@ -600,17 +609,17 @@ var PlacesUtils = {
     function gatherDataText(bNode) {
       if (self.nodeIsLivemarkContainer(bNode))
         return self.livemarks.getSiteURI(bNode.itemId).spec;
       if (self.nodeIsContainer(bNode)) {
         asContainer(bNode);
         var wasOpen = bNode.containerOpen;
         if (!wasOpen)
           bNode.containerOpen = true;
-          
+
         var childString = bNode.title + NEWLINE;
         var cc = bNode.childCount;
         for (var i = 0; i < cc; ++i) {
           var child = bNode.getChild(i);
           var suffix = i < (cc - 1) ? NEWLINE : "";
           childString += gatherDataText(child) + suffix;
         }
         bNode.containerOpen = wasOpen;
@@ -664,24 +673,24 @@ var PlacesUtils = {
     var keyword = aData.keyword;
     var annos = aData.annos;
     if (aExcludeAnnotations) {
       annos =
         annos.filter(function(aValue, aIndex, aArray) {
                        return aExcludeAnnotations.indexOf(aValue.name) == -1;
                     });
     }
-    
+
     return this.ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword,
                                annos);
   },
 
   /**
    * Gets a transaction for copying (recursively nesting to include children)
-   * a folder (or container) and its contents from one folder to another. 
+   * a folder (or container) and its contents from one folder to another.
    *
    * @param   aData
    *          Unwrapped dropped folder data - Obj containing folder and children
    * @param   aContainer
    *          The container we are copying into
    * @param   aIndex
    *          The index in the destination container to insert the new items
    * @returns A nsITransaction object that will perform the copy.
@@ -691,22 +700,22 @@ var PlacesUtils = {
     var self = this;
     function getChildItemsTransactions(aChildren) {
       var childItemsTransactions = [];
       var cc = aChildren.length;
       var index = aIndex;
       for (var i = 0; i < cc; ++i) {
         var txn = null;
         var node = aChildren[i];
-        
+
         // adjusted to make sure that items are given the correct index -
         // transactions insert differently if index == -1
         if (aIndex > -1)
           index = aIndex + i;
-          
+
         if (node.type == self.TYPE_X_MOZ_PLACE_CONTAINER) {
           if (node.folder) {
             var title = node.folder.title;
             var annos = node.folder.annos;
             var folderItemsTransactions =
               getChildItemsTransactions(node.children);
             txn = self.ptm.createFolder(title, -1, index, annos,
                                         folderItemsTransactions);
@@ -818,21 +827,21 @@ var PlacesUtils = {
         var siteURI = this._uri(data.uri.site);
         return this.ptm.createLivemark(feedURI, siteURI, data.title, container,
                                        index, data.annos);
       }
       break;
     case this.TYPE_X_MOZ_PLACE:
       if (data.id <= 0)
         return this._getURIItemCopyTransaction(data, container, index);
-  
+
       if (copy) {
         // Copying a child of a live-bookmark by itself should result
         // as a new normal bookmark item (bug 376731)
-        var copyBookmarkAnno = 
+        var copyBookmarkAnno =
           this._getBookmarkItemCopyTransaction(data, container, index,
                                                ["livemark/bookmarkFeedURI"]);
         return copyBookmarkAnno;
       }
       break;
     case this.TYPE_X_MOZ_PLACE_SEPARATOR:
       if (copy) {
         // There is no data in a separator, so copying it just amounts to
@@ -1628,16 +1637,34 @@ var PlacesUtils = {
 
   openURINodesInTabs: function PU_openURINodesInTabs(aNodes, aEvent) {
     var urlsToOpen = [];
     for (var i=0; i < aNodes.length; i++) {
       if (this.nodeIsURI(aNodes[i]))
         urlsToOpen.push(aNodes[i].uri);
     }
     this._openTabset(urlsToOpen, aEvent);
+  },
+
+  _placesFlavors: null,
+  get placesFlavors() {
+    if (!this._placesFlavors) {
+      var placeTypes = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
+                        PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
+                        PlacesUtils.TYPE_X_MOZ_PLACE];
+      this._placesFlavors = Cc["@mozilla.org/supports-array;1"].
+                            createInstance(Ci.nsISupportsArray);
+      for (var i = 0; i < placeTypes.length; ++i) {
+        var cstring = Cc["@mozilla.org/supports-cstring;1"].
+                        createInstance(Ci.nsISupportsCString);
+        cstring.data = placeTypes[i];
+        this._placesFlavors.AppendElement(cstring);
+      }
+    }
+    return this._placesFlavors;
   }
 };
 
 PlacesUtils.GENERIC_VIEW_DROP_TYPES = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
                                        PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
                                        PlacesUtils.TYPE_X_MOZ_PLACE,
                                        PlacesUtils.TYPE_X_MOZ_URL,
                                        PlacesUtils.TYPE_UNICODE];
--- a/browser/components/places/src/nsPlacesImportExportService.cpp
+++ b/browser/components/places/src/nsPlacesImportExportService.cpp
@@ -2532,17 +2532,19 @@ nsPlacesImportExportService::ArchiveBook
 
   // construct the new leafname
   PRTime          now64 = PR_Now();
   PRExplodedTime  nowInfo;
   PR_ExplodeTime(now64, PR_LocalTimeParameters, &nowInfo);
   PR_NormalizeTime(&nowInfo, PR_LocalTimeParameters);
 
   char timeString[128];
-  
+
+  // Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
+  // and makes the alphabetical order of multiple backup files more useful.
   PR_FormatTime(timeString, 128, "bookmarks-%Y-%m-%d.html", &nowInfo);
 
   //nsCAutoString backupFilenameCString(timeString);
   //nsAutoString backupFilenameString = NS_ConvertUTF8toUTF16(backupFilenameCString);
   nsAutoString backupFilenameString = NS_ConvertUTF8toUTF16((timeString));
 
   nsCOMPtr<nsIFile> backupFile;
   if (forceArchive) {
--- a/browser/components/preferences/advanced.xul
+++ b/browser/components/preferences/advanced.xul
@@ -202,17 +202,17 @@
 
            <!-- Cache -->
            <groupbox id="cacheGroup">
              <caption label="&cache.label;"/>
 
              <hbox align="center">
                <label id="useCacheBefore"
                       accesskey="&useCacheBefore.accesskey;">&useCacheBefore.label;</label>
-               <textbox id="cacheSize" size="2"
+               <textbox id="cacheSize" type="number" size="2"
                         preference="browser.cache.disk.capacity"
                         onsyncfrompreference="return gAdvancedPane.readCacheSize();"
                         onsynctopreference="return gAdvancedPane.writeCacheSize();"
                         aaa:labelledby="useCacheBefore cacheSize useCacheAfter"/>
                <label id="useCacheAfter" flex="1">&useCacheAfter.label;</label>
                <button id="clearCacheButton" icon="clear"
                        label="&clearDataNow.label2;"
                        oncommand="gAdvancedPane.clearCache();"/>
--- a/browser/components/preferences/applications.js
+++ b/browser/components/preferences/applications.js
@@ -170,16 +170,17 @@ function HandlerInfoWrapper(aType, aHand
 }
 
 HandlerInfoWrapper.prototype = {
   // The wrapped nsIHandlerInfo object.  In general, this object is private,
   // but there are a couple cases where callers access it directly for things
   // we haven't (yet?) implemented, so we make it a public property.
   wrappedHandlerInfo: null,
 
+
   //**************************************************************************//
   // Convenience Utils
 
   _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
                getService(Ci.nsIHandlerService),
 
   // Retrieve this as nsIPrefBranch and then immediately QI to nsIPrefBranch2
   // so both interfaces are available to callers.
@@ -191,46 +192,32 @@ HandlerInfoWrapper.prototype = {
                 getService(Ci.nsICategoryManager),
 
   element: function(aID) {
     return document.getElementById(aID);
   },
 
 
   //**************************************************************************//
-  // nsISupports
-
-  QueryInterface: function(aIID) {
-    if (aIID.equals(Ci.nsIHandlerInfo) ||
-        aIID.equals(Ci.nsISupports) ||
-        (aIID.equals(Ci.nsIMIMEInfo) &&
-         this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  //**************************************************************************//
   // nsIHandlerInfo
 
   // The MIME type or protocol scheme.
   _type: null,
   get type() {
     return this._type;
   },
 
   get description() {
     if (this.wrappedHandlerInfo.description)
       return this.wrappedHandlerInfo.description;
 
     if (this.primaryExtension) {
-      let bundle = this.element("bundlePreferences");
       var extension = this.primaryExtension.toUpperCase();
-      return bundle.getFormattedString("fileEnding", [extension]);
+      return this.element("bundlePreferences").getFormattedString("fileEnding",
+                                                                  [extension]);
     }
 
     return this.type;
   },
 
   get preferredApplicationHandler() {
     return this.wrappedHandlerInfo.preferredApplicationHandler;
   },
@@ -411,20 +398,16 @@ HandlerInfoWrapper.prototype = {
 
   //**************************************************************************//
   // Storage
 
   store: function() {
     this._handlerSvc.store(this.wrappedHandlerInfo);
   },
 
-  remove: function() {
-    this._handlerSvc.remove(this.wrappedHandlerInfo);
-  },
-
 
   //**************************************************************************//
   // Icons
 
   get smallIcon() {
     return this._getIcon(16);
   },
 
@@ -478,17 +461,17 @@ var feedHandlerInfo = {
   _shellSvc: Cc["@mozilla.org/browser/shell-service;1"].
              getService(Ci.nsIShellService),
 
 
   //**************************************************************************//
   // nsIHandlerInfo
 
   get description() {
-    return gApplicationsPane._bundle.getString("webFeed");
+    return this.element("bundlePreferences").getString("webFeed");
   },
 
   get preferredApplicationHandler() {
     switch (this.element(PREF_FEED_SELECTED_READER).value) {
       case "client":
         var file = this.element(PREF_FEED_SELECTED_APP).value;
         if (file)
           return getLocalHandlerApp(file);
@@ -688,19 +671,16 @@ var feedHandlerInfo = {
 
   // Changes to the preferred action and handler take effect immediately
   // (we write them out to the preferences right as they happen), so we don't
   // need to do anything when the controller calls store() after modifying
   // the handler.
   // XXX Should we hold off on making the changes until this method gets called?
   store: function() {},
 
-  // The feed type cannot be removed.
-  remove: function() {},
-
 
   //**************************************************************************//
   // Icons
 
   get smallIcon() {
     return "chrome://browser/skin/feeds/feedIcon16.png";
   },
 
@@ -714,17 +694,18 @@ var feedHandlerInfo = {
 //****************************************************************************//
 // Prefpane Controller
 
 var gApplicationsPane = {
   // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
   // objects, indexed by type.
   _handledTypes: {},
 
-  _bundle       : null,
+  _brandBundle  : null,
+  _prefsBundle  : null,
   _list         : null,
   _filter       : null,
 
   // Retrieve this as nsIPrefBranch and then immediately QI to nsIPrefBranch2
   // so both interfaces are available to callers.
   _prefSvc      : Cc["@mozilla.org/preferences-service;1"].
                   getService(Ci.nsIPrefBranch).
                   QueryInterface(Ci.nsIPrefBranch2),
@@ -742,17 +723,18 @@ var gApplicationsPane = {
                   getService(Ci.nsIIOService),
 
 
   //**************************************************************************//
   // Initialization & Destruction
 
   init: function() {
     // Initialize shortcuts to some commonly accessed elements.
-    this._bundle = document.getElementById("bundlePreferences");
+    this._brandBundle = document.getElementById("bundleBrand");
+    this._prefsBundle = document.getElementById("bundlePreferences");
     this._list = document.getElementById("handlersView");
     this._filter = document.getElementById("filter");
 
     // Observe preferences that influence what we display so we can rebuild
     // the view when they change.
     this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this, false);
     this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this, false);
     this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this, false);
@@ -982,27 +964,20 @@ var gApplicationsPane = {
 
       // We couldn't find any reason to exclude the type, so include it.
       visibleTypes.push(handlerInfo);
     }
 
     return visibleTypes;
   },
 
-  // FIXME: we filter on type and primary extension, but we don't show those
-  // values to users, unlike the description and action description, which we
-  // do show, and that could be confusing, so filter only on the values we show.
-  // Filed as bug 395139.
   _matchesFilter: function(aType) {
     var filterValue = this._filter.value.toLowerCase();
     return aType.description.toLowerCase().indexOf(filterValue) != -1 ||
-           this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1 ||
-           aType.type.toLowerCase().indexOf(filterValue) != -1 ||
-           (aType.primaryExtension &&
-            aType.primaryExtension.toLowerCase().indexOf(filterValue) != -1);
+           this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1;
   },
 
   /**
    * Describe, in a human-readable fashion, the preferred action to take on
    * the type represented by the given handler info object.
    *
    * XXX Should this be part of the HandlerInfoWrapper interface?  It would
    * violate the separation of model and view, but it might make more sense
@@ -1012,29 +987,29 @@ var gApplicationsPane = {
    *                                      is being described
    */
   _describePreferredAction: function(aHandlerInfo) {
     // alwaysAskBeforeHandling overrides the preferred action, so if that flag
     // is set, then describe that behavior instead.  Currently we hide all types
     // with alwaysAskBeforeHandling except for the feed type, so here we use
     // a feed-specific message to describe the behavior.
     if (aHandlerInfo.alwaysAskBeforeHandling)
-      return this._bundle.getString("alwaysAskAboutFeed");
+      return this._prefsBundle.getString("alwaysAskAboutFeed");
 
     switch (aHandlerInfo.preferredAction) {
       case Ci.nsIHandlerInfo.saveToDisk:
-        return this._bundle.getString("saveToDisk");
+        return this._prefsBundle.getString("saveToDisk");
 
       case Ci.nsIHandlerInfo.useHelperApp:
         return aHandlerInfo.preferredApplicationHandler.name;
 
       case Ci.nsIHandlerInfo.handleInternally:
         // For the feed type, handleInternally means live bookmarks.
         if (aHandlerInfo.type == TYPE_MAYBE_FEED)
-          return this._bundle.getString("liveBookmarks");
+          return this._prefsBundle.getString("liveBookmarks");
 
         // For other types, handleInternally looks like either useHelperApp
         // or useSystemDefault depending on whether or not there's a preferred
         // handler app.
         if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
           return aHandlerInfo.preferredApplicationHandler.name;
 
         return aHandlerInfo.defaultDescription;
@@ -1043,17 +1018,20 @@ var gApplicationsPane = {
         // Is it because the app can't actually do that?  But if that's true,
         // then why would a preferredAction ever get set to this value
         // in the first place?
 
       case Ci.nsIHandlerInfo.useSystemDefault:
         return aHandlerInfo.defaultDescription;
 
       case kActionUsePlugin:
-        return aHandlerInfo.plugin.name;
+        let brandShortName = this._brandBundle.getString("brandShortName");
+        return this._prefsBundle.getFormattedString("pluginName",
+                                                    [aHandlerInfo.plugin.name,
+                                                     brandShortName]);
     }
   },
 
   /**
    * Whether or not the given handler app is valid.
    *
    * @param aHandlerApp {nsIHandlerApp} the handler app in question
    *
@@ -1087,32 +1065,38 @@ var gApplicationsPane = {
     var menu =
       document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
     var menuPopup = menu.firstChild;
 
     // Clear out existing items.
     while (menuPopup.hasChildNodes())
       menuPopup.removeChild(menuPopup.lastChild);
 
-    // If this is the feed type, add "always ask" and "live bookmarks" items.
+    // If this is the feed type, add Preview in Firefox and Live Bookmarks items.
     if (handlerInfo.type == TYPE_MAYBE_FEED) {
       let menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("alwaysAsk", "true");
-      menuItem.setAttribute("label", this._bundle.getString("alwaysAskAboutFeed"));
+      menuItem.setAttribute("label",
+                            this._prefsBundle.getString("alwaysAskAboutFeed"));
       menuPopup.appendChild(menuItem);
       if (handlerInfo.alwaysAskBeforeHandling)
         menu.selectedItem = menuItem;
 
       menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
-      menuItem.setAttribute("label", this._bundle.getString("liveBookmarks"));
+      menuItem.setAttribute("label", this._prefsBundle.getString("liveBookmarks"));
       menuItem.setAttribute("image", "chrome://browser/skin/page-livemarks.png");
       menuPopup.appendChild(menuItem);
       if (handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally)
         menu.selectedItem = menuItem;
+
+      // Add a separator to distinguish these items from the helper app items
+      // that follow them.
+      menuItem = document.createElementNS(kXULNS, "menuseparator");
+      menuPopup.appendChild(menuItem);
     }
 
     // Create a menu item for the OS default application, if any.
     if (handlerInfo.hasDefaultHandler) {
       let menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("action", Ci.nsIHandlerInfo.useSystemDefault);
       menuItem.setAttribute("label", handlerInfo.defaultDescription);
 
@@ -1153,56 +1137,49 @@ var gApplicationsPane = {
           preferredApp.equals(possibleApp))
         menu.selectedItem = menuItem;
     }
 
     // Create a menu item for the plugin.
     if (handlerInfo.plugin) {
       let menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("action", kActionUsePlugin);
-      menuItem.setAttribute("label", handlerInfo.plugin.name);
+      let brandShortName = this._brandBundle.getString("brandShortName");
+      let label = this._prefsBundle.getFormattedString("pluginName",
+                                                       [handlerInfo.plugin.name,
+                                                        brandShortName]);
+      menuItem.setAttribute("label", label);
       menuPopup.appendChild(menuItem);
       if (handlerInfo.preferredAction == kActionUsePlugin)
         menu.selectedItem = menuItem;
     }
 
     // Create a menu item for saving to disk.
     // Note: this option isn't available to protocol types, since we don't know
     // what it means to save a URL having a certain scheme to disk, nor is it
     // available to feeds, since the feed code doesn't implement the capability.
     // And it's not available to types handled only by plugins either, although
     // I would think we'd want to give users the ability to redirect that stuff
     // to disk (so maybe we should revisit that decision).
-    if ((handlerInfo instanceof Ci.nsIMIMEInfo) &&
+    if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
         handlerInfo.type != TYPE_MAYBE_FEED &&
         !handlerInfo.handledOnlyByPlugin) {
       let menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
-      menuItem.setAttribute("label", this._bundle.getString("saveToDisk"));
+      menuItem.setAttribute("label", this._prefsBundle.getString("saveToDisk"));
       menuPopup.appendChild(menuItem);
       if (handlerInfo.preferredAction == Ci.nsIHandlerInfo.saveToDisk)
         menu.selectedItem = menuItem;
     }
 
     // Create a menu item for selecting a local application.
     {
       let menuItem = document.createElementNS(kXULNS, "menuitem");
       menuItem.setAttribute("oncommand", "gApplicationsPane.chooseApp(event)");
-      menuItem.setAttribute("label", this._bundle.getString("chooseApp"));
-      menuPopup.appendChild(menuItem);
-    }
-
-    // Create a menu item for removing this entry unless it's a plugin
-    // or the feed type, which cannot be removed.
-    // XXX Should this perhaps be a button on the entry, or should we perhaps
-    // provide no UI for removing entries at all?
-    if (!handlerInfo.plugin && handlerInfo.type != TYPE_MAYBE_FEED) {
-      let menuItem = document.createElementNS(kXULNS, "menuitem");
-      menuItem.setAttribute("oncommand", "gApplicationsPane.removeType(event)");
-      menuItem.setAttribute("label", this._bundle.getString("removeType"));
+      menuItem.setAttribute("label", this._prefsBundle.getString("chooseApp"));
       menuPopup.appendChild(menuItem);
     }
   },
 
 
   //**************************************************************************//
   // Sorting & Filtering
 
@@ -1322,25 +1299,23 @@ var gApplicationsPane = {
 
       // Set the plugin state if we're enabling or disabling a plugin.
       if (action == kActionUsePlugin)
         handlerInfo.enablePluginType();
       else if (handlerInfo.plugin && !handlerInfo.isDisabledPluginType)
         handlerInfo.disablePluginType();
 
       // Set the preferred application handler.
-      // FIXME: consider leaving the existing preferred app in the list
-      // when we set the preferred action to something other than useHelperApp
-      // so that legacy datastores that don't have the preferred app in the list
+      // We leave the existing preferred app in the list when we set
+      // the preferred action to something other than useHelperApp so that
+      // legacy datastores that don't have the preferred app in the list
       // of possible apps still include the preferred app in the list of apps
-      // the user can use to handle the type.  Filed as bug 395140.
+      // the user can choose to handle the type.
       if (action == Ci.nsIHandlerInfo.useHelperApp)
         handlerInfo.preferredApplicationHandler = actionItem.handlerApp;
-      else
-        handlerInfo.preferredApplicationHandler = null;
 
       // Set the "always ask" flag.
       handlerInfo.alwaysAskBeforeHandling = false;
 
       // Set the preferred action.
       handlerInfo.preferredAction = action;
     }
 
@@ -1353,17 +1328,17 @@ var gApplicationsPane = {
   },
 
   chooseApp: function(aEvent) {
     // Don't let the normal "on select action" handler get this event,
     // as we handle it specially ourselves.
     aEvent.stopPropagation();
 
     var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-    var winTitle = this._bundle.getString("fpTitleChooseApp");
+    var winTitle = this._prefsBundle.getString("fpTitleChooseApp");
     fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
     fp.appendFilters(Ci.nsIFilePicker.filterApps);
 
     if (fp.show() == Ci.nsIFilePicker.returnOK && fp.file) {
       // XXXben - we need to compare this with the running instance executable
       //          just don't know how to do that via script...
       // XXXmano TBD: can probably add this to nsIShellService
 #ifdef XP_WIN
@@ -1392,50 +1367,16 @@ var gApplicationsPane = {
     }
 
     // We rebuild the actions menu whether the user picked an app or canceled.
     // If they picked an app, we want to add the app to the menu and select it.
     // If they canceled, we want to go back to their previous selection.
     this.rebuildActionsMenu();
   },
 
-  removeType: function() {
-    var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
-                        getService(Ci.nsIPromptService);
-    var flags = Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0;
-    flags += Ci.nsIPromptService.BUTTON_TITLE_CANCEL * Ci.nsIPromptService.BUTTON_POS_1;
-
-    var title = this._bundle.getString("removeTitle");
-    var message = this._bundle.getString("removeMessage");
-    var button = this._bundle.getString("removeButton");
-    var rv = promptService.confirmEx(window, title, message, flags, button, 
-                                     null, null, null, { value: 0 });
-
-    if (rv == 0) {
-      // Remove information about the type from the handlers datastore.
-      let listItem = this._list.selectedItem;
-      let handlerInfo = this._handledTypes[listItem.type];
-      handlerInfo.remove();
-
-      // Select the next item in the list (or the previous item if the item
-      // being removed is the last item).
-      if (this._list.selectedIndex == this._list.getRowCount() - 1)
-        this._list.selectedIndex = this._list.selectedIndex - 1;
-      else
-        this._list.selectedIndex = this._list.selectedIndex + 1;
-
-      // Remove the item from the list.
-      this._list.removeChild(listItem);
-    }
-    else {
-      // Rebuild the actions menu so we go back to their previous selection.
-      this.rebuildActionsMenu();
-    }
-  },
-
   // Mark which item in the list was last selected so we can reselect it
   // when we rebuild the list or when the user returns to the prefpane.
   onSelectionChanged: function() {
     this._list.setAttribute("lastSelectedType",
                             this._list.selectedItem.getAttribute("type"));
   },
 
   _getIconURLForPreferredAction: function(aHandlerInfo) {
--- a/browser/components/preferences/applications.xul
+++ b/browser/components/preferences/applications.xul
@@ -73,18 +73,16 @@
 
     <script type="application/x-javascript" src="chrome://browser/content/preferences/applications.js"/>
 
     <keyset>
       <key key="&focusSearch1.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
       <key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
     </keyset>
 
-    <label>&prefpane.label;</label>
-
     <vbox flex="1" class="contentPane">
       <hbox align="center">
         <label accesskey="&filter.accesskey;" control="filter">&filter.label;</label>
         <textbox id="filter" flex="1" oninput="gApplicationsPane.onFilterInput();" 
                 onkeypress="gApplicationsPane.onFilterKeyPress(event);"/>
         <button id="clearFilter" icon="clear" label="&clear.label;" accesskey="&clear.accesskey;" 
                 oncommand="gApplicationsPane.clearFilter();" disabled="true"/>
       </hbox>
--- a/browser/components/preferences/connection.xul
+++ b/browser/components/preferences/connection.xul
@@ -110,17 +110,17 @@
             <row align="center">
               <hbox pack="end">
                 <label value="&http.label;" accesskey="&http.accesskey;" control="networkProxyHTTP"/>
               </hbox>
               <hbox align="center">
                 <textbox id="networkProxyHTTP" flex="1"
                          preference="network.proxy.http" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyServer();"/>
                 <label value="&port.label;" accesskey="&HTTPport.accesskey;" control="networkProxyHTTP_Port"/>
-                <textbox id="networkProxyHTTP_Port" size="5"
+                <textbox id="networkProxyHTTP_Port" type="number" max="65535" size="5"
                          preference="network.proxy.http_port" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyPort();"/>
               </hbox>
             </row>
             <row>
               <hbox/>
               <hbox>
                 <checkbox id="shareAllProxies" label="&shareproxy.label;" accesskey="&shareproxy.accesskey;"
                           preference="network.proxy.share_proxy_settings"
@@ -130,53 +130,53 @@
             <row align="center">
               <hbox pack="end">
                 <label value="&ssl.label;" accesskey="&ssl.accesskey;" control="networkProxySSL"/>
               </hbox>
               <hbox align="center">
                 <textbox id="networkProxySSL" flex="1" preference="network.proxy.ssl"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', false);"/>
                 <label value="&port.label;" accesskey="&SSLport.accesskey;" control="networkProxySSL_Port"/>
-                <textbox id="networkProxySSL_Port" size="5" preference="network.proxy.ssl_port"
+                <textbox id="networkProxySSL_Port" type="number" max="65535" size="5" preference="network.proxy.ssl_port"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', true);"/>
               </hbox>
             </row>
             <row align="center">
               <hbox pack="end">
                 <label value="&ftp.label;" accesskey="&ftp.accesskey;" control="networkProxyFTP"/>
               </hbox>
               <hbox align="center">
                 <textbox id="networkProxyFTP" flex="1" preference="network.proxy.ftp"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', false);"/>
                 <label value="&port.label;" accesskey="&FTPport.accesskey;" control="networkProxyFTP_Port"/>
-                <textbox id="networkProxyFTP_Port" size="5" preference="network.proxy.ftp_port"
+                <textbox id="networkProxyFTP_Port" type="number" max="65535" size="5" preference="network.proxy.ftp_port"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', true);"/>
               </hbox>
             </row>
             <row align="center">
               <hbox pack="end">
                 <label value="&gopher.label;" accesskey="&gopher.accesskey;" control="networkProxyGopher"/>
               </hbox>
               <hbox align="center">
                 <textbox id="networkProxyGopher" flex="1" preference="network.proxy.gopher"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('gopher', false);"/>
                 <label value="&port.label;" accesskey="&gopherPort.accesskey;" control="networkProxyGopher_Port"/>
-                <textbox id="networkProxyGopher_Port" size="5" preference="network.proxy.gopher_port"
+                <textbox id="networkProxyGopher_Port" type="number" max="65535" size="5" preference="network.proxy.gopher_port"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('gopher', true);"/>
               </hbox>
             </row>
             <row align="center">
               <hbox pack="end">
                 <label value="&socks.label;" accesskey="&socks.accesskey;" control="networkProxySOCKS"/>
               </hbox>
               <hbox align="center">
                 <textbox id="networkProxySOCKS" flex="1" preference="network.proxy.socks"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', false);"/>
                 <label value="&port.label;" accesskey="&SOCKSport.accesskey;" control="networkProxySOCKS_Port"/>
-                <textbox id="networkProxySOCKS_Port" size="5" preference="network.proxy.socks_port"
+                <textbox id="networkProxySOCKS_Port" type="number" max="65535" size="5" preference="network.proxy.socks_port"
                          onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', true);"/>
               </hbox>
             </row>
             <row>
               <spacer/>
               <radiogroup id="networkProxySOCKSVersion" orient="horizontal"
                           preference="network.proxy.socks_version">
                 <radio id="networkProxySOCKSVersion4" value="4" label="&socks4.label;" accesskey="&socks4.accesskey;" />
--- a/browser/components/preferences/preferences.xul
+++ b/browser/components/preferences/preferences.xul
@@ -85,17 +85,18 @@
             style="&prefWin.styleWin;">
 #else
 #ifdef XP_MACOSX
             style="&prefWindow.styleMac;">
 #else
             style="&prefWin.styleGNOME;">
 #endif
 #endif
-  
+
+    <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
     <stringbundle id="bundlePreferences"
                   src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <prefpane id="paneMain" label="&paneMain.title;"
               src="chrome://browser/content/preferences/main.xul"/>
     <prefpane id="paneTabs" label="&paneTabs.title;"
               src="chrome://browser/content/preferences/tabs.xul"/>
     <prefpane id="paneContent" label="&paneContent.title;"
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -103,17 +103,17 @@
       <caption label="&history.label;"/>
 
       <hbox align="center">
         <checkbox id="rememberHistoryDays"
                   label="&rememberBefore.label;"
                   accesskey="&rememberBefore.accesskey;"
                   oncommand="gPrivacyPane.onchangeHistoryDaysCheck();"
                   aaa:labelledby="rememberHistoryDays historyDays rememberAfter"/>
-        <textbox id="historyDays" size="3"
+        <textbox id="historyDays" type="number" size="3"
                  aaa:labelledby="rememberHistoryDays historyDays rememberAfter"/>
         <label id="rememberAfter"> &rememberAfter.label;</label>
       </hbox>
       <checkbox id="rememberForms"
                 label="&rememberForms.label;"
                 accesskey="&rememberForms.accesskey;"
                 preference="browser.formfill.enable"/>
       <checkbox id="rememberDownloads"
--- a/browser/components/preferences/tabs.xul
+++ b/browser/components/preferences/tabs.xul
@@ -44,17 +44,17 @@
 %brandDTD;
 <!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
 %tabsDTD;
 ]>
 
 <overlay id="TabsPaneOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
-  <prefpane id="paneTabs" helpTopic="prefs-tabs" helpURI="chrome://browser/locale/help/help.rdf" flex="1">
+  <prefpane id="paneTabs" helpTopic="prefs-tabs" helpURI="chrome://browser/locale/help/help.rdf">
 
     <preferences id="tabsPreferences">
       <preference id="browser.link.open_external"      name="browser.link.open_external"      type="int"/>
       <preference id="browser.link.open_newwindow"     name="browser.link.open_newwindow"     type="int"/>
       <preference id="browser.tabs.autoHide"           name="browser.tabs.autoHide"           type="bool" inverted="true"/>
       <preference id="browser.tabs.loadInBackground"   name="browser.tabs.loadInBackground"   type="bool" inverted="true"/>
       <preference id="browser.tabs.warnOnClose"        name="browser.tabs.warnOnClose"        type="bool"/>
       <preference id="browser.tabs.warnOnOpen"         name="browser.tabs.warnOnOpen"         type="bool"/>
@@ -70,18 +70,18 @@
                   onsynctopreference="return gTabsPane.writeLinkTarget();">
         <radio label="&inNewWindow.label;" accesskey="&inNewWindow.accesskey;" value="2"/>
         <radio label="&inNewTab.label;" accesskey="&inNewTab.accesskey;" value="3"/>
       </radiogroup>
     </vbox>
 
     <separator id="tabsSeparator"/>
 
-    <!-- XXX flex below and on prefpane is a hack because wrapping checkboxes don't
-             reflow properly; see bug 349098 -->
+    <!-- XXX flex below is a hack because wrapping checkboxes don't reflow
+             properly; see bug 349098 -->
     <vbox id="tabPrefsBox" align="start" flex="1">
       <checkbox id="warnCloseMultiple" label="&warnCloseMultipleTabs.label;"
                 accesskey="&warnCloseMultipleTabs.accesskey;"
                 preference="browser.tabs.warnOnClose"/>
       <checkbox id="warnOpenMany" label="&warnOpenManyTabs.label;"
                 accesskey="&warnOpenManyTabs.accesskey;"
                 preference="browser.tabs.warnOnOpen"/>
       <checkbox id="showTabBar" label="&showTabBar.label;"
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -93,17 +93,17 @@
                        autocompletepopup="PopupAutoComplete"
                        autocompletesearch="search-autocomplete"
                        autocompletesearchparam="searchbar-history"
                        timeout="250"
                        maxrows="10"
                        completeselectedindex="true"
                        showcommentcolumn="true"
                        tabscrolling="true"
-                       xbl:inherits="disabled,disableautocomplete,searchengine,src">
+                       xbl:inherits="disabled,disableautocomplete,searchengine,src,newlines">
           </xul:textbox>
         </xul:hbox>
 
         <xul:stack class="search-go-button-stack endcap">
           <xul:box class="endcap-box" chromedir="&locale.dir;"/>
           <xul:toolbarbutton class="search-go-button"
                              anonid="search-go-button"
                              chromedir="&locale.dir;"
@@ -128,25 +128,29 @@
           this.rebuildPopup();
           this.updateDisplay();
           this._textbox._displayCurrentEngine();
 
           var os =
                Components.classes["@mozilla.org/observer-service;1"]
                          .getService(Components.interfaces.nsIObserverService);
           os.addObserver(this, "browser-search-engine-modified", false);
+          
+          this._addedObserver = true;
         ]]></body>
       </method>
 
       <destructor><![CDATA[
-        var os = Components.classes["@mozilla.org/observer-service;1"]
-                           .getService(Components.interfaces.nsIObserverService);
-        os.removeObserver(this, "browser-search-engine-modified");
+        if (this._addedObserver) {
+          var os = Components.classes["@mozilla.org/observer-service;1"]
+                             .getService(Components.interfaces.nsIObserverService);
+          os.removeObserver(this, "browser-search-engine-modified");
+        }
 
-        // Make sure to break the cycle from _texbox to us.  Otherwise we leak
+        // Make sure to break the cycle from _texbox to us. Otherwise we leak
         // the world.
         this._textbox.mController.input = null;
       ]]></destructor>
 
       <field name="_stringBundle">document.getAnonymousElementByAttribute(this,
           "anonid", "searchbar-stringbundle");</field>
       <field name="_textbox">document.getAnonymousElementByAttribute(this,
           "anonid", "searchbar-textbox");</field>
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -1,80 +1,79 @@
-/* ***** 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 the nsSessionStore component.
- *
- * The Initial Developer of the Original Code is
- * Simon Bünzli <zeniko@gmail.com>
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dietrich Ayala <autonome@gmail.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 ***** */
+/* 
+# ***** 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 the nsSessionStore component.
+# *
+# * The Initial Developer of the Original Code is
+# * Simon Bünzli <zeniko@gmail.com>
+# * Portions created by the Initial Developer are Copyright (C) 2006
+# * the Initial Developer. All Rights Reserved.
+# *
+# * Contributor(s):
+# *   Dietrich Ayala <autonome@gmail.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 ***** 
+*/
 
 /**
- * Session Storage and Restoration
- * 
- * Overview
- * This service reads user's session file at startup, and makes a determination 
- * as to whether the session should be restored. It will restore the session 
- * under the circumstances described below.
- * 
- * Crash Detection
- * The session file stores a session.state property, that 
- * indicates whether the browser is currently running. When the browser shuts 
- * down, the field is changed to "stopped". At startup, this field is read, and
- * if it's value is "running", then it's assumed that the browser had previously
- * crashed, or at the very least that something bad happened, and that we should
- * restore the session.
- * 
- * Forced Restarts
- * In the event that a restart is required due to application update or extension
- * installation, set the browser.sessionstore.resume_session_once pref to true,
- * and the session will be restored the next time the browser starts.
- * 
- * Always Resume
- * This service will always resume the session if the integer pref 
- * browser.startup.page is set to 3.
- */
+# * Session Storage and Restoration
+# * 
+# * Overview
+# * This service reads user's session file at startup, and makes a determination 
+# * as to whether the session should be restored. It will restore the session 
+# * under the circumstances described below.
+# * 
+# * Crash Detection
+# * The session file stores a session.state property, that 
+# * indicates whether the browser is currently running. When the browser shuts 
+# * down, the field is changed to "stopped". At startup, this field is read, and
+# * if it's value is "running", then it's assumed that the browser had previously
+# * crashed, or at the very least that something bad happened, and that we should
+# * restore the session.
+# * 
+# * Forced Restarts
+# * In the event that a restart is required due to application update or extension
+# * installation, set the browser.sessionstore.resume_session_once pref to true,
+# * and the session will be restored the next time the browser starts.
+# * 
+# * Always Resume
+# * This service will always resume the session if the integer pref 
+# * browser.startup.page is set to 3.
+*/
 
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
-
-const CID = Components.ID("{ec7a6c20-e081-11da-8ad9-0800200c9a66}");
-const CONTRACT_ID = "@mozilla.org/browser/sessionstartup;1";
-const CLASS_NAME = "Browser Session Startup Service";
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const STATE_RUNNING_STR = "running";
 
 function debug(aMsg) {
   aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
                                      .logStringMessage(aMsg);
 }
@@ -105,17 +104,17 @@ SessionStartup.prototype = {
     // get file references
     var dirService = Cc["@mozilla.org/file/directory_service;1"].
                      getService(Ci.nsIProperties);
     this._sessionFile = dirService.get("ProfD", Ci.nsILocalFile);
     this._sessionFile.append("sessionstore.js");
     
     // only read the session file if config allows possibility of restoring
     var resumeFromCrash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
-    if (resumeFromCrash || this._doResumeSession()) {
+    if ((resumeFromCrash || this._doResumeSession()) && this._sessionFile.exists()) {
       // get string containing session state
       this._iniString = this._readFile(this._sessionFile);
       if (this._iniString) {
         try {
           // parse the session state into JS objects
           var s = new Components.utils.Sandbox("about:blank");
           var initialState = Components.utils.evalInSandbox(this._iniString, s);
 
@@ -336,89 +335,29 @@ SessionStartup.prototype = {
       
       return content.replace(/\r\n?/g, "\n");
     }
     catch (ex) { } // inexisting file?
     
     return null;
   },
 
-/* ........ QueryInterface .............. */
+  /* ........ QueryInterface .............. */
+  QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
+                                          Ci.nsISupportsWeakReference,
+                                          Ci.nsISessionStartup]),
+  classDescription: "Browser Session Startup Service",
+  classID:          Components.ID("{ec7a6c20-e081-11da-8ad9-0800200c9a66}"),
+  contractID:       "@mozilla.org/browser/sessionstartup;1",
 
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && !aIID.equals(Ci.nsIObserver) && 
-      !aIID.equals(Ci.nsISupportsWeakReference) && 
-      !aIID.equals(Ci.nsISessionStartup)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
+  // get this contractID registered for certain categories via XPCOMUtils
+  _xpcom_categories: [
+    // make ourselves a startup observer
+    { category: "app-startup", service: true }
+  ]
+
 };
 
-/* :::::::: Service Registration & Initialization ::::::::::::::: */
-
-/* ........ nsIModule .............. */
-
-const SessionStartupModule = {
-
-  getClassObject: function(aCompMgr, aCID, aIID) {
-    if (aCID.equals(CID)) {
-      return SessionStartupFactory;
-    }
-    
-    Components.returnCode = Cr.NS_ERROR_NOT_REGISTERED;
-    return null;
-  },
-
-  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.registerFactoryLocation(CID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
-
-    var catMan = Cc["@mozilla.org/categorymanager;1"].
-                 getService(Ci.nsICategoryManager);
-    catMan.addCategoryEntry("app-startup", CLASS_NAME, "service," + CONTRACT_ID, true, true);
-  },
-
-  unregisterSelf: function(aCompMgr, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.unregisterFactoryLocation(CID, aLocation);
-
-    var catMan = Cc["@mozilla.org/categorymanager;1"].
-                 getService(Ci.nsICategoryManager);
-    catMan.deleteCategoryEntry( "app-startup", "service," + CONTRACT_ID, true);
-  },
-
-  canUnload: function(aCompMgr) {
-    return true;
-  }
+//module initialization
+function NSGetModule(aCompMgr, aFileSpec) {
+  return XPCOMUtils.generateModule([SessionStartup]);
 }
 
-/* ........ nsIFactory .............. */
-
-const SessionStartupFactory = {
-
-  createInstance: function(aOuter, aIID) {
-    if (aOuter != null) {
-      Components.returnCode = Cr.NS_ERROR_NO_AGGREGATION;
-      return null;
-    }
-    
-    return (new SessionStartup()).QueryInterface(aIID);
-  },
-
-  lockFactory: function(aLock) { },
-
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && !aIID.equals(Ci.nsIModule) &&
-        !aIID.equals(Ci.nsIFactory) && !aIID.equals(Ci.nsISessionStartup)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
-};
-
-function NSGetModule(aComMgr, aFileSpec) {
-  return SessionStartupModule;
-}
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -652,16 +652,18 @@ SessionStoreService.prototype = {
 
   setWindowState: function sss_setWindowState(aWindow, aState, aOverwrite) {
     this.restoreWindow(aWindow, "(" + aState + ")", aOverwrite);
   },
 
   getClosedTabCount: function sss_getClosedTabCount(aWindow) {
     if (!aWindow.__SSi && aWindow.__SS_dyingCache)
       return aWindow.__SS_dyingCache._closedTabs.length;
+    if (!aWindow.__SSi)
+      return 0; // not a browser window, or not otherwise tracked by SS.
     
     return this._windows[aWindow.__SSi]._closedTabs.length;
   },
 
   closedTabNameAt: function sss_closedTabNameAt(aWindow, aIx) {
     var tabs;
     
     if (aWindow.__SSi && aWindow.__SSi in this._windows)
@@ -864,39 +866,75 @@ SessionStoreService.prototype = {
       entry.subframe = true;
     }
     if (!(aEntry instanceof Ci.nsISHEntry)) {
       return entry;
     }
     
     var cacheKey = aEntry.cacheKey;
     if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32) {
+      // XXXbz would be better to have cache keys implement
+      // nsISerializable or something.
       entry.cacheKey = cacheKey.data;
     }
     entry.ID = aEntry.ID;
     
+    entry.contentType = aEntry.contentType;
+    
     var x = {}, y = {};
     aEntry.getScrollPosition(x, y);
     entry.scroll = x.value + "," + y.value;
     
     try {
       var prefPostdata = this._prefBranch.getIntPref("sessionstore.postdata");
       if (prefPostdata && aEntry.postData && this._checkPrivacyLevel(aEntry.URI.schemeIs("https"))) {
         aEntry.postData.QueryInterface(Ci.nsISeekableStream).
                         seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
-        var stream = Cc["@mozilla.org/scriptableinputstream;1"].
-                     createInstance(Ci.nsIScriptableInputStream);
-        stream.init(aEntry.postData);
-        var postdata = stream.read(stream.available());
-        if (prefPostdata == -1 || postdata.replace(/^(Content-.*\r\n)+(\r\n)*/, "").length <= prefPostdata) {
-          entry.postdata = postdata;
+        var stream = Cc["@mozilla.org/binaryinputstream;1"].
+                     createInstance(Ci.nsIBinaryInputStream);
+        stream.setInputStream(aEntry.postData);
+        var postBytes = stream.readByteArray(stream.available());
+        var postdata = String.fromCharCode.apply(null, postBytes);
+        if (prefPostdata == -1 ||
+            postdata.replace(/^(Content-.*\r\n)+(\r\n)*/, "").length <=
+              prefPostdata) {
+          // We can stop doing base64 encoding once our serialization into JSON
+          // is guaranteed to handle all chars in strings, including embedded
+          // nulls.
+          entry.postdata_b64 = btoa(postdata);
         }
       }
     }
     catch (ex) { debug(ex); } // POSTDATA is tricky - especially since some extensions don't get it right
+
+    if (aEntry.owner) {
+      // Not catching anything specific here, just possible errors
+      // from writeCompoundObject and the like.
+      try {
+        var binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].
+                           createInstance(Ci.nsIObjectOutputStream);
+        var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
+        pipe.init(false, false, 0, 0xffffffff, null);
+        binaryStream.setOutputStream(pipe.outputStream);
+        binaryStream.writeCompoundObject(aEntry.owner, Ci.nsISupports, true);
+        binaryStream.close();
+
+        // Now we want to read the data from the pipe's input end and encode it.
+        var scriptableStream = Cc["@mozilla.org/binaryinputstream;1"].
+                               createInstance(Ci.nsIBinaryInputStream);
+        scriptableStream.setInputStream(pipe.inputStream);
+        var ownerBytes =
+          scriptableStream.readByteArray(scriptableStream.available());
+        // We can stop doing base64 encoding once our serialization into JSON
+        // is guaranteed to handle all chars in strings, including embedded
+        // nulls.
+        entry.owner_b64 = btoa(String.fromCharCode.apply(null, ownerBytes));
+      }
+      catch (ex) { debug(ex); }
+    }
     
     if (!(aEntry instanceof Ci.nsISHContainer)) {
       return entry;
     }
     
     for (var i = 0; i < aEntry.childCount; i++) {
       var child = aEntry.GetChildAt(i);
       if (child) {
@@ -1415,16 +1453,17 @@ SessionStoreService.prototype = {
                   createInstance(Ci.nsISHEntry);
     
     var ioService = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService);
     shEntry.setURI(ioService.newURI(aEntry.url, null, null));
     shEntry.setTitle(aEntry.title || aEntry.url);
     shEntry.setIsSubFrame(aEntry.subframe || false);
     shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
+    shEntry.contentType = aEntry.contentType;
     
     if (aEntry.cacheKey) {
       var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
                      createInstance(Ci.nsISupportsPRUint32);
       cacheKey.data = aEntry.cacheKey;
       shEntry.cacheKey = cacheKey;
     }
     if (aEntry.ID) {
@@ -1437,23 +1476,48 @@ SessionStoreService.prototype = {
         aIdMap.used[id] = true;
       }
       shEntry.ID = id;
     }
     
     var scrollPos = (aEntry.scroll || "0,0").split(",");
     scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
     shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
-    
-    if (aEntry.postdata) {
+
+    var postdata;
+    if (aEntry.postdata_b64) {  // Firefox 3
+      postdata = atob(aEntry.postdata_b64);
+    } else if (aEntry.postdata) { // Firefox 2
+      postdata = aEntry.postdata;
+    }
+
+    if (postdata) {
       var stream = Cc["@mozilla.org/io/string-input-stream;1"].
                    createInstance(Ci.nsIStringInputStream);
-      stream.setData(aEntry.postdata, -1);
+      stream.setData(postdata, postdata.length);
       shEntry.postData = stream;
     }
+
+    if (aEntry.owner_b64) {  // Firefox 3
+      var ownerInput = Cc["@mozilla.org/io/string-input-stream;1"].
+                       createInstance(Ci.nsIStringInputStream);
+      var binaryData = atob(aEntry.owner_b64);
+      ownerInput.setData(binaryData, binaryData.length);
+      var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
+                         createInstance(Ci.nsIObjectInputStream);
+      binaryStream.setInputStream(ownerInput);
+      try { // Catch possible deserialization exceptions
+        shEntry.owner = binaryStream.readObject(true);
+      } catch (ex) { debug(ex); }
+    } else if (aEntry.ownerURI) { // Firefox 2
+      var uriObj = ioService.newURI(aEntry.ownerURI, null, null);
+      shEntry.owner = Cc["@mozilla.org/scriptsecuritymanager;1"].
+                      getService(Ci.nsIScriptSecurityManager).
+                      getCodebasePrincipal(uriObj);
+    }
     
     if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
       for (var i = 0; i < aEntry.children.length; i++) {
         shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
       }
     }
     
     return shEntry;
deleted file mode 100644
--- a/browser/components/shell/content/dummyWindow.xul
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- ***** BEGIN LICENSE BLOCK *****
-   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
-   -
-   - The contents of this file are subject to the Mozilla Public License Version
-   - 1.1 (the "License"); you may not use this file except in compliance with
-   - the License. You may obtain a copy of the License at
-   - http://www.mozilla.org/MPL/
-   -
-   - Software distributed under the License is distributed on an "AS IS" basis,
-   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-   - for the specific language governing rights and limitations under the
-   - License.
-   -
-   - The Original Code is Mozilla WinXP SP1 Support.
-   -
-   - The Initial Developer of the Original Code is
-   - Netscape Communications Corporation.
-   - Portions created by the Initial Developer are Copyright (C) 2002
-   - the Initial Developer. All Rights Reserved.
-   -
-   - Contributor(s):
-   -   Bill Law  <law@netscape.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 LGPL or the GPL. 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 ***** -->
-
-<!-- This is a dummy window that autocloses.  See nsDefaultBrowser.js. -->
-
-<!DOCTYPE window>
-
-<window id="dummyWindow" onload="window.close()"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-</window>
--- a/browser/components/shell/jar.mn
+++ b/browser/components/shell/jar.mn
@@ -1,7 +1,3 @@
-toolkit.jar:
-    content/global/dummyWindow.xul (content/dummyWindow.xul)
-
 browser.jar:
 *       content/browser/setDesktopBackground.xul              (content/setDesktopBackground.xul)
 *       content/browser/setDesktopBackground.js               (content/setDesktopBackground.js)
-
--- a/browser/fuel/test/browser_Application.js
+++ b/browser/fuel/test/browser_Application.js
@@ -6,21 +6,23 @@ function test() {
   
   // I'd test these against a specific value, but that is bound to flucuate
   ok(Application.id, "Check to see if an ID exists for the Application");
   ok(Application.name, "Check to see if a name exists for the Application");
   ok(Application.version, "Check to see if a version exists for the Application");
   
   var wMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
   var console = wMediator.getMostRecentWindow("global:console");
+  waitForExplicitFinish();
   if (!console) {
     Application.console.open();
-    setTimeout(checkConsole, 500);
   }
+  setTimeout(checkConsole, 500);
 }
 
 function checkConsole() {
   var wMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
   var console = wMediator.getMostRecentWindow("global:console");
   ok(console, "Check to see if the console window opened");
   if (console)
     console.close();
+  finish();
 }
--- a/browser/installer/unix/packages-static
+++ b/browser/installer/unix/packages-static
@@ -182,16 +182,17 @@ bin/components/xpcom_io.xpt
 bin/components/xpcom_threads.xpt
 bin/components/xpcom_xpti.xpt
 bin/components/xpconnect.xpt
 bin/components/xpinstall.xpt
 bin/components/xremoteservice.xpt
 bin/components/xulapp.xpt
 bin/components/xuldoc.xpt
 bin/components/xultmpl.xpt
+bin/components/zipwriter.xpt
 bin/components/shellservice.xpt
 ; JavaScript components
 bin/components/FeedProcessor.js
 bin/components/FeedConverter.js
 bin/components/FeedWriter.js
 bin/components/fuelApplication.js
 bin/components/WebContentConverter.js
 bin/components/nsBrowserContentHandler.js
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -5,8 +5,9 @@
 !define FileInstallerEXE      "@PKG_BASENAME@.installer.exe"
 !define FileInstallerMSI      "@PKG_BASENAME@.installer.msi"
 !define FileInstallerNETRoot  "@PKG_BASENAME@.net-installer"
 
 !define FileMainEXE           "@MOZ_APP_NAME@.exe"
 !define WindowClass           "FirefoxMessageWindow"
 !define DDEApplication        "Firefox"
 !define AppRegName            "Firefox"
+!define MinUnsupportedVer     "Microsoft Windows 2000"
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -29,18 +29,18 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-# Also requires:
-# ShellLink plugin http://nsis.sourceforge.net/ShellLink_plug-in
+# Required Plugins:
+# ShellLink    http://nsis.sourceforge.net/ShellLink_plug-in
 
 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
 !verbose 3
 
 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
 ; uncompressed and use 7-Zip to create a SFX archive of it
 SetDatablockOptimize on
 SetCompress off
@@ -54,68 +54,77 @@ CRCCheck on
 !system 'echo ; > shortcuts.ini'
 
 Var TmpVal
 Var StartMenuDir
 Var InstallType
 Var AddStartMenuSC
 Var AddQuickLaunchSC
 Var AddDesktopSC
-Var fhInstallLog
-Var fhUninstallLog
 
 ; Other included files may depend upon these includes!
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
 !include TextFunc.nsh
 !include WinMessages.nsh
 !include WordFunc.nsh
 !include MUI.nsh
 
-!insertmacro FileJoin
-!insertmacro GetTime
-!insertmacro LineFind
+; WinVer.nsh was added in the same release that RequestExecutionLevel so check
+; if ___WINVER__NSH___ is defined to determine if RequestExecutionLevel is
+; available.
+!include /NONFATAL WinVer.nsh
+!ifdef ___WINVER__NSH___
+  RequestExecutionLevel admin
+!else
+  !warning "Installer will be created without Vista compatibility.$\n            \
+            Upgrade your NSIS installation to at least version 2.22 to resolve."
+!endif
+
 !insertmacro StrFilter
-!insertmacro TrimNewLines
 !insertmacro WordFind
 !insertmacro WordReplace
 !insertmacro GetSize
-!insertmacro GetParameters
-!insertmacro GetOptions
 
 ; NSIS provided macros that we have overridden
 !include overrides.nsh
 !insertmacro LocateNoDetails
 !insertmacro TextCompareNoDetails
 
 ; The following includes are custom.
 !include branding.nsi
 !include defines.nsi
 !include common.nsh
 !include locales.nsi
 !include version.nsh
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
 
+; Must be inserted before other macros that use logging
+!insertmacro _LoggingCommon
+
 !insertmacro AddHandlerValues
-!insertmacro CanWriteToInstallDir
-!insertmacro CheckDiskSpace
-!insertmacro CleanVirtualStore
 !insertmacro CloseApp
 !insertmacro CreateRegKey
-!insertmacro GetLongPath
-!insertmacro GetSingleInstallPath
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
 !insertmacro WriteRegStr2
 !insertmacro WriteRegDWORD2
 
 !include shared.nsh
 
+; Helper macros for ui callbacks. Insert these after shared.nsh
+!insertmacro CheckCustomCommon
+!insertmacro InstallEndCleanupCommon
+!insertmacro InstallOnInitCommon
+!insertmacro InstallStartCleanupCommon
+!insertmacro LeaveDirectoryCommon
+!insertmacro PreDirectoryCommon
+
 Name "${BrandFullName}"
 OutFile "setup.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}\"
 ShowInstDetails nevershow
 
 ReserveFile options.ini
 ReserveFile components.ini
@@ -141,17 +150,17 @@ ReserveFile shortcuts.ini
 
 /**
  * Installation Pages
  */
 ; Welcome Page
 !insertmacro MUI_PAGE_WELCOME
 
 ; License Page
-!define MUI_LICENSEPAGE_RADIOBUTTONS
+!define MUI_LICENSEPAGE_CHECKBOX
 !insertmacro MUI_PAGE_LICENSE license.rtf
 
 ; Custom Options Page
 Page custom preOptions leaveOptions
 
 ; Custom Components Page
 Page custom preComponents leaveComponents
 
@@ -168,37 +177,40 @@ Page custom preShortcuts leaveShortcuts
 !define MUI_PAGE_CUSTOMFUNCTION_PRE preStartMenu
 !define MUI_STARTMENUPAGE_NODISABLE
 !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
 !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main"
 !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
 !insertmacro MUI_PAGE_STARTMENU Application $StartMenuDir
 
 ; Install Files Page
-!define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveInstFiles
+!define MUI_PAGE_CUSTOMFUNCTION_PRE preInstFiles
 !insertmacro MUI_PAGE_INSTFILES
 
 ; Finish Page
 !define MUI_FINISHPAGE_NOREBOOTSUPPORT
 !define MUI_FINISHPAGE_TITLE_3LINES
 !define MUI_FINISHPAGE_RUN
 !define MUI_FINISHPAGE_RUN_FUNCTION LaunchApp
 !define MUI_FINISHPAGE_RUN_TEXT $(LAUNCH_TEXT)
 !define MUI_PAGE_CUSTOMFUNCTION_PRE preFinish
 !insertmacro MUI_PAGE_FINISH
 
 ################################################################################
 # Install Sections
 
-Section "-Application" Section1
-  SectionIn 1 RO
-  SetDetailsPrint textonly
+; Cleanup operations to perform at the start of the installation.
+Section "-InstallStartCleanup"
+  SetDetailsPrint both
   DetailPrint $(STATUS_CLEANUP)
   SetDetailsPrint none
 
+  SetOutPath $INSTDIR
+  ${StartInstallLog} "${BrandFullName}" "${AB_CD}" "${AppVersion}" "${GREVersion}"
+
   ; Try to delete the app's main executable and if we can't delete it try to
   ; close the app. This allows running an instance that is located in another
   ; directory and prevents the launching of the app during the installation.
   ; A copy of the executable is placed in a temporary directory so it can be
   ; copied back in the case where a specific file is checked / found to be in
   ; use that would prevent a successful install.
 
   ; Create a temporary backup directory.
@@ -239,93 +251,37 @@ Section "-Application" Section1
 
   StrCpy $R1 "xpicleanup.exe"
   Call CheckInUse
 
   SetOutPath $INSTDIR
   RmDir /r "$TmpVal"
   ClearErrors
 
-  ; During an install Vista checks if a new entry is added under the uninstall
-  ; registry key (e.g. ARP). When the same version of the app is installed on
-  ; top of an existing install the key is deleted / added and the Program
-  ; Compatibility Assistant doesn't see this as a new entry and displays an
-  ; error to the user. See Bug 354000.
-  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
-  DeleteRegKey HKLM "$0"
-
-  ; Remove files that may be left behind by the application in the
-  ; VirtualStore directory.
-  ${CleanVirtualStore}
-
-  ${If} $InstallType != 1
+  ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
     ; Custom installs.
     ; If DOMi is installed and this install includes DOMi remove it from
     ; the installation directory. This will remove it if the user deselected
     ; DOMi on the components page.
     ${If} ${FileExists} "$INSTDIR\extensions\inspector@mozilla.org"
     ${AndIf} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
       RmDir /r "$INSTDIR\extensions\inspector@mozilla.org"
     ${EndIf}
   ${EndIf}
 
-  Call CleanupOldLogs
-
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
-    ; Diff cleanup.log with uninstall.bak
-    ${LogHeader} "Updating Uninstall Log With XPInstall Wizard Logs"
-    StrCpy $R0 "$INSTDIR\uninstall\uninstall.log"
-    StrCpy $R1 "$INSTDIR\uninstall\cleanup.log"
-    GetTempFileName $R2
-    FileOpen $R3 $R2 w
-    ${TextCompareNoDetails} "$R1" "$R0" "SlowDiff" "GetDiff"
-    FileClose $R3
-
-    ${Unless} ${Errors}
-      ${FileJoin} "$INSTDIR\uninstall\uninstall.log" "$R2" "$INSTDIR\uninstall\uninstall.log"
-    ${EndUnless}
-    ${DeleteFile} "$INSTDIR\uninstall\cleanup.log"
-    ${DeleteFile} "$R2"
-    ${DeleteFile} "$INSTDIR\uninstall\uninstall.bak"
-    Rename "$INSTDIR\uninstall\uninstall.log" "$INSTDIR\uninstall\uninstall.bak"
-  ${EndIf}
-
-  ${Unless} ${FileExists} "$INSTDIR\uninstall"
-    CreateDirectory "$INSTDIR\uninstall"
-  ${EndUnless}
+  ${InstallStartCleanupCommon}
+SectionEnd
 
-  FileOpen $fhUninstallLog "$INSTDIR\uninstall\uninstall.log" w
-  FileOpen $fhInstallLog "$INSTDIR\install.log" w
-
-  ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
-  FileWrite $fhInstallLog "${BrandFullName} Installation Started: $2-$1-$0 $4:$5:$6"
-  Call WriteLogSeparator
-
-  ${LogHeader} "Installation Details"
-  ${LogMsg} "Install Dir: $INSTDIR"
-  ${LogMsg} "Locale     : ${AB_CD}"
-  ${LogMsg} "App Version: ${AppVersion}"
-  ${LogMsg} "GRE Version: ${GREVersion}"
+Section "-Application" APP_IDX
+  ${StartUninstallLog}
 
-  ${If} ${FileExists} "$EXEDIR\removed-files.log"
-    ${LogHeader} "Removing Obsolete Files and Directories"
-    ${LineFind} "$EXEDIR\removed-files.log" "/NUL" "1:-1" "onInstallDeleteFile"
-    ${LineFind} "$EXEDIR\removed-files.log" "/NUL" "1:-1" "onInstallRemoveDir"
-  ${EndIf}
-
-  ${DeleteFile} "$INSTDIR\install_wizard.log"
-  ${DeleteFile} "$INSTDIR\install_status.log"
-
-  RmDir /r "$INSTDIR\updates"
-  ${DeleteFile} "$INSTDIR\updates.xml"
-  ${DeleteFile} "$INSTDIR\active-update.xml"
-
-  SetDetailsPrint textonly
+  SetDetailsPrint both
   DetailPrint $(STATUS_INSTALL_APP)
   SetDetailsPrint none
+
   ${LogHeader} "Installing Main Files"
   StrCpy $R0 "$EXEDIR\nonlocalized"
   StrCpy $R1 "$INSTDIR"
   Call DoCopyFiles
 
   ; Register DLLs
   ; XXXrstrong - AccessibleMarshal.dll can be used by multiple applications but
   ; is only registered for the last application installed. When the last
@@ -349,30 +305,25 @@ Section "-Application" Section1
   ${LogUninstall} "File: \components\xpti.dat"
   ${LogUninstall} "File: \.autoreg"
   ${LogUninstall} "File: \active-update.xml"
   ${LogUninstall} "File: \install.log"
   ${LogUninstall} "File: \install_status.log"
   ${LogUninstall} "File: \install_wizard.log"
   ${LogUninstall} "File: \updates.xml"
 
-  SetDetailsPrint textonly
+  SetDetailsPrint both
   DetailPrint $(STATUS_INSTALL_LANG)
   SetDetailsPrint none
+
   ${LogHeader} "Installing Localized Files"
   StrCpy $R0 "$EXEDIR\localized"
   StrCpy $R1 "$INSTDIR"
   Call DoCopyFiles
 
-  ${If} $InstallType != 4
-    ${If} ${FileExists} "$INSTDIR\extensions\inspector@mozilla.org"
-      Call installInspector
-    ${EndIf}
-  ${EndIf}
-
   ${LogHeader} "Adding Additional Files"
   ; Check if QuickTime is installed and copy the nsIQTScriptablePlugin.xpt from
   ; its plugins directory into the app's components directory.
   ClearErrors
   ReadRegStr $R0 HKLM "Software\Apple Computer, Inc.\QuickTime" "InstallDir"
   ${Unless} ${Errors}
     Push $R0
     ${GetPathFromRegStr}
@@ -405,23 +356,24 @@ Section "-Application" Section1
   ${EndIf}
 
   ; Default for creating Desktop shortcut (1 = create, 0 = don't create)
   ${If} $AddDesktopSC == ""
     StrCpy $AddDesktopSC "1"
   ${EndIf}
 
   ; Remove registry entries for non-existent apps and for apps that point to our
-  ; install location in the Software\Mozilla key.
+  ; install location in the Software\Mozilla key and uninstall registry entries
+  ; that point to our install location for both HKCU and HKLM.
   SetShellVarContext current  ; Set SHCTX to HKCU
   ${RegCleanMain} "Software\Mozilla"
+  ${RegCleanUninstall}
+
   SetShellVarContext all  ; Set SHCTX to HKLM
   ${RegCleanMain} "Software\Mozilla"
-
-  ; Remove uninstall entries that point to our install location
   ${RegCleanUninstall}
 
   ${LogHeader} "Adding Registry Entries"
   ClearErrors
   WriteRegStr HKLM "Software\Mozilla\InstallerTest" "InstallerTest" "Test"
   ${If} ${Errors}
     SetShellVarContext current  ; Set SHCTX to HKCU
     StrCpy $TmpVal "HKCU" ; used primarily for logging
@@ -477,61 +429,74 @@ Section "-Application" Section1
   StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
   ${CreateRegKey} "$TmpVal" "$0" 0
 
   !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
 
   ; Create Start Menu shortcuts
   ${LogHeader} "Adding Shortcuts"
   ${If} $AddStartMenuSC == 1
-    CreateDirectory "$SMPROGRAMS\$StartMenuDir"
+    ${Unless} ${FileExists} "$SMPROGRAMS\$StartMenuDir"
+      CreateDirectory "$SMPROGRAMS\$StartMenuDir"
+      ${LogMsg} "Added Start Menu Directory: $SMPROGRAMS\$StartMenuDir"
+    ${EndUnless}
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk"
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} ($(SAFE_MODE)).lnk" "$INSTDIR\${FileMainEXE}" "-safe-mode" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} ($(SAFE_MODE)).lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} ($(SAFE_MODE)).lnk"
   ${EndIf}
 
   ; perhaps use the uninstall keys
   ${If} $AddQuickLaunchSC == 1
     CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $QUICKLAUNCH\${BrandFullName}.lnk"
+    ${LogMsg} "Added Shortcut: $QUICKLAUNCH\${BrandFullName}.lnk"
   ${EndIf}
 
-  ${LogHeader} "Updating Quick Launch Shortcuts"
   ${If} $AddDesktopSC == 1
     CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $DESKTOP\${BrandFullName}.lnk"
+    ${LogMsg} "Added Shortcut: $DESKTOP\${BrandFullName}.lnk"
   ${EndIf}
 
   !insertmacro MUI_STARTMENU_WRITE_END
-
-  ; Refresh desktop icons
-  System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
-SectionEnd
-
-Section /o "Developer Tools" Section2
-  Call installInspector
 SectionEnd
 
-################################################################################
-# Helper Functions
-
-Function installInspector
+Section /o "Developer Tools" DOMI_IDX
   ${If} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
-    SetDetailsPrint textonly
+    SetDetailsPrint both
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\inspector@mozilla.org"
     ClearErrors
     ${LogHeader} "Installing Developer Tools"
     StrCpy $R0 "$EXEDIR\optional\extensions\inspector@mozilla.org"
     StrCpy $R1 "$INSTDIR\extensions\inspector@mozilla.org"
     Call DoCopyFiles
   ${EndIf}
-FunctionEnd
+SectionEnd
+
+; Cleanup operations to perform at the end of the installation.
+Section "-InstallEndCleanup"
+  SetDetailsPrint both
+  DetailPrint "$(STATUS_CLEANUP)"
+  SetDetailsPrint none
+  ${LogHeader} "Updating Uninstall Log With Previous Uninstall Log"
+
+  ${InstallEndCleanupCommon}
+
+  ; Refresh desktop icons
+  System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
+SectionEnd
+
+################################################################################
+# Helper Functions
 
 ; Copies a file to a temporary backup directory and then checks if it is in use
 ; by attempting to delete the file. If the file is in use an error is displayed
 ; and the user is given the options to either retry or cancel. If cancel is
 ; selected then the files are restored.
 Function CheckInUse
   ${If} ${FileExists} "$INSTDIR\$R1"
     retry:
@@ -548,82 +513,16 @@ Function CheckInUse
       CopyFiles /SILENT "$TmpVal\*" "$INSTDIR\"
       SetOutPath $INSTDIR
       RmDir /r "$TmpVal"
       Quit
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
-; Adds a section divider to the human readable log.
-Function WriteLogSeparator
-  FileWrite $fhInstallLog "$\r$\n-------------------------------------------------------------------------------$\r$\n"
-FunctionEnd
-
-; Check whether to display the current page (e.g. if we aren't performing a
-; custom install don't display the custom pages).
-Function CheckCustom
-  ${If} $InstallType != 4
-    Abort
-  ${EndIf}
-FunctionEnd
-
-Function onInstallDeleteFile
-  ${TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    ${If} ${FileExists} "$INSTDIR$R9"
-      ClearErrors
-      Delete "$INSTDIR$R9"
-      ${If} ${Errors}
-        ${LogMsg} "** ERROR Deleting File: $INSTDIR$R9 **"
-      ${Else}
-        ${LogMsg} "Deleted File: $INSTDIR$R9"
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-; The previous installer removed directories even when they aren't empty so this
-; function does as well.
-Function onInstallRemoveDir
-  ${TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 4
-  ${If} $R1 == "Dir:"
-    StrCpy $R9 "$R9" "" 5
-    StrCpy $R1 "$R9" "" -1
-    ${If} $R1 == "\"
-      StrCpy $R9 "$R9" -1
-    ${EndIf}
-    ${If} ${FileExists} "$INSTDIR$R9"
-      ClearErrors
-      RmDir /r "$INSTDIR$R9"
-      ${If} ${Errors}
-        ${LogMsg} "** ERROR Removing Directory: $INSTDIR$R9 **"
-      ${Else}
-        ${LogMsg} "Removed Directory: $INSTDIR$R9"
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-Function GetDiff
-  ${TrimNewLines} "$9" "$9"
-  ${If} $9 != ""
-    FileWrite $R3 "$9$\r$\n"
-    ${LogMsg} "Added To Uninstall Log: $9"
-  ${EndIf}
-  Push 0
-FunctionEnd
-
 Function DoCopyFiles
   StrLen $R2 $R0
   ${LocateNoDetails} "$R0" "/L=FD" "CopyFile"
 FunctionEnd
 
 Function CopyFile
   StrCpy $R3 $R8 "" $R2
   retry:
@@ -663,17 +562,19 @@ Function CopyFile
         ${LogMsg} "** ERROR Deleting File: $R1$R3\$R7 **"
         StrCpy $0 "$R1$R3\$R7"
         ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
         MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
         Quit
       ${EndIf}
     ${EndIf}
     ClearErrors
+
     CopyFiles /SILENT $R9 "$R1$R3"
+
     ${If} ${Errors}
       ${LogMsg} "** ERROR Installing File: $R1$R3\$R7 **"
       StrCpy $0 "$R1$R3\$R7"
       ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
       MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
       Quit
     ${Else}
       ${LogMsg} "Installed File: $R1$R3\$R7"
@@ -683,95 +584,16 @@ Function CopyFile
     ; uninstall.log so it will be a relative path. This allows the same
     ; helper.exe to be used with zip builds if we supply an uninstall.log.
     ${WordReplace} "$R1$R3\$R7" "$INSTDIR" "" "+" $R3
     ${LogUninstall} "File: $R3"
   ${EndIf}
   Push 0
 FunctionEnd
 
-; Clean up the old log files. We only diff the first two found since it is
-; possible for there to be several MB and comparing that many would take a very
-; long time to diff.
-Function CleanupOldLogs
-  FindFirst $0 $TmpVal "$INSTDIR\uninstall\*wizard*"
-  StrCmp $TmpVal "" done
-  StrCpy $TmpVal "$INSTDIR\uninstall\$TmpVal"
-
-  FindNext $0 $1
-  StrCmp $1 "" cleanup
-  StrCpy $1 "$INSTDIR\uninstall\$1"
-  Push $1
-  Call DiffOldLogFiles
-  FindClose $0
-  ${DeleteFile} "$1"
-
-  cleanup:
-    StrCpy $2 "$INSTDIR\uninstall\cleanup.log"
-    ${DeleteFile} "$2"
-    FileOpen $R2 $2 w
-    Push $TmpVal
-    ${LineFind} "$INSTDIR\uninstall\$TmpVal" "/NUL" "1:-1" "CleanOldLogFilesCallback"
-    ${DeleteFile} "$INSTDIR\uninstall\$TmpVal"
-  done:
-    FindClose $0
-    FileClose $R2
-    FileClose $R3
-FunctionEnd
-
-Function DiffOldLogFiles
-  StrCpy $R1 "$1"
-  GetTempFileName $R2
-  FileOpen $R3 $R2 w
-  ${TextCompareNoDetails} "$R1" "$TmpVal" "SlowDiff" "GetDiff"
-  FileClose $R3
-  ${FileJoin} "$TmpVal" "$R2" "$TmpVal"
-  ${DeleteFile} "$R2"
-FunctionEnd
-
-Function CleanOldLogFilesCallback
-  ${TrimNewLines} "$R9" $R9
-  ${WordReplace} "$R9" "$INSTDIR" "" "+" $R3
-  ${WordFind} "$R9" "	" "E+1}" $R0
-  IfErrors updater 0
-
-  ${WordFind} "$R0" "Installing: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Replacing: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Windows Shortcut: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1.lnk$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Create Folder: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "Dir: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  updater:
-    ${WordFind} "$R9" "installing: " "E+1}" $R0
-    ${Unless} ${Errors}
-      FileWrite $R2 "File: $R0$\r$\n"
-    ${EndUnless}
-
-  done:
-    Push 0
-FunctionEnd
-
 Function LaunchApp
   ${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
   Exec "$INSTDIR\${FileMainEXE}"
 FunctionEnd
 
 ################################################################################
 # Language
 
@@ -796,268 +618,106 @@ FunctionEnd
 
 Function leaveOptions
   ${MUI_INSTALLOPTIONS_READ} $0 "options.ini" "Settings" "State"
   ${If} $0 != 0
     Abort
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 2" "State"
   StrCmp $R0 "1" +1 +2
-  StrCpy $InstallType "1"
+  StrCpy $InstallType ${INSTALLTYPE_BASIC}
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 3" "State"
   StrCmp $R0 "1" +1 +2
-  StrCpy $InstallType "4"
+  StrCpy $InstallType ${INSTALLTYPE_CUSTOM}
 FunctionEnd
 
 Function preComponents
-  Call CheckCustom
+  ${CheckCustomCommon}
   ; If DOMi isn't available skip the components page
   ${Unless} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
     Abort
   ${EndUnless}
   !insertmacro MUI_HEADER_TEXT "$(OPTIONAL_COMPONENTS_TITLE)" "$(OPTIONAL_COMPONENTS_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini"
 FunctionEnd
 
 Function leaveComponents
   ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field 2" "State"
   ; State will be 1 for checked and 0 for unchecked so we can use that to set
   ; the section flags for installation.
-  SectionSetFlags 1 $R0
+  SectionSetFlags ${DOMI_IDX} $R0
 FunctionEnd
 
 Function preDirectory
-  SetShellVarContext all  ; Set SHCTX to HKLM
-  ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
-  ${If} $R9 == "false"
-    SetShellVarContext current  ; Set SHCTX to HKCU
-    ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
-  ${EndIf}
-
-  ${Unless} $R9 == "false"
-    StrCpy $INSTDIR "$R9"
-  ${EndUnless}
-
-  ${If} $InstallType != 4
-    ${CheckDiskSpace} $R9
-    ${If} $R9 != "false"
-      ${CanWriteToInstallDir} $R9
-      ${If} $R9 != "false"
-        Abort
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
+  ${PreDirectoryCommon}
 FunctionEnd
 
 Function leaveDirectory
-  ${CheckDiskSpace} $R9
-  ${If} $R9 == "false"
-    MessageBox MB_OK "$(WARN_DISK_SPACE)"
-    Abort
-  ${EndIf}
-
-  ${CanWriteToInstallDir} $R9
-  ${If} $R9 == "false"
-    MessageBox MB_OK "$(WARN_WRITE_ACCESS)"
-    Abort
-  ${EndIf}
+  ${LeaveDirectoryCommon} "$(WARN_DISK_SPACE)" "$(WARN_WRITE_ACCESS)"
 FunctionEnd
 
 Function preShortcuts
-  Call CheckCustom
+  ${CheckCustomCommon}
   !insertmacro MUI_HEADER_TEXT "$(SHORTCUTS_PAGE_TITLE)" "$(SHORTCUTS_PAGE_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "shortcuts.ini"
 FunctionEnd
 
 Function leaveShortcuts
   ${MUI_INSTALLOPTIONS_READ} $0 "shortcuts.ini" "Settings" "State"
   ${If} $0 != 0
     Abort
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $AddDesktopSC "shortcuts.ini" "Field 2" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddQuickLaunchSC "shortcuts.ini" "Field 4" "State"
 FunctionEnd
 
 Function preStartMenu
-  Call CheckCustom
+  ${CheckCustomCommon}
   ${If} $AddStartMenuSC != 1
     Abort
   ${EndIf}
 FunctionEnd
 
-Function leaveInstFiles
-  FileClose $fhUninstallLog
-  ; Diff and add missing entries from the previous file log if it exists
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.bak"
-    SetDetailsPrint textonly
-    DetailPrint $(STATUS_CLEANUP)
-    SetDetailsPrint none
-    ${LogHeader} "Updating Uninstall Log With Previous Uninstall Log"
-    StrCpy $R0 "$INSTDIR\uninstall\uninstall.log"
-    StrCpy $R1 "$INSTDIR\uninstall\uninstall.bak"
-    GetTempFileName $R2
-    FileOpen $R3 $R2 w
-    ${TextCompareNoDetails} "$R1" "$R0" "SlowDiff" "GetDiff"
-    FileClose $R3
-    ${Unless} ${Errors}
-      ${FileJoin} "$INSTDIR\uninstall\uninstall.log" "$R2" "$INSTDIR\uninstall\uninstall.log"
-    ${EndUnless}
-    ${DeleteFile} "$INSTDIR\uninstall\uninstall.bak"
-    ${DeleteFile} "$R2"
+Function preInstFiles
+  ${If} $InstallType != ${INSTALLTYPE_CUSTOM}
+    ; Set DOMi to be installed
+    SectionSetFlags ${DOMI_IDX} 1
   ${EndIf}
-
-  Call WriteLogSeparator
-  ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
-  FileWrite $fhInstallLog "${BrandFullName} Installation Finished: $2-$1-$0 $4:$5:$6$\r$\n"
-  FileClose $fhInstallLog
 FunctionEnd
 
 ; When we add an optional action to the finish page the cancel button is
 ; enabled. This disables it and leaves the finish button as the only choice.
 Function preFinish
+  ${EndInstallLog} "${BrandFullName}"
   !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
 FunctionEnd
 
 ################################################################################
 # Initialization Functions
 
 Function .onInit
-  ${GetParameters} $R0
-  ${If} $R0 != ""
-    ClearErrors
-    ${GetOptions} "$R0" "-ms" $R1
-    ${If} ${Errors}
-      ; Default install type
-      StrCpy $InstallType "1"
-      ; Support for specifying an installation configuration file.
-      ClearErrors
-      ${GetOptions} "$R0" "/INI=" $R1
-      ${Unless} ${Errors}
-        ; The configuration file must also exist
-        ${If} ${FileExists} "$R1"
-          SetSilent silent
-          ReadINIStr $0 $R1 "Install" "InstallDirectoryName"
-          ${If} $0 != ""
-            StrCpy $INSTDIR "$PROGRAMFILES\$0"
-          ${Else}
-            ReadINIStr $0 $R1 "Install" "InstallDirectoryPath"
-            ${If} $$0 != ""
-              StrCpy $INSTDIR "$0"
-            ${EndIf}
-          ${EndIf}
-
-          ${If} $INSTDIR == ""
-            ; Check if there is an existing uninstall registry entry for this
-            ; version of the application and if present install into that location
-            ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
-            ${If} $0 == ""
-              StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
-            ${Else}
-              GetFullPathName $INSTDIR "$0"
-              ${Unless} ${FileExists} "$INSTDIR"
-                StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
-              ${EndUnless}
-            ${EndIf}
-          ${EndIf}
-
-          ; Quit if we are unable to create the installation directory or we are
-          ; unable to write to a file in the installation directory.
-          ClearErrors
-          ${If} ${FileExists} "$INSTDIR"
-            GetTempFileName $R2 "$INSTDIR"
-            FileOpen $R3 $R2 w
-            FileWrite $R3 "Write Access Test"
-            FileClose $R3
-            Delete $R2
-            ${If} ${Errors}
-              Quit
-            ${EndIf}
-          ${Else}
-            CreateDirectory "$INSTDIR"
-            ${If} ${Errors}
-              Quit
-            ${EndIf}
-          ${EndIf}
+  ${InstallOnInitCommon} "$(WARN_UNSUPPORTED_MSG)"
 
-          ReadINIStr $0 $R1 "Install" "CloseAppNoPrompt"
-          ${If} $0 == "true"
-            ; Try to close the app if the exe is in use.
-            ClearErrors
-            ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
-              ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-            ${EndIf}
-            ${If} ${Errors}
-              ClearErrors
-              ${CloseApp} "false" ""
-              ClearErrors
-              ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-              ; If unsuccessful try one more time and if it still fails Quit
-              ${If} ${Errors}
-                ClearErrors
-                ${CloseApp} "false" ""
-                ClearErrors
-                ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-                ${If} ${Errors}
-                  Quit
-                ${EndIf}
-              ${EndIf}
-            ${EndIf}
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "QuickLaunchShortcut"
-          ${If} $0 == "false"
-            StrCpy $AddQuickLaunchSC "0"
-          ${Else}
-            StrCpy $AddQuickLaunchSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "DesktopShortcut"
-          ${If} $0 == "false"
-            StrCpy $AddDesktopSC "0"
-          ${Else}
-            StrCpy $AddDesktopSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "StartMenuShortcuts"
-          ${If} $0 == "false"
-            StrCpy $AddStartMenuSC "0"
-          ${Else}
-            StrCpy $AddStartMenuSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "StartMenuDirectoryName"
-          ${If} $0 != ""
-            StrCpy $StartMenuDir "$0"
-          ${EndIf}
-        ${EndIf}
-      ${EndUnless}
-    ${Else}
-      ; Support for the deprecated -ms command line argument. The new command
-      ; line arguments are not supported when -ms is used.
-      SetSilent silent
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-
-  StrCpy $LANGUAGE 0
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "options.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "components.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "shortcuts.ini"
   !insertmacro createBasicCustomOptionsINI
   !insertmacro createComponentsINI
   !insertmacro createShortcutsINI
 
+  StrCpy $LANGUAGE 0
+
   ; There must always be nonlocalized and localized directories.
-  ${GetSize} "$EXEDIR\nonlocalized\" "/S=0K" $1 $8 $9
-  ${GetSize} "$EXEDIR\localized\" "/S=0K" $2 $8 $9
-  IntOp $0 $1 + $2
-  SectionSetSize 0 $0
+  ${GetSize} "$EXEDIR\nonlocalized\" "/S=0K" $R5 $R7 $R8
+  ${GetSize} "$EXEDIR\localized\" "/S=0K" $R6 $R7 $R8
+  IntOp $R8 $R5 + $R6
+  SectionSetSize ${APP_IDX} $R8
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
     ; Set the section size for DOMi.
     ${GetSize} "$EXEDIR\optional\extensions\inspector@mozilla.org" "/S=0K" $0 $8 $9
-    SectionSetSize 1 $0
+    SectionSetSize ${DOMI_IDX} $0
   ${Else}
     ; Hide DOMi in the components page if it isn't available.
-    SectionSetText 1 ""
+    SectionSetText ${DOMI_IDX} ""
   ${EndIf}
 FunctionEnd
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -34,23 +34,24 @@
 #
 # ***** END LICENSE BLOCK *****
 
 !macro PostUpdate
   SetShellVarContext all
   ${SetStartMenuInternet}
 
   ; Remove registry entries for non-existent apps and for apps that point to our
-  ; install location in the Software\Mozilla key.
+  ; install location in the Software\Mozilla key and uninstall registry entries
+  ; that point to our install location for both HKCU and HKLM.
   SetShellVarContext current  ; Set SHCTX to HKCU
   ${RegCleanMain} "Software\Mozilla"
+  ${RegCleanUninstall}
+
   SetShellVarContext all  ; Set SHCTX to HKLM
   ${RegCleanMain} "Software\Mozilla"
-
-  ; Remove uninstall entries that point to our install location
   ${RegCleanUninstall}
 
   ; Add Software\Mozilla\ registry entries
   ${SetAppKeys}
 
   ${SetUninstallKeys}
 
   ${FixClassKeys}
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -29,17 +29,17 @@
 # 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 *****
 
-# Also requires:
+# Required Plugins:
 # ShellLink plugin http://nsis.sourceforge.net/ShellLink_plug-in
 
 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
 !verbose 3
 
 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
 ; uncompressed and use 7-Zip to create a SFX archive of it
 SetDatablockOptimize on
@@ -57,54 +57,68 @@ Var TmpVal
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
 !include TextFunc.nsh
 !include WinMessages.nsh
 !include WordFunc.nsh
 !include MUI.nsh
 
-!insertmacro GetOptions
-!insertmacro GetParameters
+; WinVer.nsh was added in the same release that RequestExecutionLevel so check
+; if ___WINVER__NSH___ is defined to determine if RequestExecutionLevel is
+; available.
+!include /NONFATAL WinVer.nsh
+!ifdef ___WINVER__NSH___
+  RequestExecutionLevel admin
+!else
+  !warning "Uninstaller will be created without Vista compatibility.$\n            \
+            Upgrade your NSIS installation to at least version 2.22 to resolve."
+!endif
+
 !insertmacro StrFilter
 !insertmacro WordFind
 !insertmacro WordReplace
 
+!insertmacro un.GetParent
 !insertmacro un.LineFind
 !insertmacro un.TrimNewLines
 
 ; The following includes are custom.
 !include branding.nsi
 !include defines.nsi
 !include common.nsh
 !include locales.nsi
 !include version.nsh
 
 ; This is named BrandShortName helper because we use this for software update
 ; post update cleanup.
 VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
 
-!insertmacro GetLongPath
 !insertmacro AddHandlerValues
 !insertmacro CleanVirtualStore
+!insertmacro GetLongPath
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
-!insertmacro UpdateUninstallLog
+!insertmacro WriteRegDWORD2
 !insertmacro WriteRegStr2
-!insertmacro WriteRegDWORD2
 
+!insertmacro un.CleanVirtualStore
+!insertmacro un.CloseApp
 !insertmacro un.GetLongPath
+!insertmacro un.GetSecondInstallPath
+!insertmacro un.ParseUninstallLog
 !insertmacro un.RegCleanMain
 !insertmacro un.RegCleanUninstall
-!insertmacro un.CleanVirtualStore
-!insertmacro un.CloseApp
-!insertmacro un.GetSecondInstallPath
+!insertmacro un.RemoveQuotesFromPath
 
 !include shared.nsh
 
+; Helper macros for ui callbacks. Insert these after shared.nsh
+!insertmacro UninstallOnInitCommon
+
 Name "${BrandFullName}"
 OutFile "helper.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}"
 ShowUnInstDetails nevershow
 
 ################################################################################
 # Modern User Interface - MUI
@@ -159,41 +173,39 @@ SectionEnd
 
 ################################################################################
 # Uninstall Sections
 
 Section "Uninstall"
   SetDetailsPrint textonly
   DetailPrint $(STATUS_UNINSTALL_MAIN)
   SetDetailsPrint none
+
   ; Remove registry entries for non-existent apps and for apps that point to our
-  ; install location in the Software\Mozilla key.
+  ; install location in the Software\Mozilla key and uninstall registry entries
+  ; that point to our install location for both HKCU and HKLM.
   SetShellVarContext current  ; Sets SHCTX to HKCU
   ${un.RegCleanMain} "Software\Mozilla"
+  ${un.RegCleanUninstall}
+
   SetShellVarContext all  ; Sets SHCTX to HKLM
   ${un.RegCleanMain} "Software\Mozilla"
-
-  ; Remove uninstall entries that point to our install location
   ${un.RegCleanUninstall}
 
   SetShellVarContext all  ; Set SHCTX to HKLM
   ${un.GetSecondInstallPath} "Software\Mozilla" $R9
   ${If} $R9 == "false"
     SetShellVarContext current  ; Set SHCTX to HKCU
     ${un.GetSecondInstallPath} "Software\Mozilla" $R9
   ${EndIf}
 
   StrCpy $0 "Software\Clients\StartMenuInternet\${FileMainEXE}\shell\open\command"
-  ReadRegStr $1 HKLM "$0" ""
-  Push $1
-  ${GetPathFromRegStr}
-  Pop $R0
-  Push $R0
-  ${GetParentDir}
-  Pop $R1
+  ReadRegStr $R1 HKLM "$0" ""
+  ${un.RemoveQuotesFromPath} "$R1" $R1
+  ${un.GetParent} "$R1" $R1
 
   ; Only remove the StartMenuInternet key if it refers to this install location.
   ; The StartMenuInternet registry key is independent of the default browser
   ; settings. The XPInstall base un-installer always removes this key if it is
   ; uninstalling the default browser and it will always replace the keys when
   ; installing even if there is another install of Firefox that is set as the
   ; default browser. Now the key is always updated on install but it is only
   ; removed if it refers to this install location.
@@ -210,162 +222,55 @@ Section "Uninstall"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
     StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\${FileMainEXE}"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
     StrCpy $0 "MIME\Database\Content Type\application/x-xpinstall;app=firefox"
     DeleteRegKey HKCR "$0"
   ${Else}
-    ReadRegStr $1 HKLM "$0" ""
-    Push $1
-    ${GetPathFromRegStr}
-    Pop $R0
-    Push $R0
-    ${GetParentDir}
-    Pop $R1
+    ReadRegStr $R1 HKLM "$0" ""
+    ${un.RemoveQuotesFromPath} "$R1" $R1
+    ${un.GetParent} "$R1" $R1
     ${If} "$INSTDIR" == "$R1"
       WriteRegStr HKLM "$0" "" "$R9"
-      Push $R9
-      ${GetParentDir}
-      Pop $R1
+      ${un.GetParent} "$R9" $R1
       WriteRegStr HKLM "$0" "Path" "$R1"
     ${EndIf}
   ${EndIf}
 
-  ; Remove files. If we don't have a log file skip
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
-    ; Copy the uninstall log file to a temporary file
-    GetTempFileName $TmpVal
-    CopyFiles /SILENT /FILESONLY "$INSTDIR\uninstall\uninstall.log" "$TmpVal"
-
-    ; Unregister DLL's
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.UnRegDLLsCallback"
-
-    ; Delete files
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveFilesCallback"
+  ; Remove directories and files we always control
+  RmDir /r "$INSTDIR\updates"
+  RmDir /r "$INSTDIR\defaults\shortcuts"
+  RmDir /r "$INSTDIR\distribution"
+  Delete "$INSTDIR\removed-files"
 
-    ; Remove directories we always control
-    RmDir /r "$INSTDIR\uninstall"
-    RmDir /r "$INSTDIR\updates"
-    RmDir /r "$INSTDIR\defaults\shortcuts"
+  ; Parse the uninstall log to unregister dll's and remove all installed
+  ; files / directories this install is responsible for.
+  ${un.ParseUninstallLog}
 
-    ; Remove empty directories
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveDirsCallback"
+  ; Remove the uninstall directory that we control
+  RmDir /r "$INSTDIR\uninstall"
 
-    ; Delete the temporary uninstall log file
-    ${DeleteFile} "$TmpVal"
-
-    ; Remove the installation directory if it is empty
-    ${RemoveDir} "$INSTDIR"
-  ${EndIf}
+  ; Remove the installation directory if it is empty
+  ${RemoveDir} "$INSTDIR"
 
   ; Remove files that may be left behind by the application in the
   ; VirtualStore directory.
   ${un.CleanVirtualStore}
 
   ; Refresh desktop icons otherwise the start menu internet item won't be
-  ; removed and other ugly things will happen like recreation of the registry
-  ; key by the OS under some conditions.
+  ; removed and other ugly things will happen like recreation of the app's
+  ; clients registry key by the OS under some conditions.
   System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
 SectionEnd
 
 ################################################################################
 # Helper Functions
 
-Function un.RemoveFilesCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    StrCpy $R0 "$R9" 1
-    ; If the path is relative prepend the install directory
-    ${If} $R0 == "\"
-      StrCpy $R0 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R0 "$R9"
-    ${EndIf}
-    ${If} ${FileExists} "$R0"
-      ${DeleteFile} "$R0"
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-; Using locate will leave file handles open to some of the directories which
-; will prevent the deletion of these directories. This parses the uninstall.log
-; and uses the file entries to find / remove empty directories.
-Function un.RemoveDirsCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    StrCpy $R1 "$R9" 1
-    ${If} $R1 == "\"
-      StrCpy $R2 "$INSTDIR"
-      StrCpy $R1 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R2 ""
-      StrCpy $R1 "$R9"
-    ${EndIf}
-    loop:
-      Push $R1
-      ${GetParentDir}
-      Pop $R0
-      GetFullPathName $R1 "$R0"
-      ; We only try to remove empty directories but the Desktop, StartMenu, and
-      ; QuickLaunch directories can be empty so guard against removing them.
-      ${If} "$R2" != "$INSTDIR"
-        SetShellVarContext all
-        ${If} $R1 == "$DESKTOP"
-        ${OrIf} $R1 == "$STARTMENU"
-          GoTo end
-        ${EndIf}
-        SetShellVarContext current
-        ${If} $R1 == "$QUICKLAUNCH"
-        ${OrIf} $R1 == "$DESKTOP"
-        ${OrIf} $R1 == "$STARTMENU"
-          GoTo end
-        ${EndIf}
-      ${ElseIf} "$R1" == "$INSTDIR"
-        GoTo end
-      ${EndIf}
-      ${If} ${FileExists} "$R1"
-        RmDir "$R1"
-      ${EndIf}
-      ${If} ${Errors}
-      ${OrIf} "$R2" != "$INSTDIR"
-        GoTo end
-      ${EndIf}
-      GoTo loop
-  ${EndIf}
-
-  end:
-    ClearErrors
-    Push 0
-FunctionEnd
-
-Function un.UnRegDLLsCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 7
-  ${If} $R1 == "DLLReg:"
-    StrCpy $R9 "$R9" "" 8
-    StrCpy $R1 "$R9" 1
-    ${If} $R1 == "\"
-      StrCpy $R1 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R1 "$R9"
-    ${EndIf}
-    UnRegDLL $R1
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
 ; Setup the survey controls, functions, etc. except when the application has
 ; defined NO_UNINSTALL_SURVEY
 !ifndef NO_UNINSTALL_SURVEY
 Function un.Survey
   Exec "$\"$TmpVal$\" $\"${SurveyURL}$\""
 FunctionEnd
 !endif
 
@@ -436,95 +341,20 @@ Function un.preFinish
         !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
       ${EndIf}
     ${EndIf}
   !endif
 FunctionEnd
 
 ################################################################################
 # Initialization Functions
-
 Function .onInit
-  GetFullPathName $INSTDIR "$EXEDIR\.."
-  ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
-    Abort
-  ${EndUnless}
-  ${GetParameters} $R0
-
-  ${Switch} $R0
-    ${Case} "/HideShortcuts"
-      ${HideShortcuts}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/ShowShortcuts"
-      ${ShowShortcuts}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/SetAsDefaultAppUser"
-      ${SetAsDefaultAppUser}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/SetAsDefaultAppGlobal"
-      ${SetAsDefaultAppGlobal}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Default}
-      ClearErrors
-      ${Unless} "$R0" == ""
-        ${WordReplace} "$R0" "$\"" "" "+" $R0
-        ClearErrors
-        ${GetOptions} "$R0" "/PostUpdate" $R2
-        ${Unless} ${Errors}
-          ${PostUpdate}
-          ClearErrors
-          ${GetOptions} "$R0" "/UninstallLog=" $R2
-          ${Unless} ${Errors}
-            ${Unless} "$R2" == ""
-              GetFullPathName $R3 "$R2"
-              ${If} ${FileExists} "$R3"
-                Delete "$INSTDIR\uninstall\*wizard*"
-                Delete "$INSTDIR\uninstall\uninstall.log"
-                CopyFiles /SILENT /FILESONLY "$R3" "$INSTDIR\uninstall\"
-                Push $R3
-                ${GetParentDir}
-                Pop $R4
-                Delete "$R3"
-                RmDir "$R4"
-              ${EndIf}
-            ${EndUnless}
-          ${Else}
-            ${UpdateUninstallLog}
-          ${EndUnless}
-          StrCpy $R1 "true"
-        ${EndUnless}
-      ${EndUnless}
-      ${Break}
-  ${EndSwitch}
-
-  ${If} $R1 == "true"
-    System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
-    Quit
-  ${EndIf}
-
-  ; If we made it this far then this installer is being used as an uninstaller.
-  WriteUninstaller "$EXEDIR\uninstaller.exe"
-
-  ${If} $R0 == "/S"
-    StrCpy $TmpVal "$\"$EXEDIR\uninstaller.exe$\" /S"
-  ${Else}
-    StrCpy $TmpVal "$\"$EXEDIR\uninstaller.exe$\""
-  ${EndIf}
-
-  ; When the uninstaller is launched it copies itself to the temp directory so
-  ; it won't be in use so it can delete itself.
-  ExecWait $TmpVal
-  ${DeleteFile} "$EXEDIR\uninstaller.exe"
-  SetErrorLevel 0
-  Quit
+  ${UninstallOnInitCommon}
 FunctionEnd
 
 Function un.onInit
   GetFullPathName $INSTDIR "$INSTDIR\.."
+  ${un.GetLongPath} "$INSTDIR" $INSTDIR
   ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
     Abort
   ${EndUnless}
   StrCpy $LANGUAGE 0
 FunctionEnd
--- a/browser/installer/windows/packages-static
+++ b/browser/installer/windows/packages-static
@@ -187,16 +187,17 @@ bin\components\xpcom_ds.xpt
 bin\components\xpcom_io.xpt
 bin\components\xpcom_thread.xpt
 bin\components\xpcom_xpti.xpt
 bin\components\xpconnect.xpt
 bin\components\xpinstall.xpt
 bin\components\xulapp.xpt
 bin\components\xuldoc.xpt
 bin\components\xultmpl.xpt
+bin\components\zipwriter.xpt
 ; JavaScript components
 bin\components\FeedProcessor.js
 bin\components\FeedConverter.js
 bin\components\FeedWriter.js
 bin\components\fuelApplication.js
 bin\components\WebContentConverter.js
 bin\components\nsBrowserContentHandler.js
 bin\components\nsBrowserGlue.js
--- a/browser/locales/en-US/chrome/browser/places/editBookmarkOverlay.dtd
+++ b/browser/locales/en-US/chrome/browser/places/editBookmarkOverlay.dtd
@@ -2,11 +2,11 @@
 <!ENTITY editBookmarkOverlay.location.label                  "Location:">
 <!ENTITY editBookmarkOverlay.liveTitlesSeparator.label       "Live Titles">
 <!ENTITY editBookmarkOverlay.folder.label                    "Folder:">
 <!ENTITY editBookmarkOverlay.allBookmarksFolderItem.label    "All Bookmarks">
 <!ENTITY editBookmarkOverlay.bookmarksMenuFolderItem.label   "Bookmarks Menu">
 <!ENTITY editBookmarkOverlay.toolbarFolderItem.label         "Bookmarks Toolbar">
 <!ENTITY editBookmarkOverlay.foldersExpanderDown.tooltip     "Show all the bookmarks folders">
 <!ENTITY editBookmarkOverlay.expanderUp.tooltip              "Hide">
-<!ENTITY editBookmarkOverlay.tags.label                      "Tags">
+<!ENTITY editBookmarkOverlay.tags.label                      "Tags:">
 <!ENTITY editBookmarkOverlay.description.label               "Description:">
 <!ENTITY editBookmarkOverlay.tagsExpanderDown.tooltip        "Show all tags">
--- a/browser/locales/en-US/chrome/browser/places/places.dtd
+++ b/browser/locales/en-US/chrome/browser/places/places.dtd
@@ -1,316 +1,194 @@
-<!ENTITY places.bm.title
-  "Bookmarks Manager">
-<!ENTITY file.label
-  "File">
-<!ENTITY file.accesskey
-  "F">
-<!ENTITY file.close.label
-  "Close">
-<!ENTITY file.close.accesskey
-  "C">
-<!ENTITY cmd.close.key
-  "w">
-<!ENTITY edit.label
-  "Edit">
-<!ENTITY edit.accesskey
-  "E">
-<!ENTITY view.label
-  "View">
-<!ENTITY view.accesskey
-  "V">
-<!ENTITY view.toolbar.label
-  "Toolbar">
-<!ENTITY view.toolbar.accesskey
-  "o">
-<!ENTITY view.columns.label
-  "Show Columns">
-<!ENTITY view.columns.accesskey
-  "S">
-<!ENTITY view.unsorted.label
-  "Unsorted">
-<!ENTITY view.unsorted.accesskey
-  "U">
-<!ENTITY view.sortAscending.label
-  "A > Z Sort Order">
-<!ENTITY view.sortAscending.accesskey
-  "A">
-<!ENTITY view.sortDescending.label
-  "Z > A Sort Order">
-<!ENTITY view.sortDescending.accesskey
-  "Z">
-<!ENTITY help.usingBookmarks.label
-  "Using Bookmarks">
-<!ENTITY help.usingBookmarks.accesskey
-  "B">
-<!ENTITY help.usingHistory.label
-  "Using History">
-<!ENTITY help.usingHistory.accesskey
-  "i">
-<!ENTITY help.advancedTips.label
-  "Advanced Tips &amp; Tricks">
-<!ENTITY help.advancedTips.accesskey
-  "T">
+<!ENTITY places.organizer.title  "Places Organizer">
+<!ENTITY organize.label          "Organize">
+
+<!ENTITY file.accesskey                 "F">
+<!ENTITY file.close.label               "Close">
+<!ENTITY file.close.accesskey           "C">
+<!ENTITY cmd.close.key                  "w">
+<!ENTITY edit.label                     "Edit">
+<!ENTITY edit.accesskey                 "E">
+<!ENTITY views.label                    "Views">
+<!ENTITY view.accesskey                 "V">
+<!ENTITY view.toolbar.label             "Toolbar">
+<!ENTITY view.toolbar.accesskey         "o">
+<!ENTITY view.columns.label             "Show Columns">
+<!ENTITY view.columns.accesskey         "S">
+<!ENTITY view.sort.label                "Sort">
+<!ENTITY view.sort.accesskey            "s">
+<!ENTITY view.unsorted.label            "Unsorted">
+<!ENTITY view.unsorted.accesskey        "U">
+<!ENTITY view.sortAscending.label       "A > Z Sort Order">
+<!ENTITY view.sortAscending.accesskey   "A">
+<!ENTITY view.sortDescending.label      "Z > A Sort Order">
+<!ENTITY view.sortDescending.accesskey  "Z">
+<!ENTITY help.usingBookmarks.label      "Using Bookmarks">
+<!ENTITY help.usingBookmarks.accesskey  "B">
+<!ENTITY help.usingHistory.label        "Using History">
+<!ENTITY help.usingHistory.accesskey    "i">
+<!ENTITY help.advancedTips.label        "Advanced Tips &amp; Tricks">
+<!ENTITY help.advancedTips.accesskey    "T">
+
+<!ENTITY cmd.findInBookmarks.label      "Find in Bookmarks...">
+<!ENTITY cmd.findInBookmarks.accesskey  "F">
+<!ENTITY cmd.findCurrent.label          "Find in Current Collection...">
+<!ENTITY cmd.findCurrent.accesskey      "i">
+
+<!ENTITY cmd.export.label      "Export...">
+<!ENTITY cmd.export.accesskey  "E">
+<!ENTITY cmd.import.label      "Import...">
+<!ENTITY cmd.import.accesskey  "I">
+
+<!ENTITY cmd.backup.label               "Backup...">
+<!ENTITY cmd.backup.accesskey           "B">
+<!ENTITY cmd.restore.label              "Restore...">
+<!ENTITY cmd.restore.accesskey          "R">
+<!ENTITY cmd.restoreFromFile.label      "Choose File...">
+<!ENTITY cmd.restoreFromFile.accesskey  "C">
+
+<!ENTITY cmd.select_all.label "Select All">
+<!ENTITY cmd.select_all.accesskey "A">
+<!ENTITY cmd.select_all.key "a">
+
+<!ENTITY cmd.edit_cut.label         "Cut">
+<!ENTITY cmd.edit_cut.accesskey     "t">
+<!ENTITY cmd.edit_cut.key           "x">
+<!ENTITY cmd.edit_copy.label        "Copy">
+<!ENTITY cmd.edit_copy.accesskey    "C">
+<!ENTITY cmd.edit_copy.key          "c">
+<!ENTITY cmd.edit_paste.label       "Paste">
+<!ENTITY cmd.edit_paste.accesskey   "P">
+<!ENTITY cmd.edit_paste.key         "v">
+<!ENTITY cmd.edit_delete.label      "Delete">
+<!ENTITY cmd.edit_delete.accesskey  "D">
+<!ENTITY cmd.edit_undo.label        "Undo">
+<!ENTITY cmd.edit_undo.accesskey    "U">
+<!ENTITY cmd.edit_undo.key          "z">
+<!ENTITY cmd.edit_redo.label        "Redo">
+<!ENTITY cmd.edit_redo.accesskey    "R">
+<!ENTITY cmd.edit_redo.key          "y">
+
+<!ENTITY cmd.open.label                  "Open">
+<!ENTITY cmd.open.accesskey              "O">
+<!ENTITY cmd.open_window.label           "Open in a New Window">
+<!ENTITY cmd.open_window.accesskey       "N">
+<!ENTITY cmd.open_tab.label              "Open in a New Tab">
+<!ENTITY cmd.open_tab.accesskey          "w">
+<!ENTITY cmd.open_all_in_tabs.label      "Open All in Tabs">
+<!ENTITY cmd.open_all_in_tabs.accesskey  "O">
+
+<!ENTITY cmd.properties.label      "Properties">
+<!ENTITY cmd.properties.accesskey  "i">
+
+<!ENTITY cmd.show_info.key  "i">
+
+<!ENTITY cmd.rename.label      "Rename">
+<!ENTITY cmd.rename.accesskey  "R">
+
+<!ENTITY cmd.sortby_name.label              "Sort By Name">
+<!ENTITY cmd.sortby_name.accesskey          "S">
+<!ENTITY cmd.context_sortby_name.accesskey  "r">
 
-<!ENTITY cmd.findInBookmarks.label 
-  "Find in Bookmarks...">
-<!ENTITY cmd.findInBookmarks.accesskey
-  "F">
-<!ENTITY cmd.findCurrent.label
-  "Find in Current Collection...">
-<!ENTITY cmd.findCurrent.accesskey
-  "i">
-<!ENTITY cmd.export.label
-  "Export...">
-<!ENTITY cmd.export.accesskey
-  "E">
-<!ENTITY cmd.import.label
-  "Import...">
-<!ENTITY cmd.import.accesskey
-  "I">
-<!ENTITY cmd.backup.label
-  "Backup...">
-<!ENTITY cmd.backup.accesskey
-  "B">
-<!ENTITY cmd.restore.label
-  "Restore...">
-<!ENTITY cmd.restore.accesskey
-  "R">
-<!ENTITY cmd.restoreFromFile.label
-  "Choose File...">
-<!ENTITY cmd.restoreFromFile.accesskey
-  "C">
-<!ENTITY cmd.select_all.label
-  "Select All">
-<!ENTITY cmd.select_all.accesskey
-  "A">
-<!ENTITY cmd.select_all.key
-  "a">
-<!ENTITY cmd.edit_cut.label
-  "Cut">
-<!ENTITY cmd.edit_cut.accesskey
-  "t">
-<!ENTITY cmd.edit_cut.key
-  "x">
-<!ENTITY cmd.edit_copy.label
-  "Copy">
-<!ENTITY cmd.edit_copy.accesskey
-  "C">
-<!ENTITY cmd.edit_copy.key
-  "c">
-<!ENTITY cmd.edit_paste.label
-  "Paste">
-<!ENTITY cmd.edit_paste.accesskey
-  "P">
-<!ENTITY cmd.edit_paste.key
-  "v">
-<!ENTITY cmd.edit_delete.label
-  "Delete">
-<!ENTITY cmd.edit_delete.accesskey
-  "D">
-<!ENTITY cmd.edit_undo.label
-  "Undo">
-<!ENTITY cmd.edit_undo.accesskey
-  "U">
-<!ENTITY cmd.edit_undo.key
-  "z">
-<!ENTITY cmd.edit_redo.label
-  "Redo">
-<!ENTITY cmd.edit_redo.accesskey
-  "R">
-<!ENTITY cmd.edit_redo.key
-  "y">
-<!ENTITY cmd.open.label
-  "Open">
-<!ENTITY cmd.open.accesskey
-  "O">
-<!ENTITY cmd.open_window.label
-  "Open in a New Window">
-<!ENTITY cmd.open_window.accesskey
-  "N">
-<!ENTITY cmd.open_tab.label
-  "Open in a New Tab">
-<!ENTITY cmd.open_tab.accesskey
-  "w">
-<!ENTITY cmd.open_all_in_tabs.label
-  "Open All in Tabs">
-<!ENTITY cmd.open_all_in_tabs.accesskey
-  "O">
-<!ENTITY cmd.properties.label
-  "Properties">
-<!ENTITY cmd.properties.accesskey
-  "i">
-<!ENTITY cmd.show_info.key
-  "i">
-<!ENTITY cmd.rename.label
-  "Rename">
-<!ENTITY cmd.rename.accesskey
-  "R">
-<!ENTITY cmd.sortby_name.label
-  "Sort By Name">
-<!ENTITY cmd.sortby_name.accesskey
-  "S">
-<!ENTITY cmd.context_sortby_name.accesskey
-  "r">
-<!ENTITY cmd.new_bookmark.label
-  "New Bookmark...">
-<!ENTITY cmd.new_bookmark.accesskey
-  "B">
-<!ENTITY cmd.new_livemark.label
-  "New Live Bookmark...">
-<!ENTITY cmd.new_livemark.accesskey
-  "L">
-<!ENTITY cmd.new_folder.label
-  "New Folder...">
-<!ENTITY cmd.new_folder.accesskey
-  "o">
-<!ENTITY cmd.context_new_folder.accesskey
-  "F">
-<!ENTITY cmd.new_separator.label
-  "New Separator">
-<!ENTITY cmd.new_separator.accesskey
-  "S">
-<!ENTITY cmd.reloadLivebookmark.label
-  "Reload Live Bookmark">
-<!ENTITY cmd.reloadLivebookmark.accesskey
-  "R">
-<!ENTITY cmd.reloadMicrosummary.label
-  "Reload Live Title">
-<!ENTITY cmd.reloadMicrosummary.accesskey
-  "R">
-<!ENTITY cmd.groupby_site.label
-  "Group by Site">
-<!ENTITY cmd.groupby_site.accesskey
-  "S">
-<!ENTITY cmd.groupby_page.label
-  "Group by Page">
-<!ENTITY cmd.groupby_page.accesskey
-  "P">
-<!ENTITY cmd.groupby_feed.label
-  "Group by Subscription">
-<!ENTITY cmd.groupby_feed.accesskey
-  "S">
-<!ENTITY cmd.groupby_post.label
-  "Group by Post">
-<!ENTITY cmd.groupby_post.accesskey
-  "P">
+<!ENTITY cmd.new_bookmark.label            "New Bookmark...">
+<!ENTITY cmd.new_bookmark.accesskey        "B">
+<!ENTITY cmd.new_livemark.label            "New Live Bookmark...">
+<!ENTITY cmd.new_livemark.accesskey        "L">
+<!ENTITY cmd.new_folder.label              "New Folder...">
+<!ENTITY cmd.new_folder.accesskey          "o">
+<!ENTITY cmd.context_new_folder.accesskey  "F">
+<!ENTITY cmd.new_separator.label           "New Separator">
+<!ENTITY cmd.new_separator.accesskey       "S">
+
+<!ENTITY cmd.reloadLivebookmark.label      "Reload Live Bookmark">
+<!ENTITY cmd.reloadLivebookmark.accesskey  "R">
+<!ENTITY cmd.reloadMicrosummary.label      "Reload Live Title">
+<!ENTITY cmd.reloadMicrosummary.accesskey  "R">
+
+<!ENTITY cmd.groupby_site.label      "Group by Site">
+<!ENTITY cmd.groupby_site.accesskey  "S">
+<!ENTITY cmd.groupby_page.label      "Group by Page">
+<!ENTITY cmd.groupby_page.accesskey  "P">
+<!ENTITY cmd.groupby_feed.label      "Group by Subscription">
+<!ENTITY cmd.groupby_feed.accesskey  "S">
+<!ENTITY cmd.groupby_post.label      "Group by Post">
+<!ENTITY cmd.groupby_post.accesskey  "P">
+
+<!ENTITY cmd.moveBookmarks.label                  "Move...">
+<!ENTITY cmd.moveBookmarks.accesskey              "M">
+<!ENTITY cmd.moveBookmarks.menuLabel              "Move Bookmark(s)...">
+<!ENTITY cmd.moveBookmarks.menuAccesskey          "M">
+<!ENTITY cmd.personalToolbarFolder.menuLabel      "Set as Bookmarks Toolbar Folder">
+<!ENTITY cmd.personalToolbarFolder.menuAccesskey  "b">
+
+<!ENTITY col.name.label          "Name">
+<!ENTITY col.tags.label          "Tags">
+<!ENTITY col.url.label           "Location">
+<!ENTITY col.lastvisit.label     "Visit Date">
+<!ENTITY col.visitcount.label    "Visit Count">
+<!ENTITY col.keyword.label       "Keyword">
+<!ENTITY col.description.label   "Description">
+<!ENTITY col.dateadded.label     "Added">
+<!ENTITY col.lastmodified.label  "Last Modified">
 
-<!ENTITY cmd.moveBookmarks.label
-         "Move...">
-<!ENTITY cmd.moveBookmarks.accesskey
-         "M">
-<!ENTITY cmd.moveBookmarks.menuLabel
-         "Move Bookmark(s)...">
-<!ENTITY cmd.moveBookmarks.menuAccesskey
-         "M">
-<!ENTITY cmd.personalToolbarFolder.menuLabel
-         "Set as Bookmarks Toolbar Folder">
-<!ENTITY cmd.personalToolbarFolder.menuAccesskey
-         "b">
-
-<!ENTITY col.name.label
-  "Name">
-<!ENTITY col.tags.label
-  "Tags">
-<!ENTITY col.url.label
-  "Location">
-<!ENTITY col.lastvisit.label
-  "Visit Date">
-<!ENTITY col.visitcount.label
-  "Visit Count">
-<!ENTITY col.keyword.label
-  "Keyword">
-<!ENTITY col.description.label
-  "Description">
-<!ENTITY col.dateadded.label
-  "Added">
-<!ENTITY col.lastmodified.label
-  "Last Modified">
+<!ENTITY search.label                              "Search:">
+<!ENTITY search.accesskey                          "S">
+<!ENTITY search.collection.label                   "Current Collection Only">
+<!ENTITY search.collection.accesskey               "C">
+<!ENTITY search.allBookmarks.label                 "All Bookmarks">
+<!ENTITY search.allBookmarks.accesskey             "A">
+<!ENTITY saveSearch.label                          "Save">
+<!ENTITY saveSearch.accesskey                      "S">
+<!ENTITY moreCriteria.label                        "+">
+<!ENTITY advancedSearch.onlybookmarked.label       "Search Bookmarks only">
+<!ENTITY advancedSearch.match.label                "Match ">
+<!ENTITY advancedSearch.all.label                  "all">
+<!ENTITY advancedSearch.any.label                  "any">
+<!ENTITY advancedSearch.rules.label                " of the following rules:">
+<!ENTITY advancedSearch.subj_keyword.label         "Containing the text">
+<!ENTITY advancedSearch.subj_visited.label         "Visited">
+<!ENTITY advancedSearch.subj_location.label        "Location">
+<!ENTITY advancedSearch.location_startswith.label  "starts with">
+<!ENTITY advancedSearch.location_is.label          "is">
+<!ENTITY advancedSearch.location_onsite.label      "is on site">
+<!ENTITY advancedSearch.time_is.label              "on">
+<!ENTITY advancedSearch.time_before.label          "before">
+<!ENTITY advancedSearch.time_after.label           "after">
+<!ENTITY advancedSearch.time_inlast.label          "in the last">
+<!ENTITY advancedSearch.last_days.label            "days">
+<!ENTITY advancedSearch.last_weeks.label           "weeks">
+<!ENTITY advancedSearch.last_months.label          "months">
+<!ENTITY advancedSearch.plus.label                 "+">
+<!ENTITY advancedSearch.minus.label                "-">
+<!ENTITY advancedSearch.groupby.label              "Group by: ">
+<!ENTITY advancedSearch.groupby_host.label         "host">
+<!ENTITY advancedSearch.groupby_domain.label       "domain">
+<!ENTITY advancedSearch.groupby_folder.label       "folder">
+<!ENTITY advancedSearch.sortby.label               "Sort by: ">
+<!ENTITY advancedSearch.sortby_title.label         "title">
+<!ENTITY advancedSearch.sortby_date.label          "date">
+<!ENTITY advancedSearch.sortby_visit.label         "visit count">
+<!ENTITY advancedSearch.sortby_url.label           "url">
+<!ENTITY advancedSearch.sortby_asc.label           "ascending">
+<!ENTITY advancedSearch.sortby_desc.label          "descending">
+<!ENTITY advancedSearch.max.label                  "Maximum results: ">
 
-<!ENTITY search.label
-  "Search:">
-<!ENTITY search.accesskey
-  "S">
-<!ENTITY search.collection.label
-  "Current Collection Only">
-<!ENTITY search.collection.accesskey
-  "C">
-<!ENTITY search.allBookmarks.label
-  "All Bookmarks">
-<!ENTITY search.allBookmarks.accesskey
-  "A">
-<!ENTITY saveSearch.label
-  "Save">
-<!ENTITY saveSearch.accesskey
-  "S">
-<!ENTITY moreCriteria.label
-  "+">
-<!ENTITY advancedSearch.onlybookmarked.label
-  "Search Bookmarks only">
-<!ENTITY advancedSearch.match.label
-  "Match ">
-<!ENTITY advancedSearch.all.label
-  "all">
-<!ENTITY advancedSearch.any.label
-  "any">
-<!ENTITY advancedSearch.rules.label
-  " of the following rules:">
-<!ENTITY advancedSearch.subj_keyword.label
-  "Containing the text">
-<!ENTITY advancedSearch.subj_visited.label
-  "Visited">
-<!ENTITY advancedSearch.subj_location.label
-  "Location">
-<!ENTITY advancedSearch.location_startswith.label
-  "starts with">
-<!ENTITY advancedSearch.location_is.label
-  "is">
-<!ENTITY advancedSearch.location_onsite.label
-  "is on site">
-<!ENTITY advancedSearch.time_is.label
-  "on">
-<!ENTITY advancedSearch.time_before.label
-  "before">
-<!ENTITY advancedSearch.time_after.label
-  "after">
-<!ENTITY advancedSearch.time_inlast.label
-  "in the last">
-<!ENTITY advancedSearch.last_days.label
-  "days">
-<!ENTITY advancedSearch.last_weeks.label
-  "weeks">
-<!ENTITY advancedSearch.last_months.label
-  "months">
-<!ENTITY advancedSearch.plus.label
-  "+">
-<!ENTITY advancedSearch.minus.label
-  "-">
-<!ENTITY advancedSearch.groupby.label
-  "Group by: ">
-<!ENTITY advancedSearch.groupby_host.label
-  "host">
-<!ENTITY advancedSearch.groupby_domain.label
-  "domain">
-<!ENTITY advancedSearch.groupby_folder.label
-  "folder">
-<!ENTITY advancedSearch.sortby.label
-  "Sort by: ">
-<!ENTITY advancedSearch.sortby_title.label
-  "title">
-<!ENTITY advancedSearch.sortby_date.label
-  "date">
-<!ENTITY advancedSearch.sortby_visit.label
-  "visit count">
-<!ENTITY advancedSearch.sortby_url.label
-  "url">
-<!ENTITY advancedSearch.sortby_asc.label
-  "ascending">
-<!ENTITY advancedSearch.sortby_desc.label
-  "descending">
-<!ENTITY advancedSearch.max.label
-  "Maximum results: ">
-<!ENTITY cmd.find.key
-  "f">
-<!ENTITY feed.subscribe.label
-  "Feed">
-<!ENTITY feed.subscribe.tooltip
-  "Subscribe">
+<!ENTITY cmd.find.key  "f">
+
+<!ENTITY feed.subscribe.label    "Feed">
+<!ENTITY feed.subscribe.tooltip  "Subscribe">
+
+<!ENTITY view.detailsMacOSX.label  "List">
+<!ENTITY view.details.label        "Details">
+<!ENTITY view.details.accesskey    "">
+
+<!ENTITY view.addons.label   "Get View Add-ons">
+<!ENTITY view.columns.label  "Columns">
+
+<!ENTITY maintenance.label   "Import and Backup">
+
+<!ENTITY backCmd.label       "Back">
+<!ENTITY backCmd.accesskey   "B">
+<!ENTITY backButton.tooltip  "Go back">
+
+<!ENTITY forwardCmd.label       "Forward">
+<!ENTITY forwardCmd.accesskey   "F">
+<!ENTITY forwardButton.tooltip  "Go forward">
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -15,17 +15,22 @@ noTitle=(no title)
 localhost=(local files)
 
 bookmarksMenuName=Bookmarks Menu
 bookmarksToolbarName=Bookmarks Toolbar
 bookmarksMenuEmptyFolder=(Empty)
 bookmarksLivemarkLoading=Live Bookmark loading...
 bookmarksLivemarkFailed=Live Bookmark feed failed to load.
 
-bookmarksBackupFilename=Bookmarks %1$S.html
+# LOCALIZATION NOTE (bookmarksBackupFilename) :
+# %S will be replaced by the current date in ISO 8601 format, YYYY-MM-DD.
+# The resulting string will be suggested as a filename, so make sure that you're
+# only using characters legal for file names. Consider falling back to the
+# en-US value if you have to use non-ascii characters.
+bookmarksBackupFilename=Bookmarks %S.html
 bookmarksBackupTitle=Bookmarks backup filename
 
 bookmarksRestoreAlertTitle=Revert Bookmarks
 bookmarksRestoreAlert=This will replace all of your current bookmarks with the backup. Are you sure?
 bookmarksRestoreTitle=Select a bookmarks backup
 
 headerTextPrefix1=Showing 
 headerTextPrefix2=Search Results for 
--- a/browser/locales/en-US/chrome/browser/preferences/applications.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/applications.dtd
@@ -1,9 +1,8 @@
-<!ENTITY  prefpane.label          "Here you can configure &brandShortName; to let your favorite applications handle different types of content.">
 <!ENTITY  filterActive.label      "The following entries match your search:">
 
 <!ENTITY  typeColumn.label        "Content Type">
 <!ENTITY  typeColumn.accesskey    "T">
 
 <!ENTITY  actionColumn.label      "Application">
 <!ENTITY  actionColumn.accesskey  "A">
 
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -40,27 +40,27 @@ languageCodeFormat=%1$S  [%2$S]
 #### Downloads
 
 desktopFolderName=Desktop
 downloadsFolderName=Downloads
 chooseDownloadFolderTitle=Choose Download Folder:
 
 #### Applications
 
-removeType=Remove this entry...
-removeButton=Remove Entry
-removeTitle=Remove Entry
-removeMessage=If you remove this entry, Firefox will ask you what to do next time you access content of this type.  Are you sure you want to remove this entry?
 fileEnding=%S file
 saveToDisk=Save to Disk
 chooseApp=Choose application...
 fpTitleChooseApp=Select Helper Application
 webFeed=Web Feed
 alwaysAskAboutFeed=Show me a preview and ask me which Feed Reader to use
 liveBookmarks=Live Bookmarks
+# LOCALIZATION NOTE (pluginName):
+# %1$S = plugin name (for example "QuickTime Plugin-in 7.2")
+# %2$S = brandShortName from brand.properties (for example "Minefield")
+pluginName=%S (in %S)
 
 #### Cookie Viewer
 
 hostColon=Host:
 domainColon=Domain:
 forSecureOnly=Encrypted connections only
 forAnyConnection=Any type of connection
 AtEndOfSession = at end of session
--- a/browser/locales/en-US/chrome/help/prefs.xhtml
+++ b/browser/locales/en-US/chrome/help/prefs.xhtml
@@ -404,21 +404,25 @@ Contributors:
 <p><em>Warn me when sites try to install add-ons</em><br/>
   &brandShortName; will always ask you to confirm installations of add-ons.
   To prevent unrequested installation prompts which may lead to accidental
   installations, &brandShortName; warns you when a web site tries to install
   an add-on and blocks the installation prompt.  To allow installations from
   a specific site, click <em>Exceptions...</em>, enter the site name, and click
   <em>Allow</em>.  Uncheck this &pref.singular; to disable the warning for all
   sites.</p>
-    
-<p><em>Tell me if the site I'm visiting is a suspected forgery</em><br/>
+
+<p id="phishing"><em>Tell me if the site I'm visiting is a suspected forgery</em><br/>
   Check this &pref.singular; if you want &brandShortName; to actively check
   whether the site you are visiting may be an attempt to mislead you into
-  providing personal information (this is often referred to as <em>phishing</em>).</p>
+  providing personal information (this is often referred to as <em>phishing</em>).<br/>
+  Note that the absence of a warning does not guarantee that a site is trustworthy.
+  If you come across a "phishing" site which is not marked as such, please report
+  it using <span class="menuPath">Help &gt; Report Web Forgery...</span>, as
+  explained in the <a href="menu_reference.xhtml#web_forgery">menu reference</a>.</p>
 
 <p><em>Check using a downloaded list of suspected sites</em><br/>
   With this &pref.singular; selected, &brandShortName; will check the current
   site against a frequently updated list stored on your computer.  No data about
   the sites you visit is transferred to third-party anti-phishing providers
   during normal browsing.  Since phishing techniques and sites evolve quickly,
   this mode of protection may not be as effective as having an anti-phishing
   provider check every site you visit.</p>
@@ -680,13 +684,13 @@ Contributors:
       your Internet environment requires it.</p>
 
     <p><em>Security Devices</em><br/>
       Security devices can encrypt and decrypt connections and store
       certificates and passwords.  If you need to use a security device other
       than the one in &brandShortName;, click the <em>Security Devices</em>
       button.</p>
 
-<div class="contentsBox"><em>12 September 2006</em></div>
+<div class="contentsBox"><em>17 September 2007</em></div>
 <p>Copyright &copy; &copyright.years; Contributors to the Mozilla Help Viewer Project.</p>
 
 </body>
 </html>
--- a/browser/locales/en-US/chrome/help/search-db.rdf
+++ b/browser/locales/en-US/chrome/help/search-db.rdf
@@ -9,16 +9,18 @@
       <Seq>
         <!--
           These nodes are used for searching purposes; they display in search results but do not
           show up in the default listing displayed when the help viewer loads.
           DO NOT CREATE NAME COLLISIONS BETWEEN THE ITEMS HERE AND THE ITEMS IN THE TOC!
         -->
         <li><Description nc:name="Accessibility Options" nc:link="prefs.xhtml#accessibility" nc:platform="win os2"/></li>
         <li><Description nc:name="Accessibility Preferences" nc:link="prefs.xhtml#accessibility" nc:platform="unix mac"/></li>
+        <li><Description nc:name="Anti-Phishing Options" nc:link="prefs.xhtml#phishing" nc:platform="win os2"/></li>
+        <li><Description nc:name="Anti-Phishing Preferences" nc:link="prefs.xhtml#phishing" nc:platform="unix mac"/></li>
         <li><Description nc:name="authentication (definition)" nc:link="glossary.xhtml#authentication"/></li>
         <li><Description nc:name="Back Button" nc:link="using_firebird.xhtml#retracing_your_steps"/></li>
         <li><Description nc:name="Block Popups" nc:link="popup.xhtml"/></li>
         <li><Description nc:name="bookmark (definition)" nc:link="glossary.xhtml#bookmark"/></li>
         <li><Description nc:name="Bookmarks Toolbar (definition)" nc:link="glossary.xhtml#Bookmarks_Toolbar"/></li>
         <li><Description nc:name="Browsing" nc:link="using_firebird.xhtml#navigating_web_pages"/></li>
         <li><Description nc:name="cache (definition)" nc:link="glossary.xhtml#cache"/></li>
         <li><Description nc:name="certificate (definition)" nc:link="glossary.xhtml#certificate"/></li>
--- a/browser/locales/en-US/installer/custom.properties
+++ b/browser/locales/en-US/installer/custom.properties
@@ -67,16 +67,17 @@ LAUNCH_TEXT=&Launch ${BrandFullName} now
 WARN_APP_RUNNING_INSTALL=${BrandFullName} must be closed to proceed with the installation.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
 WARN_APP_RUNNING_UNINSTALL=${BrandFullName} must be closed to proceed with the uninstall.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
 CREATE_ICONS_DESC=Create icons for ${BrandShortName}:
 ICONS_DESKTOP=On my &Desktop
 ICONS_STARTMENU=In my &Start Menu Programs folder
 ICONS_QUICKLAUNCH=In my &Quick Launch bar
 WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory.
 WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location.
+WARN_UNSUPPORTED_MSG=Sorry, ${BrandShortName} can't be installed. This version of ${BrandShortName} requires ${MinUnsupportedVer} or newer.
 
 STATUS_INSTALL_APP=Installing ${BrandShortName}...
 STATUS_INSTALL_LANG=Installing Language Files (${AB_CD})...
 STATUS_INSTALL_OPTIONAL=Installing Optional Components...
 STATUS_UNINSTALL_MAIN=Uninstalling ${BrandShortName}...
 STATUS_CLEANUP=A Little Housekeeping...
 
 # _DESC strings support approximately 65 characters per line.
--- a/browser/locales/en-US/installer/mui.properties
+++ b/browser/locales/en-US/installer/mui.properties
@@ -52,16 +52,17 @@
 
 # You can use \n to create a newline in the string but only when the string
 # from en-US contains a \n.
 MUI_TEXT_WELCOME_INFO_TITLE=Welcome to the $(^NameDA) Setup Wizard
 MUI_TEXT_WELCOME_INFO_TEXT=This wizard will guide you through the installation of $(^NameDA).\n\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without having to reboot your computer.\n\n$_CLICK
 MUI_TEXT_LICENSE_TITLE=License Agreement
 MUI_TEXT_LICENSE_SUBTITLE=Please review the license terms before installing $(^NameDA).
 MUI_INNERTEXT_LICENSE_TOP=Press Page Down to see the rest of the agreement.
+MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX=If you accept the terms of the agreement, click the check box below. You must accept the agreement to install $(^NameDA). $_CLICK
 MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS=If you accept the terms of the agreement, select the first option below. You must accept the agreement to install $(^NameDA). $_CLICK
 MUI_TEXT_COMPONENTS_TITLE=Choose Components
 MUI_TEXT_COMPONENTS_SUBTITLE=Choose which features of $(^NameDA) you want to install.
 MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE=Description
 MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO=Position your mouse over a component to see its description.
 MUI_TEXT_DIRECTORY_TITLE=Choose Install Location
 MUI_TEXT_DIRECTORY_SUBTITLE=Choose the folder in which to install $(^NameDA).
 MUI_TEXT_INSTALLING_TITLE=Installing
new file mode 100755
--- /dev/null
+++ b/browser/locales/filter.py
@@ -0,0 +1,28 @@
+def test(mod, path, entity = None):
+  import re
+  # ignore anyhting but Firefox
+  if mod not in ("netwerk", "dom", "toolkit", "security/manager",
+                 "browser", "extensions/reporter", "extensions/spellcheck",
+                 "other-licenses/branding/firefox"):
+    return False
+  if mod != "browser" and mod != "extensions/spellcheck":
+    # we only have exceptions for browser and extensions/spellcheck
+    return True
+  if not entity:
+    if mod == "extensions/spellcheck":
+      return False
+    # browser
+    return not (re.match(r"searchplugins\/.+\.xml", path) or
+                re.match(r"chrome\/help\/images\/[A-Za-z-_]+\.png", path))
+  if mod == "extensions/spellcheck":
+    # l10n ships en-US dictionary or something, do compare
+    return True
+  if path == "defines.inc":
+    return entity != "MOZ_LANGPACK_CONTRIBUTORS"
+
+  if path != "chrome/browser-region/region.properties":
+    # only region.properties exceptions remain, compare all others
+    return True
+  
+  return not (re.match(r"browser\.search\.order.[1-9]", entity) or
+              re.match(r"browser\.contentHandlers\.types.[0-5]", entity))
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1227,20 +1227,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 .openintabs-menuitem {
   list-style-image: none;
 }
 
 /* ::::: tabbrowser ::::: */
 
-.tabs-left {
-	display: none !important;
-}
-
 .tabbrowser-tab:not([selected="true"]):hover {
   background: url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
 }
 
 .tabbrowser-tab:hover > .tab-image-middle > .tab-icon > .tab-extra-status {
   background: none;
 }
 
@@ -1293,20 +1289,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 .tabbrowser-tab:focus > .tab-image-middle > .tab-text {
   border: 1.4pt solid -moz-mac-focusring;
 }
 
 .tabbrowser-tab[selected="true"], .tabbrowser-tab:hover {
   color: #000000;
 }
 
-.tabbrowser-tab[first-tab="true"] > .tab-image-left {
-  margin-left: 3px !important;
-}
-
 .tab-image-left, .tab-image-right {
   width: 8px;
   margin: 0px;
   padding: 0px;
 }
 
 .tabbrowser-tab > .tab-image-right {
   background: url("chrome://browser/skin/tabbrowser/tab-right.png") no-repeat;
@@ -1389,42 +1381,53 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 .tabs-bottom {