Merge from cvs-trunk-mirror to mozilla-central.
authorjorendorff@mozilla.com
Wed, 31 Oct 2007 10:40:29 -0500
changeset 7266 da56edb3eb5b
parent 6957 a7bda428ef83 (current diff)
parent 7265 9c0e67d528bf (diff)
child 8097 74d4f075ce54
push id1
push userbsmedberg@mozilla.com
push date2008-03-20 16:49 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9a9pre
Merge from cvs-trunk-mirror to mozilla-central.
client.mk
client.py
config/rules.mk
js/src/Makefile.in
js/src/js.cpp
js/src/jsfun.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/tests/js1_5/GC/regress-390078.js
js/tests/js1_7/extensions/regress-387955-01.js
js/tests/js1_7/extensions/regress-387955-02.js
layout/reftests/bugs/336736-1.html
layout/reftests/bugs/391412-1-ref.html
layout/reftests/bugs/391412-1a.html
layout/reftests/bugs/391412-1b.html
toolkit/components/places/content/places.properties
toolkit/components/places/jar.mn
toolkit/crashreporter/google-breakpad/src/common/linux/md5.c
toolkit/crashreporter/google-breakpad/src/common/linux/md5.h
toolkit/mozapps/installer/windows/nsis/AppAssocReg.dll
toolkit/mozapps/installer/windows/nsis/SetVistaDefaultApp.dll
toolkit/mozapps/installer/windows/nsis/check-locales.pl
uriloader/exthandler/nsHandlerService.js
xpcom/build/nsOS2VACLegacy.cpp
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -1634,42 +1634,37 @@ nsresult nsAccessible::AppendFlatStringF
 
   textEquivalent.CompressWhitespace();
   return AppendStringWithSpaces(aFlatString, textEquivalent);
 }
 
 
 nsresult nsAccessible::AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
 {
-  static nsIContent *startContent = nsnull;
-  // never run into the same content node, to prevent infinite recursion
-  if (startContent == aContent) {
+  static PRBool isAlreadyHere; // Prevent recursion which can cause infinite loops
+  if (isAlreadyHere) {
     return NS_OK;
   }
-  if (!startContent) {
-    startContent = aContent;
-  }
+  isAlreadyHere = PR_TRUE;
   nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString);
+  isAlreadyHere = PR_FALSE;
+
   if (NS_SUCCEEDED(rv) && !aFlatString->IsEmpty()) {
     nsAString::const_iterator start, end;
     aFlatString->BeginReading(start);
     aFlatString->EndReading(end);
 
     PRInt32 spacesToTruncate = 0;
     while (-- end != start && *end == ' ')
       ++ spacesToTruncate;
 
     if (spacesToTruncate > 0)
       aFlatString->Truncate(aFlatString->Length() - spacesToTruncate);
   }
 
-  if (startContent == aContent) {
-    // we are leaving the original invoking
-    startContent = nsnull;
-  }
   return rv;
 }
 
 nsresult nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString)
 {
   // Depth first search for all text nodes that are decendants of content node.
   // Append all the text into one flat string
   PRUint32 numChildren = 0;
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -59,17 +59,17 @@ 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
+    { NS_ENSURE_ARG_POINTER(aAccessible); NS_ADDREF(*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/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -726,17 +726,17 @@ nsresult nsRootAccessible::HandleEventWi
 
       return nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SELECTION,
                                       treeItemAccessible);
     }
   }
   else
 #endif
   if (eventType.EqualsLiteral("focus")) {
-    if (aTargetNode == mDOMNode) {
+    if (aTargetNode == mDOMNode && mDOMNode != gLastFocusedNode) {
       // Got focus event for the window, we will make sure that an accessible
       // focus event for initial focus is fired. We do this on a short timer
       // because the initial focus may not have been set yet.
       if (!mFireFocusTimer) {
         mFireFocusTimer = do_CreateInstance("@mozilla.org/timer;1");
       }
       if (mFireFocusTimer) {
         mFireFocusTimer->InitWithFuncCallback(FireFocusCallback, this,
@@ -842,18 +842,25 @@ nsresult nsRootAccessible::HandleEventWi
         // is active.
         return NS_OK;
       } else {
         nsCOMPtr<nsIAccessible> containerAccessible;
         accessible->GetParent(getter_AddRefs(containerAccessible));
         NS_ENSURE_TRUE(containerAccessible, NS_ERROR_FAILURE);
         // It is not top level menuitem
         // Only fire focus event if it is not inside collapsed popup
-        if (State(containerAccessible) & nsIAccessibleStates::STATE_COLLAPSED)
-          return NS_OK;
+        // and not a listitem of a combo box
+        if (State(containerAccessible) & nsIAccessibleStates::STATE_COLLAPSED) {
+          nsCOMPtr<nsIAccessible> containerParent;
+          containerAccessible->GetParent(getter_AddRefs(containerParent));
+          NS_ENSURE_TRUE(containerParent, NS_ERROR_FAILURE);
+          if (Role(containerParent) != nsIAccessibleRole::ROLE_COMBOBOX) {
+            return NS_OK;
+          }
+        }
       }
     }
     nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);  // Always asynch, always from user input
     FireAccessibleFocusEvent(accessible, aTargetNode, aEvent, PR_TRUE, PR_TRUE);
   }
   else if (eventType.EqualsLiteral("DOMMenuBarActive")) {  // Always asynch, always from user input
     nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
     nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, accessible, PR_TRUE);
--- a/accessible/src/html/nsHTMLAreaAccessible.h
+++ b/accessible/src/html/nsHTMLAreaAccessible.h
@@ -52,12 +52,12 @@ public:
   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
+    { NS_ENSURE_ARG_POINTER(aAccessible); NS_ADDREF(*aAccessible = this); return NS_OK; } // Don't walk into these
 };
 
 #endif  
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -844,17 +844,20 @@ nsHTMLTableAccessible::GetTableLayout(ns
 
   nsCOMPtr<nsIDOMNode> tableNode;
   rv = GetTableNode(getter_AddRefs(tableNode));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(tableNode));
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
-  nsIPresShell *presShell = content->GetDocument()->GetPrimaryShell();
+  nsIDocument *doc = content->GetDocument();
+  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+
+  nsIPresShell *presShell = doc->GetPrimaryShell();
 
   nsCOMPtr<nsISupports> layoutObject;
   rv = presShell->GetLayoutObjectFor(content, getter_AddRefs(layoutObject));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return CallQueryInterface(layoutObject, aLayoutObject);
 }
 
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -195,18 +195,16 @@ pref("browser.urlbar.clickSelectsAll", t
 #endif
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.doubleClickSelectsAll", true);
 #else
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 pref("browser.urlbar.autoFill", false);
 pref("browser.urlbar.matchOnlyTyped", false);
-pref("browser.urlbar.hideProtocols", "");
-pref("browser.urlbar.animateBlend", true);
 
 pref("browser.download.useDownloadDir", true);
 pref("browser.download.folderList", 0);
 pref("browser.download.manager.showAlertOnComplete", true);
 pref("browser.download.manager.showAlertInterval", 2000);
 pref("browser.download.manager.retention", 2);
 pref("browser.download.manager.showWhenStarting", true);
 pref("browser.download.manager.useWindow", true);
@@ -375,17 +373,17 @@ pref("mousewheel.withshiftkey.sysnumline
 pref("mousewheel.withshiftkey.numlines",1);
 pref("mousewheel.withaltkey.action",0);
 pref("mousewheel.withaltkey.sysnumlines",false);
 pref("mousewheel.withaltkey.numlines",1);
 pref("mousewheel.withmetakey.action",0);
 pref("mousewheel.withmetakey.sysnumlines",true);
 pref("mousewheel.withmetakey.numlines",1);
 #endif
-pref("mousewheel.withcontrolkey.action",3);
+pref("mousewheel.withcontrolkey.action",5);
 pref("mousewheel.withcontrolkey.sysnumlines",false);
 pref("mousewheel.withcontrolkey.numlines",1);
 
 pref("profile.allow_automigration", false);   // setting to false bypasses automigration in the profile code
 
 // Customizable toolbar stuff
 pref("custtoolbar.personal_toolbar_folder", "");
 
@@ -438,21 +436,17 @@ pref("pfs.datasource.url", "https://pfs.
 // by default we show an infobar message when pages require plugins the user has not installed
 pref("plugins.hide_infobar_for_missing_plugin", false);
 
 #ifdef XP_WIN
 pref("browser.preferences.instantApply", false);
 #else
 pref("browser.preferences.instantApply", true);
 #endif
-#ifdef XP_MACOSX
-pref("browser.preferences.animateFadeIn", true);
-#else
 pref("browser.preferences.animateFadeIn", false);
-#endif
 
 pref("browser.download.show_plugins_in_list", true);
 pref("browser.download.hide_plugins_without_extensions", true);
 
 // Setting this pref to |true| forces BiDi UI menu items and keyboard shortcuts
 // to be exposed. By default, only expose it for bidi-associated system locales.
 pref("bidi.browser.ui", false);
 
@@ -540,16 +534,20 @@ pref("browser.safebrowsing.provider.0.pr
 
 // HTML report pages
 pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
 
 // FAQ URL
 pref("browser.safebrowsing.warning.infoURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
+
+// Name of the about: page contributed by safebrowsing to handle display of error
+// pages on phishing/malware hits.  (bug 399233)
+pref("urlclassifier.alternate_error_page", "blocked");
 #endif
 
 // defaults to true
 pref("browser.EULA.2.accepted", true);
 
 // if we rev the EULA again, we should bump this so users agree to the new EULA
 pref("browser.EULA.version", 2);
 
@@ -569,13 +567,10 @@ pref("browser.sessionstore.privacy_level
 pref("browser.sessionstore.max_tabs_undo", 10);
 
 // allow META refresh by default
 pref("accessibility.blockautorefresh", false);
 
 // import bookmarks.html into Places bookmarks
 pref("browser.places.importBookmarksHTML", true);
 
-// Show infobar on chromeless windows
-pref("browser.warn_chromeless_window.infobar", false);
-
 // if false, will add the "Places" folder to the personal toolbar
 pref("browser.places.createdDefaultQueries", false);
--- a/browser/base/content/aboutDialog.css
+++ b/browser/base/content/aboutDialog.css
@@ -1,10 +1,13 @@
 #aboutDialog {
-  padding: 0px 0px 10px 0px;
+  padding-top: 0;
+  -moz-padding-end: 0;
+  padding-bottom: 10px;
+  -moz-padding-start: 0;
   width: 299px;
 }
 
 #modes {
   min-height: 380px;
 }
 
 #clientBox {
@@ -15,58 +18,76 @@
   color: #000000;
 }
 
 #brandName {
   font-weight: bold; font-size: larger;
 } 
 
 #userAgent {
-  margin: 11px 20px 0px 13px;
+  margin-top: 11px;
+  -moz-margin-end: 20px;
+  margin-bottom: 0;
+  -moz-margin-start: 13px;
   background-color: #FFFFFF;
   color: #000000;
-  padding: 1px 0px 0px 3px;
+  padding-top: 1px;
+  -moz-padding-end: 0;
+  padding-bottom: 0;
+  -moz-padding-start: 3px;
   -moz-appearance: none;
   overflow: hidden;
-  border: 0px;
+  border: 0;
 }
 
 #groove {
-  margin-top: 0px;
+  margin-top: 0;
 }
 
 #creditsIframe {
   cursor: default;
   -moz-user-select: none;
-  border: 0px;
+  border: 0;
 }
 
 #version {
   font-weight: bold;
   color: #909090;
-  margin: 1em 0px 10px 17px;
+  margin-top: 1em;
+  -moz-margin-end: 0;
+  margin-bottom: 10px;
+  -moz-margin-start: 17px;
 }
 
 #distribution {
   font-weight: bold;
   color: #909090;
   display: none;
-  margin: 0em 0px 0px 17px;
+  margin-top: 0;
+  -moz-margin-end: 0;
+  margin-bottom: 0;
+  -moz-margin-start: 17px;
 }
 
 #distributionId {
   font-weight: bold;
   color: #909090;
   display: none;
-  margin: 0em 0px 10px 17px;
+  margin-top: 0;
+  -moz-margin-end: 0;
+  margin-bottom: 10px;
+  -moz-margin-start: 17px;
 }
 
 #copyright {
-  margin: 0px 0px 3px 16px;
+  margin-top: 0;
+  -moz-margin-end: 0;
+  margin-bottom: 3px;
+  -moz-margin-start: 16px;
 }
 
 button[dlgtype="extra2"] {
-  margin-left: 13px;
+  -moz-margin-start: 13px;
 }
 
 button[dlgtype="accept"] {
-  margin-right: 13px;
+  -moz-margin-end: 13px;
 }
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -166,25 +166,25 @@
                           command="Browser:Stop"
 #ifdef XP_MACOSX
                           key="key_stop_mac"/>
 #else
                           key="key_stop"/>
 #endif
                 <menuitem label="&reloadCmd.label;" accesskey="&reloadCmd.accesskey;" command="Browser:Reload" key="key_reload"/>
                 <menuseparator/>
-                <menu id="viewTextZoomMenu" label="&textSize.label;" accesskey="&textSize.accesskey;" observes="isImage">
-                  <menupopup>                    
-                    <menuitem key="key_textZoomEnlarge" label="&textZoomEnlargeCmd.label;" accesskey="&textZoomEnlargeCmd.accesskey;"
-                              command="cmd_textZoomEnlarge"/>
-                    <menuitem key="key_textZoomReduce"  label="&textZoomReduceCmd.label;"  accesskey="&textZoomReduceCmd.accesskey;"
-                              command="cmd_textZoomReduce"/>
+                <menu id="viewFullZoomMenu" label="&fullZoom.label;" accesskey="&fullZoom.accesskey;" observes="isImage">
+                  <menupopup>
+                    <menuitem key="key_fullZoomEnlarge" label="&fullZoomEnlargeCmd.label;" accesskey="&fullZoomEnlargeCmd.accesskey;"
+                              command="cmd_fullZoomEnlarge"/>
+                    <menuitem key="key_fullZoomReduce"  label="&fullZoomReduceCmd.label;"  accesskey="&fullZoomReduceCmd.accesskey;"
+                              command="cmd_fullZoomReduce"/>
                     <menuseparator/>
-                    <menuitem key="key_textZoomReset" label="&textZoomResetCmd.label;" accesskey="&textZoomResetCmd.accesskey;"
-                              command="cmd_textZoomReset"/>
+                    <menuitem key="key_fullZoomReset" label="&fullZoomResetCmd.label;" accesskey="&fullZoomResetCmd.accesskey;"
+                              command="cmd_fullZoomReset"/>
                   </menupopup>
                 </menu>
                 <menu id="pageStyleMenu" label="&pageStyleMenu.label;" accesskey="&pageStyleMenu.accesskey;" observes="isImage">
                   <menupopup onpopupshowing="stylesheetFillPopup(this);"
                              oncommand="stylesheetSwitchAll(window.content, event.target.getAttribute('data')); setStyleDisabled(false);">
                     <menuitem label="&pageStyleNoStyle.label;" accesskey="&pageStyleNoStyle.accesskey;"
                               oncommand="setStyleDisabled(true); event.stopPropagation();" type="radio"/>
                     <menuitem label="&pageStylePersistentOnly.label;" accesskey="&pageStylePersistentOnly.accesskey;" type="radio" checked="true"/>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -45,17 +45,21 @@ var PlacesCommandHook = {
         aIID.equals(Ci.nsISupports))
       return this;
 
     throw Cr.NS_NOINTERFACE;
   },
 
   // Edit-bookmark panel
   get panel() {
-    return document.getElementById("editBookmarkPanel");
+    delete this.panel;
+    var element = document.getElementById("editBookmarkPanel");
+    element.addEventListener("popuphiding", this, false);
+    element.addEventListener("keypress", this, true);
+    return this.panel = element;
   },
 
   // list of command elements (by id) to disable when the panel is opened
   _blockedCommands: ["cmd_close", "cmd_closeWindow"],
 
   _blockCommands: function PCH__blockCommands() {
     for each(var key in this._blockedCommands) {
       var elt = document.getElementById(key);
@@ -124,23 +128,25 @@ var PlacesCommandHook = {
           aSelf._self._doShowEditBookmarkPanel(aItemId, aSelf._anchorElement,
                                                aSelf._position);
         }, 0, this);
       }
     };
     this._overlayLoading = true;
     document.loadOverlay("chrome://browser/content/places/editBookmarkOverlay.xul",
                          loadObserver);
-    this.panel.addEventListener("popuphiding", this, false);
   },
 
   _doShowEditBookmarkPanel:
   function PCH__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) {
-    this.panel.addEventListener("keypress", this, true);
     this._blockCommands(); // un-done in the popuphiding handler
+
+    // Consume dismiss clicks, see bug 400924
+    this.panel.popupBoxObject
+        .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
     this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
 
     gEditItemOverlay.initPanel(aItemId,
                                { hiddenRows: ["description", "location",
                                               "loadInSidebar", "keyword"] });
     setTimeout(function() {
                  var namePicker = document.getElementById("editBMPanel_namePicker");
                  namePicker.focus();
@@ -400,48 +406,43 @@ var BookmarksEventHandler = {
     if (target.localName == "menu" ||
         target.localName == "menuitem") {
       var node = target.parentNode;
       while (node && 
              (node.localName == "menu" || 
               node.localName == "menupopup")) {
         if (node.localName == "menupopup")
           node.hidePopup();
-        
+
         node = node.parentNode;
       }
     }
     // The event target we get if someone middle clicks on a bookmark in the
     // bookmarks toolbar overflow menu is different from if they click on a
     // bookmark in a folder or in the bookmarks menu; handle this case
     // separately.
     var bookmarksBar = document.getElementById("bookmarksBarContent");
     if (bookmarksBar._chevron.getAttribute("open") == "true")
-      bookmarksBar._chevron.firstChild.hidePopupAndChildPopups();
+      bookmarksBar._chevron.firstChild.hidePopup();
   },
-  
+
   /**
    * Handler for command event for an item in the bookmarks toolbar.
    * Menus and submenus from the folder buttons bubble up to this handler.
    * Opens the item.
    * @param aEvent 
    *        DOMEvent for the command
    */
   onCommand: function BM_onCommand(aEvent) {
-    // If this is the special "Open All in Tabs" menuitem,
-    // load all the menuitems in tabs.
-
     var target = aEvent.originalTarget;
-    if (target.hasAttribute("siteURI"))
-      openUILink(target.getAttribute("siteURI"), aEvent);
-    // If this is a normal bookmark, just load the bookmark's URI.
-    else if (!target.hasAttribute("openInTabs"))
+    if (target.node) {
       PlacesUtils.getViewForNode(target)
                  .controller
                  .openSelectedNodeWithEvent(aEvent);
+    }
   },
 
   /**
    * Handler for popupshowing event for an item in bookmarks toolbar or menu.
    * If the item isn't the main bookmarks menu, add an "Open All in Tabs"
    * menuitem to the bottom of the popup.
    * @param event 
    *        DOMEvent for popupshowing
@@ -451,59 +452,61 @@ var BookmarksEventHandler = {
     if (target.localName == "menupopup" &&
         target.id != "bookmarksMenuPopup" &&
         target.getAttribute("anonid") != "chevronPopup") {
       // Add the "Open All in Tabs" menuitem if there are
       // at least two menuitems with places result nodes.
       // Add the "Open (Feed Name)" menuitem if it's a livemark with a siteURI.
       var numNodes = 0;
       var hasMultipleEntries = false;
-      var hasFeedHomePage = false;
       var currentChild = target.firstChild;
       while (currentChild) {
         if (currentChild.localName == "menuitem" && currentChild.node)
           numNodes++;
 
         // If the menuitem already exists, do nothing.
         if (currentChild.getAttribute("openInTabs") == "true")
           return;
         if (currentChild.hasAttribute("siteURI"))
           return;
 
         currentChild = currentChild.nextSibling;
       }
       if (numNodes > 1)
         hasMultipleEntries = true;
 
-      var button = target.parentNode;
-      if (button.getAttribute("livemark") == "true" &&
-          button.hasAttribute("siteURI"))
-        hasFeedHomePage = true;
+      var itemId = target._resultNode.itemId;
+      var siteURIString = "";
+      if (itemId != -1 && PlacesUtils.livemarks.isLivemark(itemId)) {
+        var siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
+        if (siteURI)
+          siteURIString = siteURI.spec;
+      }
 
-      if (hasMultipleEntries || hasFeedHomePage) {
+      if (hasMultipleEntries || siteURIString) {
         var separator = document.createElement("menuseparator");
         target.appendChild(separator);
 
-        if (hasFeedHomePage) {
+        if (siteURIString) {
           var openHomePage = document.createElement("menuitem");
-          openHomePage.setAttribute(
-            "siteURI", button.getAttribute("siteURI"));
+          openHomePage.setAttribute("siteURI", siteURIString);
+          openHomePage.setAttribute("oncommand",
+                                    "openUILink(this.getAttribute('siteURI'), event);");
           openHomePage.setAttribute(
             "label",
             PlacesUtils.getFormattedString("menuOpenLivemarkOrigin.label",
-                                           [button.getAttribute("label")]));
+                                           [target.parentNode.getAttribute("label")]));
           target.appendChild(openHomePage);
         }
 
         if (hasMultipleEntries) {
           var openInTabs = document.createElement("menuitem");
           openInTabs.setAttribute("openInTabs", "true");
-          openInTabs.setAttribute("onclick", "checkForMiddleClick(this, event)");
           openInTabs.setAttribute("oncommand",
-                                  "PlacesUtils.openContainerNodeInTabs(this.parentNode.getResultNode(), event);");
+                                  "PlacesUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);");
           openInTabs.setAttribute("label",
                      gNavigatorBundle.getString("menuOpenAllInTabs.label"));
           target.appendChild(openInTabs);
         }
       }
     }
   },
 
@@ -698,29 +701,29 @@ var PlacesMenuDNDController = {
     if (PlacesControllerDragHelper.draggingOverChildNode(target))
       return;
 
     if ("closeTime" in this._timers)
       delete this._timers.closeTime;
     
     // Close the bookmarks menu
     var bookmarksMenu = document.getElementById("bookmarksMenu");
-    bookmarksMenu.firstChild.hidePopupAndChildPopups();
+    bookmarksMenu.firstChild.hidePopup();
 
     var bookmarksBar = document.getElementById("bookmarksBarContent");
     if (bookmarksBar) {
       // Close the overflow chevron menu and all its children
-      bookmarksBar._chevron.firstChild.hidePopupAndChildPopups();
+      bookmarksBar._chevron.firstChild.hidePopup();
 
       // Close all popups on the bookmarks toolbar
       var toolbarItems = bookmarksBar.childNodes;
       for (var i = 0; i < toolbarItems.length; ++i) {
         var item = toolbarItems[i]
         if (this._isContainer(item))
-          item.firstChild.hidePopupAndChildPopups();
+          item.firstChild.hidePopup();
       }
     }
   },
   
   /**
    * Opens the Bookmarks Menu when it is dragged over. (This is special-cased, 
    * since the toplevel Bookmarks <menu> is not a member of an existing places
    * container, as folders on the personal toolbar or submenus are. 
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -96,19 +96,19 @@
              oncommand="gBookmarkAllTabsHandler.doCommand();"
              disabled="true"/>
     <command id="Browser:Home"    oncommand="BrowserHome();"/>
     <command id="Browser:Back"    oncommand="BrowserBack();" disabled="true"/>
     <command id="Browser:Forward" oncommand="BrowserForward();" disabled="true"/>
     <command id="Browser:Stop"    oncommand="BrowserStop();" disabled="true"/>
     <command id="Browser:Reload"  oncommand="if (event.shiftKey) BrowserReloadSkipCache(); else BrowserReload()" disabled="true"/>
     <command id="Browser:ReloadSkipCache"  oncommand="BrowserReloadSkipCache()" disabled="true"/>
-    <command id="cmd_textZoomReduce"  oncommand="TextZoom.reduce()"/>
-    <command id="cmd_textZoomEnlarge" oncommand="TextZoom.enlarge()"/>
-    <command id="cmd_textZoomReset" oncommand="TextZoom.reset()"/>
+    <command id="cmd_fullZoomReduce"  oncommand="FullZoom.reduce()"/>
+    <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
+    <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>    
     <command id="Tools:Downloads" oncommand="toOpenWindowByType('Download:Manager', 
                                                                 'chrome://mozapps/content/downloads/downloads.xul',
                                                                 'chrome,dialog=no,resizable');"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:Sanitize"
@@ -281,20 +281,20 @@
          key="&historySidebarCmd.commandKey;"
 #ifdef XP_MACOSX
          modifiers="accel,shift"
 #else
          modifiers="accel"
 #endif
          command="viewHistorySidebar"/>
 
-    <key id="key_textZoomReduce"  key="&textZoomReduceCmd.commandkey;"   command="cmd_textZoomReduce"  modifiers="accel"/>
-    <key id="key_textZoomEnlarge" key="&textZoomEnlargeCmd.commandkey;"  command="cmd_textZoomEnlarge" modifiers="accel"/>
-    <key                          key="&textZoomEnlargeCmd.commandkey2;" command="cmd_textZoomEnlarge" modifiers="accel"/>
-    <key id="key_textZoomReset"   key="&textZoomResetCmd.commandkey;"    command="cmd_textZoomReset"   modifiers="accel"/>
+    <key id="key_fullZoomReduce"  key="&fullZoomReduceCmd.commandkey;"   command="cmd_fullZoomReduce"  modifiers="accel"/>
+    <key id="key_fullZoomEnlarge" key="&fullZoomEnlargeCmd.commandkey;"  command="cmd_fullZoomEnlarge" modifiers="accel"/>
+    <key                          key="&fullZoomEnlargeCmd.commandkey2;" command="cmd_fullZoomEnlarge" modifiers="accel"/>
+    <key id="key_fullZoomReset"   key="&fullZoomResetCmd.commandkey;"    command="cmd_fullZoomReset"   modifiers="accel"/>
     
     <key id="key_switchTextDirection" key="&bidiSwitchTextDirectionItem.commandkey;" command="cmd_switchTextDirection" modifiers="accel,shift" />
 
     <key id="key_sanitize" command="Tools:Sanitize" keycode="VK_DELETE" modifiers="accel,shift"/>
 #ifdef XP_MACOSX
     <key id="key_sanitize_mac" command="Tools:Sanitize" keycode="VK_BACK" modifiers="accel,shift"/>
     <key id="key_quitApplicationCmdMac" key="&quitApplicationCmdMac.key;" modifiers="accel"/>
 #endif
--- a/browser/base/content/browser-textZoom.js
+++ b/browser/base/content/browser-textZoom.js
@@ -16,16 +16,17 @@
  * The Original Code is Content Preferences (cpref).
  *
  * The Initial Developer of the Original Code is Mozilla.
  * Portions created by the Initial Developer are Copyright (C) 2006
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Myk Melez <myk@mozilla.org>
+ *   Dão Gottwald <dao@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -36,105 +37,82 @@
  *
  * ***** END LICENSE BLOCK *****
 #endif
  */
 
 // From nsMouseScrollEvent::kIsHorizontal
 const MOUSE_SCROLL_IS_HORIZONTAL = 1 << 2;
 
-// Not sure where this comes from.  It's one of the possible values
-// for the mousewheel.* preferences.
-const MOUSE_SCROLL_TEXTSIZE = 3;
+// One of the possible values for the mousewheel.* preferences.
+// From nsEventStateManager.cpp.
+const MOUSE_SCROLL_FULLZOOM = 5;
 
 /**
- * Controls the "text zoom" setting and its site-specific preferences.
+ * Controls the "full zoom" setting and its site-specific preferences.
  */
-var TextZoom = {
+var FullZoom = {
 
   //**************************************************************************//
   // Name & Values
 
   // The name of the setting.  Identifies the setting in the prefs database.
-  name: "browser.content.text-zoom",
+  name: "browser.content.full-zoom",
 
   // The global value (if any) for the setting.  Retrieved from the prefs
   // database when this handler gets initialized, then updated as it changes.
   // If there is no global value, then this should be undefined.
   globalValue: undefined,
 
-  // From viewZoomOverlay.js
-  minValue: 1,
-  maxValue: 2000,
-  defaultValue: 100,
-
 
   //**************************************************************************//
   // Convenience Getters
 
-  __zoomManager: null,
-  get _zoomManager() {
-    if (!this.__zoomManager)
-      this.__zoomManager = ZoomManager.prototype.getInstance();
-    return this.__zoomManager;
-  },
-
   // Content Pref Service
-  __cps: null,
   get _cps() {
-    if (!this.__cps)
-      this.__cps = Cc["@mozilla.org/content-pref/service;1"].
-                   getService(Ci.nsIContentPrefService);
-    return this.__cps;
-  },
-
-  // Pref Branch
-  __prefBranch: null,
-  get _prefBranch() {
-    if (!this.__prefBranch)
-      this.__prefBranch = Cc["@mozilla.org/preferences-service;1"].
-                           getService(Ci.nsIPrefBranch);
-    return this.__prefBranch;
+    delete this._cps;
+    return this._cps = Cc["@mozilla.org/content-pref/service;1"].
+                       getService(Ci.nsIContentPrefService);
   },
 
 
   //**************************************************************************//
   // nsISupports
 
   // We can't use the Ci shortcut here because it isn't defined yet.
   interfaces: [Components.interfaces.nsIDOMEventListener,
                Components.interfaces.nsIContentPrefObserver,
                Components.interfaces.nsISupports],
 
-  QueryInterface: function TextZoom_QueryInterface(aIID) {
-    if (!this.interfaces.some( function(v) { return aIID.equals(v) } ))
+  QueryInterface: function (aIID) {
+    if (!this.interfaces.some(function (v) aIID.equals(v)))
       throw Cr.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
 
   //**************************************************************************//
   // Initialization & Destruction
 
-  init: function TextZoom_init() {
+  init: function () {
     // Listen for scrollwheel events so we can save scrollwheel-based changes.
     window.addEventListener("DOMMouseScroll", this, false);
 
     // Register ourselves with the service so we know when our pref changes.
     this._cps.addObserver(this.name, this);
 
     // Register ourselves with the sink so we know when the location changes.
     var globalValue = ContentPrefSink.addObserver(this.name, this);
     this.globalValue = this._ensureValid(globalValue);
 
     // Set the initial value of the setting.
     this._applyPrefToSetting();
   },
 
-  destroy: function TextZoom_destroy() {
+  destroy: function () {
     ContentPrefSink.removeObserver(this.name, this);
     this._cps.removeObserver(this.name, this);
     window.removeEventListener("DOMMouseScroll", this, false);
 
     // Delete references to XPCOM components to make sure we don't leak them
     // (although we haven't observed leakage in tests).
     for (var i in this) {
       try { this[i] = null }
@@ -144,22 +122,25 @@ var TextZoom = {
   },
 
 
   //**************************************************************************//
   // Event Handlers
 
   // nsIDOMEventListener
 
-  handleEvent: function TextZoom_handleEvent(event) {
-    // The only events we handle are DOMMouseScroll events.
-    this._handleMouseScrolled(event);
+  handleEvent: function (event) {
+    switch (event.type) {
+      case "DOMMouseScroll":
+        this._handleMouseScrolled(event);
+        break;
+    }
   },
 
-  _handleMouseScrolled: function TextZoom__handleMouseScrolled(event) {
+  _handleMouseScrolled: function (event) {
     // Construct the "mousewheel action" pref key corresponding to this event.
     // Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
     var pref = "mousewheel";
     if (event.scrollFlags & MOUSE_SCROLL_IS_HORIZONTAL)
       pref += ".horizscroll";
 
     if (event.shiftKey)
       pref += ".withshiftkey";
@@ -169,163 +150,142 @@ var TextZoom = {
       pref += ".withaltkey";
     else if (event.metaKey)
       pref += ".withmetakey";
     else
       pref += ".withnokey";
 
     pref += ".action";
 
-    // Don't do anything if this isn't a "change text size" scroll event.
-    if (this._getAppPref(pref, null) != MOUSE_SCROLL_TEXTSIZE)
+    // Don't do anything if this isn't a "zoom" scroll event.
+    var isZoomEvent = false;
+    try {
+      isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_FULLZOOM);
+    } catch (e) {}
+    if (!isZoomEvent)
       return;
 
     // XXX Lazily cache all the possible action prefs so we don't have to get
     // them anew from the pref service for every scroll event?  We'd have to
     // make sure to observe them so we can update the cache when they change.
 
     // We have to call _applySettingToPref in a timeout because we handle
     // the event before the event state manager has a chance to apply the zoom
     // during nsEventStateManager::PostHandleEvent.
-    window.setTimeout(function() { TextZoom._applySettingToPref() }, 0);
+    window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
   },
 
   // nsIContentPrefObserver
 
-  onContentPrefSet: function TextZoom_onContentPrefSet(aGroup, aName, aValue) {
+  onContentPrefSet: function (aGroup, aName, aValue) {
     if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
       this._applyPrefToSetting(aValue);
     else if (aGroup == null) {
       this.globalValue = this._ensureValid(aValue);
 
       // If the current page doesn't have a site-specific preference,
       // then its zoom should be set to the new global preference now that
       // the global preference has changed.
       if (!this._cps.hasPref(gBrowser.currentURI, this.name))
         this._applyPrefToSetting();
     }
   },
 
-  onContentPrefRemoved: function TextZoom_onContentPrefRemoved(aGroup, aName) {
+  onContentPrefRemoved: function (aGroup, aName) {
     if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
       this._applyPrefToSetting();
     else if (aGroup == null) {
       this.globalValue = undefined;
 
       // If the current page doesn't have a site-specific preference,
       // then its zoom should be set to the default preference now that
       // the global preference has changed.
       if (!this._cps.hasPref(gBrowser.currentURI, this.name))
         this._applyPrefToSetting();
     }
   },
 
   // ContentPrefSink observer
 
-  onLocationChanged: function TextZoom_onLocationChanged(aURI, aName, aValue) {
+  onLocationChanged: function (aURI, aName, aValue) {
     this._applyPrefToSetting(aValue);
   },
 
 
   //**************************************************************************//
   // Setting & Pref Manipulation
 
-  reduce: function TextZoom_reduce() {
-    this._zoomManager.reduce();
+  reduce: function () {
+    ZoomManager.reduce();
     this._applySettingToPref();
   },
 
-  enlarge: function TextZoom_enlarge() {
-    this._zoomManager.enlarge();
+  enlarge: function () {
+    ZoomManager.enlarge();
     this._applySettingToPref();
   },
 
-  reset: function TextZoom_reset() {
+  reset: function () {
     if (typeof this.globalValue != "undefined")
-      this._zoomManager.textZoom = this.globalValue;
+      ZoomManager.fullZoom = this.globalValue;
     else
-      this._zoomManager.reset();
+      ZoomManager.reset();
 
     this._removePref();
   },
 
   /**
-   * Set the text zoom for the current tab.
+   * Set the zoom level for the current tab.
    *
-   * Per DocumentViewerImpl::SetTextZoom in nsDocumentViewer.cpp, it looks
+   * Per DocumentViewerImpl::SetFullZoom in nsDocumentViewer.cpp, it looks
    * like we can set the zoom to its current value without significant impact
    * on performance, as the setting is only applied if it differs from the
    * current setting.
    *
    * And perhaps we should always set the zoom even if it were to incur
-   * a performance penalty, since SetTextZoom claims that child documents
+   * a performance penalty, since SetFullZoom claims that child documents
    * may have a different zoom under unusual circumstances, and it implies
    * that those child zooms should get updated when the parent zoom gets set.
    *
    * So when we apply new zoom values to the browser, we simply set the zoom.
    * We don't check first to see if the new value is the same as the current
    * one.
    **/
-  _applyPrefToSetting: function TextZoom__applyPrefToSetting(aValue) {
+  _applyPrefToSetting: function (aValue) {
     // Bug 375918 means this will sometimes throw, so we catch it
     // and don't do anything in those cases.
     try {
       if (typeof aValue != "undefined")
-        this._zoomManager.textZoom = this._ensureValid(aValue);
+        ZoomManager.fullZoom = this._ensureValid(aValue);
       else if (typeof this.globalValue != "undefined")
-        this._zoomManager.textZoom = this.globalValue;
+        ZoomManager.fullZoom = this.globalValue;
       else
-        this._zoomManager.reset();
+        ZoomManager.reset();
     }
     catch(ex) {}
   },
 
-  _applySettingToPref: function TextZoom__applySettingToPref() {
-    var textZoom = this._zoomManager.textZoom;
-    this._cps.setPref(gBrowser.currentURI, this.name, textZoom);
+  _applySettingToPref: function () {
+    var fullZoom = ZoomManager.fullZoom;
+    this._cps.setPref(gBrowser.currentURI, this.name, fullZoom);
   },
 
-  _removePref: function TextZoom__removePref() {
+  _removePref: function () {
     this._cps.removePref(gBrowser.currentURI, this.name);
   },
 
 
   //**************************************************************************//
   // Utilities
 
-  _ensureValid: function TextZoom__ensureValid(aValue) {
+  _ensureValid: function (aValue) {
     if (isNaN(aValue))
-      return this.defaultValue;
+      return 1;
 
-    if (aValue < this.minValue)
-      return this.minValue;
+    if (aValue < ZoomManager.MIN)
+      return ZoomManager.MIN;
 
-    if (aValue > this.maxValue)
-      return this.maxValue;
+    if (aValue > ZoomManager.MAX)
+      return ZoomManager.MAX;
 
     return aValue;
-  },
-
-  /**
-   * Get a value from a pref or a default value if the pref doesn't exist.
-   *
-   * @param   aPrefName
-   * @param   aDefaultValue
-   * @returns the pref's value or the default (if it is missing)
-   */
-  _getAppPref: function TextZoom__getAppPref(aPrefName, aDefaultValue) {
-    try {
-      switch (this._prefBranch.getPrefType(aPrefName)) {
-        case this._prefBranch.PREF_STRING:
-          return this._prefBranch.getCharPref(aPrefName);
-
-        case this._prefBranch.PREF_BOOL:
-          return this._prefBranch.getBoolPref(aPrefName);
-
-        case this._prefBranch.PREF_INT:
-          return this._prefBranch.getIntPref(aPrefName);
-      }
-    }
-    catch (ex) { /* return the default value */ }
-    
-    return aDefaultValue;
   }
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -357,64 +357,66 @@ function initPlacesDefaultQueries() {
       // XXX should this be a pref?  see bug #399268
       var maxResults = 10;
 
       // exclude queries so that user created "saved searches" 
       // and these queries (added automatically) are excluded
       var recentlyCreatedBookmarksItem = bmsvc.insertBookmark(placesFolder,
         IO.newURI("place:folder=" + bookmarksRoot + "&folder=" + unfiledRoot +
             "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-            "&sort=" + 
+            "&sort=" +
             Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
             "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
             "&maxResults=" + maxResults +
             "&excludeQueries=1"),
             defaultIndex, recentlyCreatedBookmarksTitle);
 
       var recentlyVisitedBookmarksItem = bmsvc.insertBookmark(placesFolder,
         IO.newURI("place:folder=" + bookmarksRoot + "&folder=" + unfiledRoot +
             "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-            "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING + 
+            "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING +
+            "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
             "&minVisits=1&maxResults=" + maxResults),
             defaultIndex, recentlyVisitedBookmarksTitle);
 
       var mostVisitedBookmarksItem = bmsvc.insertBookmark(placesFolder,
         IO.newURI("place:folder=" + bookmarksRoot + "&folder=" + unfiledRoot +
             "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-            "&sort=" + 
-            Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + 
+            "&sort=" +
+            Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
+            "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
             "&minVisits=1&maxResults=" + maxResults),
             defaultIndex, mostVisitedBookmarksTitle);
 
       var recentlyUsedTagsItem = bmsvc.insertBookmark(placesFolder,
         IO.newURI("place:folder=" + tagRoot +
             "&group=" + Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER +
             "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-            "&applyOptionsToContainers=1" +  
-            "&sort=" + 
-            Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING + 
+            "&applyOptionsToContainers=1" +
+            "&sort=" +
+            Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
             "&resolveNullBookmarkTitles=1" +
             "&maxResults=" + maxResults),
             defaultIndex, recentlyUsedTagsTitle);
 
       var mostUsedTagsItem = bmsvc.insertBookmark(placesFolder,
-        IO.newURI("place:folder=" + tagRoot + 
+        IO.newURI("place:folder=" + tagRoot +
             "&group=" + Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER +
             "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
             "&applyOptionsToContainers=1" +
-            "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_COUNT_DESCENDING + 
+            "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_COUNT_DESCENDING +
             "&resolveNullBookmarkTitles=1" +
             "&maxResults=" + maxResults),
             defaultIndex, mostUsedTagsTitle);
 
       var mostVisitedSitesItem = bmsvc.insertBookmark(placesFolder,
-        IO.newURI("place:queryType=" + 
+        IO.newURI("place:queryType=" +
             Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
-            "&sort=" + 
-            Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + 
+            "&sort=" +
+            Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
             "&maxResults=" + maxResults),
             defaultIndex, mostVisitedSitesTitle);
     }
   }
   
   try {
     bmsvc.runInBatchMode(callback, null);
   } finally {
@@ -1159,17 +1161,17 @@ function delayedStartup()
     Components.utils.reportError("Failed to init microsummary service:\n" + ex);
   }
 
   // Initialize the content pref event sink and the text zoom setting.
   // We do this before the session restore service gets initialized so we can
   // apply text zoom settings to tabs restored by the session restore service.
   try {
     ContentPrefSink.init();
-    TextZoom.init();
+    FullZoom.init();
   }
   catch(ex) {
     Components.utils.reportError("Failed to init content pref service:\n" + ex);
   }
 
 #ifdef XP_WIN
   // For Vista, flip the default download folder pref once from Desktop to Downloads
   // on new profiles.
@@ -1197,26 +1199,22 @@ function delayedStartup()
       ss.init(window);
     } catch(ex) {
       dump("nsSessionStore could not be initialized: " + ex + "\n");
     }
   }
 
   // bookmark-all-tabs command
   gBookmarkAllTabsHandler = new BookmarkAllTabsHandler();
-  
-  // Prevent chrome-spoofing popups from forging our chrome, by adding a
-  // notification box entry in cases of chromeless popups.
-  checkForChromelessWindow();
 }
 
 function BrowserShutdown()
 {
   try {
-    TextZoom.destroy();
+    FullZoom.destroy();
     ContentPrefSink.destroy();
   }
   catch(ex) {
     Components.utils.reportError(ex);
   }
 
   var os = Components.classes["@mozilla.org/observer-service;1"]
     .getService(Components.interfaces.nsIObserverService);
@@ -1283,17 +1281,17 @@ function BrowserShutdown()
 // nonBrowserWindowShutdown() are used for non-browser windows in
 // macBrowserOverlay
 function nonBrowserWindowStartup()
 {
   // Disable inappropriate commands / submenus
   var disabledItems = ['cmd_newNavigatorTab', 'Browser:SavePage', 'Browser:SendLink',
                        'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain', 'viewToolbarsMenu',
                        'cmd_toggleTaskbar', 'viewSidebarMenuMenu', 'Browser:Reload', 'Browser:ReloadSkipCache',
-                       'viewTextZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
+                       'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
                        'viewHistorySidebar', 'Browser:AddBookmarkAs', 'View:PageInfo', 'Tasks:InspectPage'];
   var element;
 
   for (var id in disabledItems)
   {
     element = document.getElementById(disabledItems[id]);
     if (element)
       element.setAttribute("disabled", "true");
@@ -2228,16 +2226,26 @@ function PageProxyClickHandler(aEvent)
     case 1:
       if (gPrefService.getBoolPref("middlemouse.paste"))
         middleMousePaste(aEvent);
       break;
   }
   return true;
 }
 
+function URLBarOnInput(evt)
+{
+  gBrowser.userTypedValue = gURLBar.value;
+  
+  // If the user is interacting with the url bar, get rid of the identity popup
+  var ih = getIdentityHandler();
+  if(ih._identityPopup)
+    ih._identityPopup.hidePopup();
+}
+
 function URLBarOnDragOver(evt)
 {
   nsDragAndDrop.dragOver(evt, urlbarObserver);
 }
 
 function URLBarOnDrop(evt)
 {
   nsDragAndDrop.drop(evt, urlbarObserver);
@@ -3843,16 +3851,17 @@ nsBrowserStatusHandler.prototype =
     }
 
     if (setHost && this._host)
       this.securityButton.setAttribute("label", this._host);
     else
       this.securityButton.removeAttribute("label");
 
     this.securityButton.setAttribute("tooltiptext", this._tooltipText);
+    getIdentityHandler().checkIdentity(this._state, this._host);
   },
 
   // simulate all change notifications after switching tabs
   onUpdateCurrentBrowser : function(aStateFlags, aStatus, aMessage, aTotalProgress)
   {
     var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
     var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP;
     // use a pseudo-object instead of a (potentially non-existing) channel for getting
@@ -3937,16 +3946,20 @@ nsBrowserAccess.prototype =
     var referrer = null;
     var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
 
     if (isExternal && aURI && aURI.schemeIs("chrome")) {
       dump("use -chrome command-line option to load external chrome urls\n");
       return null;
     }
 
+    if (!gPrefService)
+      gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
+                               .getService(Components.interfaces.nsIPrefBranch2);
+
     var loadflags = isExternal ?
                        Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
                        Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
     var location;
     if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
       switch (aContext) {
         case Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL :
           aWhere = gPrefService.getIntPref("browser.link.open_external");
@@ -3972,16 +3985,18 @@ nsBrowserAccess.prototype =
             referrer =
                     Components.classes["@mozilla.org/network/io-service;1"]
                               .getService(Components.interfaces.nsIIOService)
                               .newURI(location, null, null);
           }
           newWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIWebNavigation)
                    .loadURI(url, loadflags, referrer, null, null);
+          if (!loadInBackground && isExternal)
+            newWindow.focus();
         } catch(e) {
         }
         break;
       default : // OPEN_CURRENTWINDOW or an illegal value
         try {
           if (aOpener) {
             newWindow = aOpener.top;
             location = aOpener.location;
@@ -5571,97 +5586,16 @@ BookmarkAllTabsHandler.prototype = {
   },
 
   // nsIDOMEventListener
   handleEvent: function(aEvent) {
     this._updateCommandState(aEvent.type == "TabClose");
   }
 };
 
-
-/**
- * Check the chromehidden attribute to see if the toolbar is hidden.  If so,
- * and if they haven't disabled the security.warn_chromeless_window.infobar
- * pref, show an infobar notification informing them of what's going on.  This
- * helps fight chrome spoofing on popups.  See bug 337344
- */
-function checkForChromelessWindow() {
-
-  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
-                        .getService(Components.interfaces.nsIPrefBranch);
-  
-  // true by default
-  if (!prefs.getBoolPref("browser.warn_chromeless_window.infobar"))
-    return;
-
-  if (document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1 ||
-      document.documentElement.getAttribute("chromehidden").indexOf("location") != -1) {
-    
-    var bundle_browser = document.getElementById("bundle_browser");
-    
-    // It's possible that something in the window.content.opener.location.path
-    // chain might be null.  Rather than chaining a ton of 99% pass null checks,
-    // though, let's try/catch in order to fail gracefully
-    try {
-      var messageString = bundle_browser.getFormattedString("chromelessWindow.warningMessage",
-                                                            [window.content.opener.location.host]);
-    } catch (ex) {
-        
-      // An exception here is not worth breaking our security warning, but is worth
-      // logging, since it shouldn't happen.
-      Components.utils.reportError(ex);
-      messageString = bundle_browser.getString("chromelessWindow.warningNoLocation");
-      
-    }
-
-    var notificationBox = gBrowser.getNotificationBox();
-    var notificationName = "chromeless-info";
-    if (notificationBox.getNotificationWithValue(notificationName)) {
-      Components.utils.reportError("Already have a chromeless-info notification!")
-      return;
-    }
-    
-    var buttons = [{
-      label: bundle_browser.getString("chromelessWindow.showToolbarsButton"),
-      accessKey: bundle_browser.getString("chromelessWindow.accessKey"),
-      popup: null,
-      callback: function() { return showToolbars(); }
-    }];
-
-    notificationBox.appendNotification(messageString,
-                                       notificationName,
-                                       "chrome://browser/skin/Info.png",
-                                       notificationBox.PRIORITY_INFO_HIGH,
-                                       buttons);
-  }
-}
-
-/**
- * Callback for "Show Toolbars" button in chromeless window notification box.
- * Resets visibility of the go button stack and url bar, and wipes the
- * chromehidden document attribute.
- */
-function showToolbars() {
-
-  // Unhide the chrome elements
-  document.documentElement.removeAttribute("chromehidden");
-  
-  // Undo the URLBar tweaks performed when the url bar was chromehidden
-  if (gURLBar) {
-    gURLBar.removeAttribute("readonly");
-    gURLBar.setAttribute("enablehistory", "true");
-  }
-  
-  var goButtonStack = document.getElementById("go-button-stack");
-  if (goButtonStack)
-    goButtonStack.removeAttribute("hidden");
-  
-  return false; // Dismiss the notification message
-}
-
 /**
  * Utility class to handle manipulations of the identity indicators in the UI
  */
 function IdentityHandler() {
   this._identityPopup = document.getElementById("identity-popup");
   this._identityBox = document.getElementById("identity-box");
   this._identityPopupContentBox = document.getElementById("identity-popup-content-box");
   this._identityPopupTitle = document.getElementById("identity-popup-title");
@@ -5691,17 +5625,17 @@ IdentityHandler.prototype = {
 
   // Mode strings used to control CSS display
   IDENTITY_MODE_IDENTIFIED       : "verifiedIdentity", // High-quality identity information
   IDENTITY_MODE_DOMAIN_VERIFIED  : "verifiedDomain",   // Minimal SSL CA-signed domain verification
   IDENTITY_MODE_UNKNOWN          : "unknownIdentity",  // No trusted identity information
 
   // Cache the most recently seen SSLStatus and URI to prevent unnecessary updates
   _lastStatus : null,
-  _lastURI : null,
+  _lastHost : null,
 
   /**
    * Handler for mouseclicks on the "Tell me more about this website" link text
    * in the "identity-popup" panel.
    */
   handleMoreInfoClick : function(event) {
     if (event.button == 0) {
       displaySecurityInfo();
@@ -5739,37 +5673,27 @@ IdentityHandler.prototype = {
     result.caOrg =  cert.issuerOrganization || cert.issuerCommonName;
     
     return result;
   },
   
   /**
    * Determine the identity of the page being displayed by examining its SSL cert
    * (if available) and, if necessary, update the UI to reflect this.  Intended to
-   * be called by an nsIWebProgressListener.
-   *
-   * @param nsIWebProgress webProgress
-   * @param nsIRequest request
+   * be called by onSecurityChange
+   * 
    * @param PRUint32 state
+   * @param AUTF8String host
    */
-  checkIdentity : function(state) {
-    var currentURI = gBrowser.currentURI;
-    if (currentURI.schemeIs("http") && this._lastURI.schemeIs("http"))
-      return;
-
+  checkIdentity : function(state, host) {
     var currentStatus = gBrowser.securityUI
                                 .QueryInterface(Components.interfaces.nsISSLStatusProvider)
                                 .SSLStatus;
-    if (currentStatus == this._lastStatus && currentURI == this._lastURI) {
-      // No need to update, this is a no-op check
-      return;
-    }
-
     this._lastStatus = currentStatus;
-    this._lastURI = currentURI;
+    this._lastHost = host;
     
     if (state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL)
       this.setMode(this.IDENTITY_MODE_IDENTIFIED);
     else if (state & Components.interfaces.nsIWebProgressListener.STATE_SECURE_HIGH)
       this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
     else
       this.setMode(this.IDENTITY_MODE_UNKNOWN);
   },
@@ -5797,17 +5721,17 @@ IdentityHandler.prototype = {
     if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
       var iData = this.getIdentityData();     
       
       // It would be sort of nice to use the CN= field in the cert, since that's
       // typically what we want here, but thanks to x509 certs being extensible,
       // it's not the only place you have to check, there can be more than one domain,
       // et cetera, ad nauseum.  We know the cert is valid for location.host, so
       // let's just use that, it's what the status bar does too.
-      var icon_label = this._lastURI.host; 
+      var icon_label = this._lastHost; 
       var tooltip = this._stringBundle.getFormattedString("identity.identified.verifier",
                                                           [iData.caOrg]);
     }
     else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
       // If it's identified, then we can populate the dialog with credentials
       iData = this.getIdentityData();  
       tooltip = this._stringBundle.getFormattedString("identity.identified.verifier",
                                                       [iData.caOrg]);
@@ -5845,17 +5769,17 @@ IdentityHandler.prototype = {
     
     // Initialize the optional strings to empty values
     var supplemental = "";
     var verifier = "";
       
     if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
       var iData = this.getIdentityData();
 
-      var body = this._lastURI.host;     
+      var body = this._lastHost;     
       verifier = this._stringBundle.getFormattedString("identity.identified.verifier",
                                                        [iData.caOrg]);
       supplemental = this._stringBundle.getString("identity.domainverified.supplemental");
     }
     else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
       // If it's identified, then we can populate the dialog with credentials
       iData = this.getIdentityData();
 
@@ -5892,16 +5816,20 @@ IdentityHandler.prototype = {
   handleIdentityClick : function(event) {
     if (event.button != 0)
       return; // We only want left-clicks
         
     // Make sure that the display:none style we set in xul is removed now that
     // the popup is actually needed
     this._identityPopup.hidden = false;
     
+    // Tell the popup to consume dismiss clicks, to avoid bug 395314
+    this._identityPopup.popupBoxObject
+        .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
+    
     // Update the popup strings
     this.setPopupMessages(this._identityBox.className);
     
     // Now open the popup, anchored off the primary chrome element
     this._identityPopup.openPopup(this._identityBox, 'after_start');
   }
 };
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -23,16 +23,17 @@
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Blake Ross <blake@cs.stanford.edu>
 #   David Hyatt <hyatt@mozilla.org>
 #   Joe Hewitt <hewitt@netscape.com>
 #   Pierre Chanial <chanial@noos.fr>
 #   Dean Tessman <dean_tessman@hotmail.com>
+#   Johnathan Nightingale <johnath@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -52,17 +53,17 @@
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
 
 # All DTD information is stored in a separate file so that it can be shared by
 # hiddenWindow.xul.
 #include browser-doctype.inc
- 
+
 <window id="main-window"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="BrowserStartup()" onunload="BrowserShutdown()" onclose="return WindowIsClosing();"
         contenttitlesetting="true"
         title="&mainWindow.title;"
         titlemodifier="&mainWindow.title;"
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
@@ -133,25 +134,53 @@
     <popup id="contentAreaContextMenu"
            onpopupshowing="if (event.target != this) return true; gContextMenu = new nsContextMenu(this, window.getBrowser()); return gContextMenu.shouldDisplay;"
            onpopuphiding="if (event.target == this) { gContextMenu = null; }">
 #include browser-context.inc
     </popup>
 
     <popup id="placesContext"/>
 
+    <!-- Popup for site identity information -->
+    <panel id="identity-popup" position="after_start" hidden="true" noautofocus="true">
+      <hbox id="identity-popup-container" align="top">
+        <image id="identity-popup-icon"/>
+        <vbox id="identity-popup-content-box">
+          <!-- Title Bar -->
+          <label id="identity-popup-title"/>
+          <!-- Content area -->
+          <description id="identity-popup-content"/>
+          <description id="identity-popup-content-supplemental"/>
+          <description id="identity-popup-content-verifier"/>
+          <hbox id="identity-popup-encryption" flex="1">
+            <vbox>
+              <image id="identity-popup-encryption-icon"/>
+              <spacer flex="1"/>
+            </vbox>
+            <description id="identity-popup-encryption-label" flex="1"/>
+          </hbox>
+          <spacer flex="1"/>
+          <!-- Footer link to page info -->
+          <label id="identity-popup-more-info-link"
+                 class="text-link plain"
+                 value="&identity.moreInfoLinkText;"
+                 onclick="getIdentityHandler().handleMoreInfoClick(event);"/>
+        </vbox>
+      </hbox>
+    </panel>
+
     <tooltip id="urlTooltip">
       <label crop="center" flex="1"/>
     </tooltip>
   </popupset>
 
   <!-- bookmarks toolbar tooltip -->
   <tooltip id="btTooltip" noautohide="true"
            onpopupshowing="return BookmarksEventHandler.fillInBTTooltip(document.tooltipNode)">
-    <vbox id="btTooltipTextBox" flex="1">  
+    <vbox id="btTooltipTextBox" flex="1">
       <label id="btTitleText" />
       <label id="btUrlText" />
     </vbox>
   </tooltip>
 
   <toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
            defaultmode="icons">
     <!-- Menu -->
@@ -178,36 +207,36 @@
                      context="backMenu"
                      tooltiptext="&backButton.tooltip;">
         <observes element="Browser:Back" attribute="disabled"/>
         <menupopup context=""
                    onpopupshowing="BrowserBackMenu(event);"
                    oncommand="gotoHistoryIndex(event); event.stopPropagation();"
                    onclick="checkForMiddleClick(this, event);"/>
       </toolbarbutton>
-    
+
       <toolbarbutton id="forward-button" type="menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      chromedir="&locale.dir;"
                      label="&forwardCmd.label;"
                      oncommand="BrowserForward(event)"
                      onclick="checkForMiddleClick(this, event);"
                      context="forwardMenu"
                      tooltiptext="&forwardButton.tooltip;">
         <observes element="Browser:Forward" attribute="disabled"/>
         <menupopup context=""
                    onpopupshowing="BrowserForwardMenu(event);"
                    oncommand="gotoHistoryIndex(event); event.stopPropagation()"
                    onclick="checkForMiddleClick(this, event);"/>
       </toolbarbutton>
-    
+
       <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&reloadCmd.label;"
                      command="Browser:Reload"
                      tooltiptext="&reloadButton.tooltip;"/>
-                    
+
       <toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&stopCmd.label;"
                      command="Browser:Stop"
                      tooltiptext="&stopButton.tooltip;"/>
 
       <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&homeButton.label;"
                      ondragover="nsDragAndDrop.dragOver(event, homeButtonObserver);"
@@ -216,53 +245,58 @@
                      onclick="BrowserHomeClick(event);"/>
 
       <toolbaritem id="urlbar-container" align="center" flex="400" persist="width"
                    title="&locationItem.title;" class="chromeclass-location">
         <hbox id="urlbar-button-box" flex="1">
           <textbox id="urlbar" flex="1"
                    chromedir="&locale.dir;"
                    type="autocomplete"
-                   autocompletesearch="history" 
+                   autocompletesearch="history"
                    autocompletepopup="PopupAutoComplete"
                    completeselectedindex="true"
                    tabscrolling="true"
                    showcommentcolumn="true"
-                   showimagecolumn="true" 
+                   showimagecolumn="true"
                    enablehistory="true"
                    maxrows="10"
                    newlines="stripsurroundingwhitespace"
-                   oninput="gBrowser.userTypedValue = this.value"
+                   oninput="URLBarOnInput(event);"
                    ontextentered="return handleURLBarCommand(param);"
                    ontextreverted="return handleURLBarRevert();">
-            <deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
-              <image id="page-proxy-button"
-                     ondraggesture="PageProxyDragGesture(event);"
-                     tooltiptext="&proxyIcon.tooltip;"/>
-              <image id="page-proxy-favicon" validate="never"
-                     ondraggesture="PageProxyDragGesture(event);"
-                     onload="this.parentNode.selectedIndex = 1;
-                             event.stopPropagation();"
-                     onerror="this.removeAttribute('src');
-                              this.parentNode.selectedIndex = 0;"
-                     tooltiptext="&proxyIcon.tooltip;"/>
-            </deck>
+              <!-- Use onclick instead of normal popup= syntax since the popup
+                   code fires onmousedown, and hence eats our favicon drag events -->
+              <box id="identity-box" align="center" 
+                   onclick="getIdentityHandler().handleIdentityClick(event);">
+              <deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
+                <image id="page-proxy-button"
+                       ondraggesture="PageProxyDragGesture(event);"
+                       tooltiptext="&proxyIcon.tooltip;"/>
+                <image id="page-proxy-favicon" validate="never"
+                       ondraggesture="PageProxyDragGesture(event);"
+                       onload="this.parentNode.selectedIndex = 1;
+                               event.stopPropagation();"
+                       onerror="this.removeAttribute('src');
+                                this.parentNode.selectedIndex = 0;"
+                       tooltiptext="&proxyIcon.tooltip;"/>
+              </deck>
+              <label id="identity-icon-label"/>
+            </box>
             <hbox id="urlbar-icons">
               <button type="menu"
                       style="-moz-user-focus: none"
                       class="plain"
                       id="feed-button"
                       chromedir="&locale.dir;"
                       onclick="return FeedHandler.onFeedButtonClick(event);">
                 <menupopup position="after_end"
                            onpopupshowing="return FeedHandler.buildFeedList(this);"
                            oncommand="return FeedHandler.subscribeToFeed(null, event);"
                            onclick="checkForMiddleClick(this, event);"/>
               </button>
-              <image id="lock-icon" onclick="if (event.button == 0) displaySecurityInfo(); event.stopPropagation();"/>
 #ifdef MOZ_SAFE_BROWSING
               <image id="safebrowsing-urlbar-icon" tooltiptext="&safeb.urlbaricon.tooltip;"
                      level="safe"
                      onclick="goDoCommand('safebrowsing-show-warning')"/>
 #endif
             </hbox>
           </textbox>
           <stack id="go-button-stack" class="endcap">
@@ -277,34 +311,34 @@
                              ondragdrop="nsDragAndDrop.drop(event, goButtonObserver);"
                              ondragexit="nsDragAndDrop.dragExit(event, goButtonObserver);"
                              tooltiptext="&goEndCap.tooltip;"/>
             </hbox>
           </stack>
         </hbox>
       </toolbaritem>
 
-      <toolbaritem id="search-container" title="&searchItem.title;" 
+      <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;"
                    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"/>
       </toolbaritem>
 
       <toolbaritem flex="1" id="personal-bookmarks" title="&bookmarksItem.title;">
          <hbox id="bookmarksBarContent" flex="1" type="places"
-               context="placesContext" asyncinit="true" 
+               context="placesContext" asyncinit="true"
                onclick="BookmarksEventHandler.onClick(event);"
                oncommand="BookmarksEventHandler.onCommand(event);"
                onpopupshowing="BookmarksEventHandler.onPopupShowing(event);"
                ondragexit="PlacesMenuDNDController.onDragExit(event);"
                tooltip="btTooltip"/>
       </toolbaritem>
 
         <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
@@ -328,17 +362,17 @@
                        ondragexit="nsDragAndDrop.dragExit(event, bookmarksButtonObserver);"/>
 
         <toolbarbutton id="new-tab-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&tabCmd.label;"
                        command="cmd_newNavigatorTab"
                        tooltiptext="&newTabButton.tooltip;"
                        ondragover="nsDragAndDrop.dragOver(event, newTabButtonObserver);"
                        ondragdrop="nsDragAndDrop.drop(event, newTabButtonObserver);"
-                       ondragexit="nsDragAndDrop.dragExit(event, newTabButtonObserver);"/>         
+                       ondragexit="nsDragAndDrop.dragExit(event, newTabButtonObserver);"/>
 
         <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&newNavigatorCmd.label;"
                        command="key_newNavigator"
                        tooltiptext="&newWindowButton.tooltip;"
                        ondragover="nsDragAndDrop.dragOver(event, newWindowButtonObserver);"
                        ondragdrop="nsDragAndDrop.drop(event, newWindowButtonObserver);"
                        ondragexit="nsDragAndDrop.dragExit(event, newWindowButtonObserver);"/>
@@ -357,17 +391,17 @@
                        label="&pasteCmd.label;"
                        command="cmd_paste"
                        tooltiptext="&pasteButton.tooltip;"/>
 
     </toolbarpalette>
 
     <toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
              toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
-             fullscreentoolbar="true" mode="icons" 
+             fullscreentoolbar="true" mode="icons"
              customizable="true"
 #ifdef XP_MACOSX
              defaultset="back-button,forward-button,reload-button,stop-button,home-button,urlbar-container,splitter,search-container,throbber-box"
 #else
              defaultset="back-button,forward-button,reload-button,stop-button,home-button,urlbar-container,splitter,search-container,fullscreenflex,window-controls"
 #endif
              context="toolbar-context-menu">
 #ifndef XP_MACOSX
@@ -382,38 +416,38 @@
                        oncommand="BrowserFullScreen();"/>
 
         <toolbarbutton id="close-button" class="toolbarbutton-1"
                        tooltiptext="&fullScreenClose.tooltip;"
                        oncommand="BrowserTryToCloseWindow();"/>
       </hbox>
 #endif
     </toolbar>
- 
+
     <toolbarset id="customToolbars" context="toolbar-context-menu"/>
 
-    <toolbar id="PersonalToolbar" mode="icons"  iconsize="small" 
+    <toolbar id="PersonalToolbar" mode="icons"  iconsize="small"
              class="chromeclass-directories"
-             context="toolbar-context-menu" 
+             context="toolbar-context-menu"
              defaultset="bookmarksBarShowPlaces,personal-bookmarks"
              toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
              customizable="true"/>
   </toolbox>
-  
+
   <hbox flex="1" id="browser">
     <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
       <sidebarheader align="center">
         <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
         <image id="sidebar-throbber"/>
         <toolbarbutton class="tabs-closebutton" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/>
-      </sidebarheader>        
+      </sidebarheader>
       <browser id="sidebar" flex="1" autoscroll="false"
                 style="min-width: 14em; width: 18em; max-width: 36em;"/>
-    </vbox>    
-    
+    </vbox>
+
     <splitter id="sidebar-splitter" class="chromeclass-extrachrome" hidden="true"/>
     <vbox id="appcontent" flex="1">
       <tabbrowser id="content" disablehistory="true"
                   flex="1" contenttooltip="aHTMLTooltip"
                   contentcontextmenu="contentAreaContextMenu"
                   onnewtab="BrowserOpenTab();"
                   autocompletepopup="PopupAutoComplete"
                   ondragdrop="nsDragAndDrop.drop(event, contentAreaDNDObserver);"
@@ -425,30 +459,30 @@
     <iframe id="customizeToolbarSheetIFrame"
             style="&dialog.style;"
             src="chrome://global/content/customizeToolbar.xul"
             hidden="true"/>
   </panel>
 #endif
 
   <findbar browserid="content" id="FindToolbar"/>
-  
+
   <statusbar class="chromeclass-status" id="status-bar"
              ondragdrop="nsDragAndDrop.drop(event, contentAreaDNDObserver);">
     <statusbarpanel id="statusbar-display" label="" flex="1"/>
     <statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
       <progressmeter class="progressmeter-statusbar" id="statusbar-icon" mode="normal" value="0"/>
     </statusbarpanel>
     <statusbarpanel id="security-button" class="statusbarpanel-iconic-text"
                     ondblclick="if (event.button == 0) displaySecurityInfo();"/>
-    <statusbarpanel id="page-report-button" type="menu" 
-                    class="statusbarpanel-menu-iconic" 
+    <statusbarpanel id="page-report-button" type="menu"
+                    class="statusbarpanel-menu-iconic"
                     tooltiptext="&pageReportIcon.tooltip;">
       <menupopup onpopupshowing="gPopupBlockerObserver.fillPopupList(event);">
         <menuitem observes="blockedPopupAllowSite"/>
         <menuitem observes="blockedPopupEditSettings"/>
         <menuitem observes="blockedPopupDontShowMessage"/>
         <menuseparator observes="blockedPopupsSeparator"/>
       </menupopup>
     </statusbarpanel>
   </statusbar>
 </window>
-  
+
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -54,17 +54,17 @@
 <?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
 #endif
 
 <window id="main-window"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   windowtype="Browser:page-info"
   onload="onLoadPageInfo()"
   onunload="onUnloadPageInfo()"
-  xmlns:xhtml="http://www.w3.org/1999/xhtml">
+  xmlns:xhtml="http://www.w3.org/1999/xhtml"
   align="stretch"
   screenX="10" screenY="10"
   width="&pageInfoWindow.width;" height="&pageInfoWindow.height;"
   persist="screenX screenY width height sizemode">
 
   <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
   <script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
   <script type="application/x-javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1694,32 +1694,36 @@
 
       <method name="onDragOver">
         <parameter name="aEvent"/>
         <parameter name="aFlavour"/>
         <parameter name="aDragSession"/>
         <body>
           <![CDATA[
             var tabStrip = this.mTabContainer.mTabstrip;
+            var ltr = (window.getComputedStyle(this.parentNode, null).direction
+                       == "ltr");
 
             // autoscroll the tab strip if we drag over the scroll
             // buttons, even if we aren't dragging a tab, but then
             // return to avoid drawing the drop indicator
             var pixelsToScroll = 0;
-
-            var targetAnonid = aEvent.originalTarget.getAttribute("anonid");
-            if (targetAnonid == "scrollbutton-up") {
-              pixelsToScroll = tabStrip.scrollIncrement * -1;
-              tabStrip.scrollByPixels(pixelsToScroll);
-            }
-            else if (targetAnonid == "scrollbutton-down" || 
-                     (targetAnonid == "alltabs-button" && 
-                      this.mTabContainer.getAttribute("overflow") == "true")) {
-              pixelsToScroll = tabStrip.scrollIncrement;
-              tabStrip.scrollByPixels(pixelsToScroll);
+            if (this.mTabContainer.getAttribute("overflow") == "true") {
+              var targetAnonid = aEvent.originalTarget.getAttribute("anonid");
+              switch (targetAnonid) {
+                case "scrollbutton-up":
+                  pixelsToScroll = tabStrip.scrollIncrement * -1;
+                  break;
+                case "scrollbutton-down":
+                case "alltabs-button":
+                  pixelsToScroll = tabStrip.scrollIncrement;
+                  break;
+              }
+              if (pixelsToScroll)
+                tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll);
             }
 
             var isTabDrag = (aDragSession.sourceNode && 
                              aDragSession.sourceNode.parentNode == this.mTabContainer);
             if (!isTabDrag && aEvent.target.localName == "tab") {
               if (!this.mDragTime) 
                 this.mDragTime = Date.now();
               if (Date.now() >= this.mDragTime + this.mDragOverDelay)
@@ -1737,19 +1741,20 @@
             // 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);
+            if (!ltr)
+              [minMargin, maxMargin] = [this.boxObject.width - maxMargin,
+                                        this.boxObject.width - minMargin];
             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
               newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
             }
             else {
               if (newIndex == this.mTabs.length) {
                 tabBoxObject =  this.mTabs[newIndex-1].boxObject;
@@ -1770,20 +1775,17 @@
               }
               // 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';
+            ind.style.MozMarginStart = newMargin + 'px';
 
             ib.collapsed = !aDragSession.canDrop;
           ]]>
         </body>
       </method>
 
       <method name="onDrop">
         <parameter name="aEvent"/>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -33,325 +33,93 @@
 # 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 *****
 
-<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
-          xmlns:html="http://www.w3.org/1999/xhtml"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
+<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl">
 
   <binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
-    <content sizetopopup="pref">
-      <xul:hbox class="autocomplete-textbox-container" flex="1">
-        <children includes="image|deck|stack">
-          <xul:image class="autocomplete-icon" allowevents="true"/>
-        </children>
-
-        <xul:stack flex="1" class="textbox-stack">
-          <xul:hbox anonid="textbox-input-box" class="textbox-input-box"
-                    flex="1" xbl:inherits="tooltiptext=inputtooltiptext">
-            <children/>
-            <html:input anonid="input" class="autocomplete-textbox textbox-input"
-                        flex="1" allowevents="true"
-                        xbl:inherits="tooltiptext=inputtooltiptext,onfocus,onblur,value,type,maxlength,disabled,size,readonly,userAction"/>
-          </xul:hbox>
-          <xul:hbox anonid="presentation-box" class="formatted-url" flex="1"
-                    onmousedown="focus();" hidden="true">
-            <xul:scrollbox anonid="presentation" class="formatted-url-contents" flex="1"
-                           onoverflow="_contentIsCropped = true;"
-                           onunderflow="_contentIsCropped = false;">
-              <xul:hbox anonid="prePath" class="formatted-url-prePath">
-                <xul:label anonid="protocol" class="formatted-url-protocol"/>
-                <xul:label anonid="subdomain" class="formatted-url-subdomain"/>
-                <xul:label anonid="domain" class="formatted-url-domain"/>
-                <xul:label anonid="port" class="formatted-url-port"/>
-              </xul:hbox>
-              <xul:label anonid="path" class="formatted-url-path"/>
-            </xul:scrollbox>
-            <xul:label anonid="overflow-ellipsis" class="formatted-url-ellipsis"
-                       value="&#8230;" hidden="true"/>
-          </xul:hbox>
-        </xul:stack>
-
-        <children includes="hbox"/>
-      </xul:hbox>
-
-      <xul:dropmarker anonid="historydropmarker" class="autocomplete-history-dropmarker"
-                      allowevents="true"
-                      xbl:inherits="open,enablehistory"/>
-
-      <xul:popupset anonid="popupset" class="autocomplete-result-popupset"/>
-    </content>
-
     <implementation implements="nsIObserver, nsIDOMEventListener">
       <constructor><![CDATA[
         this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
                                     .getService(Components.interfaces.nsIIOService);
         this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
                                 .getService(Components.interfaces.nsIPrefService)
                                 .getBranch("browser.urlbar.")
                                 .QueryInterface(Components.interfaces.nsIPrefBranch2);
 
         this._prefs.addObserver("", this, false);
-        this._hideProtocols = this._prefs.getCharPref("hideProtocols").split(" ");
-        this._animateBlend = this._prefs.getBoolPref("animateBlend");
         this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
         this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
         this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
 
-        this._inputBox = document.getAnonymousElementByAttribute(this, "anonid", "textbox-input-box");
-        this._presentationBox = document.getAnonymousElementByAttribute(this, "anonid", "presentation-box");
-        this._overflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "overflow-ellipsis");
-        this._prePath = document.getAnonymousElementByAttribute(this, "anonid", "prePath");
-        this._protocol = document.getAnonymousElementByAttribute(this, "anonid", "protocol");
-        this._subDomain = document.getAnonymousElementByAttribute(this, "anonid", "subdomain");
-        this._domain = document.getAnonymousElementByAttribute(this, "anonid", "domain");
-        this._port = document.getAnonymousElementByAttribute(this, "anonid", "port");
-        this._path = document.getAnonymousElementByAttribute(this, "anonid", "path");
         this._urlTooltip = document.getElementById("urlTooltip");
 
         this.inputField.controllers.insertControllerAt(0, this._copyCutController);
         this.inputField.addEventListener("mousedown", this, false);
-
-        this._blendingTimers = [];
+        this.inputField.addEventListener("mousemove", this, false);
+        this.inputField.addEventListener("mouseout", this, false);
       ]]></constructor>
 
       <destructor><![CDATA[
         this._prefs.removeObserver("", this);
         this._prefs = null;
         this._ioService = null;
-        this._tldService = null;
         this.inputField.controllers.removeController(this._copyCutController);
         this.inputField.removeEventListener("mousedown", this, false);
+        this.inputField.removeEventListener("mousemove", this, false);
+        this.inputField.removeEventListener("mouseout", this, false);
       ]]></destructor>
 
-      <!-- initially empty fields:
-        <field name="_uri"/>
-        <field name="_protocolHidden"/>
-        <field name="_focused"/>
-        <field name="_mouseover"/>
-        <field name="_tooltipTimer"/>
-        <field name="_tldService"/>
-        <field name="_formatted"/>
-      -->
-
-      <property name="plain" onget="return !this._formatted">
-        <setter><![CDATA[
-          this._formatted = !val;
-          while (this._blendingTimers.length)
-            clearTimeout(this._blendingTimers.pop());
-          if (val) {
-            this._inputBox.style.removeProperty("opacity");
-            this._presentationBox.hidden = true;
-          } else {
-            this._inputBox.style.setProperty("opacity", "0", "important");
-          }
-          this._presentationBox.style.removeProperty("opacity");
-          this._hideURLTooltip();
-          return val;
-        ]]></setter>
-      </property>
-
-      <property name="tldService" readonly="true">
-        <getter><![CDATA[
-          if (!this._tldService) {
-            this._tldService =
-              Components.classes["@mozilla.org/network/effective-tld-service;1"]
-                        .getService(Components.interfaces.nsIEffectiveTLDService);
-          }
-
-          return this._tldService;
-        ]]></getter>
-      </property>
-
-      <property name="_contentIsCropped"
-                onget="return !this._overflowEllipsis.hidden;"
-                onset="this._overflowEllipsis.hidden = !val; return val;"/>
-
       <property name="value"
                 onget="return this.inputField.value;">
         <setter><![CDATA[
           this.mIgnoreInput = true;
-          this._syncValue(val);
+
+          if (val != "") {
+            var uri;
+            try {
+              uri = this._ioService.newURI(val, null, null);
+            } catch(e) {}
+            if (uri) {
+              val = uri.spec;
+              try {
+                // try to decode as UTF-8
+                val = decodeURI(val);
+              } catch(e) {}
+            }
+          }
+          this.inputField.value = val;
+
           this.mIgnoreInput = false;
-          if (this._focused)
-            this.plain = true;
-          else if (!this._mouseover || !this.plain)
-            this._prettyView(false);
           var event = document.createEvent("Events");
           event.initEvent("ValueChange", true, true);
           this.inputField.dispatchEvent(event);
           return val;
         ]]></setter>
       </property>
 
-      <method name="_syncValue">
-        <parameter name="aValue"/>
+      <method name="_initURLTooltip">
         <body><![CDATA[
-          var value = aValue != null ? aValue : this.value;
-          if (value == "") {
-            this._uri = null;
-          } else {
-            try {
-              this._uri = this._ioService.newURI(value, null, null);
-              // next line throws if .host is not defined
-              this._uri.host;
-            } catch(e) {
-              this._uri = null;
-            }
-          }
-          if (!this._uri) {
-            this._contentIsCropped = false;
-            if (aValue != null)
-              this.inputField.value = aValue;
+          if (this.focused)
             return;
-          }
-
-          if (!this._focused || aValue != null) {
-            value = this._uri.spec;
-            try {
-              // try to decode as UTF-8
-              value = decodeURI(value);
-            } catch(e) {}
-            this.inputField.value = value;
-          }
-
-          this._protocol.setAttribute("value", this._uri.scheme + "://");
-          this._protocolHidden = this._hideProtocols.indexOf(this._uri.scheme) > -1;
-
-          var host = this._uri.host;
-          if (host) {
-            var subdomain;
-            var port = (this._uri.port > -1) ? ":" + this._uri.port : "";
-            if (this._uri.hostPort[0] == "[") {
-              // IPv6 address
-              subdomain = "[";
-              port = "]" + port;
-            }
-            else if (0 && !/^[.0-9]+$/.test(host)) {
-              //XXX subdomain detection disabled (bug 386727)
-              //XXX subdomain detection disabled for IP addresses (bug 364129)
-
-              // getEffectiveTLDLength might convert our host and return a misleading length.
-              // To avoid this, pass the ASCII host, count the dots of its effective TLD
-              // and use that number to operate on our actual host.
-
-              var asciiHost = this._uri.asciiHost;
-              var domainSegments = host.split(".");
-              var cSubdomain = domainSegments.length -
-                               asciiHost.slice(asciiHost.length -
-                                               this.tldService.getEffectiveTLDLength(asciiHost))
-                                        .split(".").length - 1;
-              if (cSubdomain > 0) {
-                host = domainSegments;
-                subdomain = host.splice(0, cSubdomain).join(".") + ".";
-                host = host.join(".");
-              }
-            } else {
-              subdomain = "";
-            }
-            this._subDomain.setAttribute("value", subdomain);
-            this._domain.setAttribute("value", host);
-            this._port.setAttribute("value", port);
-          } else {
-            this._subDomain.removeAttribute("value");
-            this._domain.removeAttribute("value");
-            this._port.removeAttribute("value");
-          }
-
-          var path = this._uri.path;
-          try {
-            // try to decode as UTF-8
-            path = decodeURI(path);
-          } catch(e) {}
-          this._path.setAttribute("value", path);
-        ]]></body>
-      </method>
-
-      <method name="_initPrettyView">
-        <body><![CDATA[
-          this._plain = false;
-          this._protocol.hidden = false;
-          this._presentationBox.hidden = false;
-          this._prePath.width = "";
-          if (this._protocolHidden) {
-            this._prePath.width = this._prePath.boxObject.width;
-            this._protocol.hidden = true;
-          }
-        ]]></body>
-      </method>
-
-      <method name="_prettyView">
-        <parameter name="aAnimateBlend"/>
-        <body><![CDATA[
-          if (!this._uri) {
-            this.plain = true;
-            return;
-          }
-
-          if (!aAnimateBlend || !this._animateBlend) {
-            this._initPrettyView();
-            this.plain = false;
-            return;
-          }
-
-          const INITIAL_DELAY = 150;
-          const FRAME_LENGTH = 60;
-          const DECLINATION_REL = .2;
-          const DECLINATION_ABS = .15;
-
-          var inputBox = this._inputBox;
-          var presentationBox = this._presentationBox;
-          var self = this;
-          var opacity = parseFloat(document.defaultView.getComputedStyle(inputBox, null).opacity);
-          var delay = INITIAL_DELAY;
-
-          function processFrame(opacity, init) {
-            inputBox.style.setProperty("opacity", opacity, "important");
-            presentationBox.style.setProperty("opacity", 1-opacity, "important");
-            if (init)
-              self._initPrettyView();
-            if (!opacity)
-              self.plain = false;
-          }
-
-          while (opacity > 0) {
-            opacity -= opacity * DECLINATION_REL + DECLINATION_ABS;
-            if (opacity < 0)
-              opacity = 0;
-            this._blendingTimers.push(setTimeout(processFrame, delay, opacity, delay == INITIAL_DELAY));
-            delay += FRAME_LENGTH;
-          }
-        ]]></body>
-      </method>
-
-      <method name="_initURLTooltip">
-        <parameter name="aCallback"/>
-        <parameter name="aObject"/>
-        <parameter name="aCrop"/>
-        <body><![CDATA[
           if (this._tooltipTimer)
             clearTimeout(this._tooltipTimer);
-          this._tooltipTimer = setTimeout(function(self) {
+          this._tooltipTimer = setTimeout(function (self) {
             self._tooltipTimer = 0;
-            var tooltipText = aCallback.apply(aObject);
-            if (tooltipText) {
-              var label = self._urlTooltip.firstChild;
-              label.value = tooltipText;
-              label.crop = aCrop || "center";
-              var bO = self.boxObject;
-              self._urlTooltip.maxWidth = bO.width;
-              self._urlTooltip.showPopup(self, bO.screenX, bO.screenY + bO.height, "tooltip");
-            }
-          }, 400, this);
+            var label = self._urlTooltip.firstChild;
+            label.value = self.value;
+            var bO = self.boxObject;
+            self._urlTooltip.maxWidth = bO.width;
+            self._urlTooltip.showPopup(self, bO.screenX, bO.screenY + bO.height, "tooltip");
+          }, 700, this);
         ]]></body>
       </method>
 
       <method name="_hideURLTooltip">
         <body><![CDATA[
           if (this._tooltipTimer) {
             clearTimeout(this._tooltipTimer);
             this._tooltipTimer = 0;
@@ -406,105 +174,52 @@
 
       <method name="observe">
         <parameter name="aSubject"/>
         <parameter name="aTopic"/>
         <parameter name="aData"/>
         <body><![CDATA[
           if (aTopic == "nsPref:changed") {
             switch(aData) {
-              case "hideProtocols":
-                this._hideProtocols = this._prefs.getCharPref(aData).split(" ");
-                this._syncValue();
-                if (!this.plain)
-                  this._prettyView(false);
-                break;
               case "clickSelectsAll":
               case "doubleClickSelectsAll":
                 this[aData] = this._prefs.getBoolPref(aData);
                 break;
               case "autoFill":
                 this.completeDefaultIndex = this._prefs.getBoolPref(aData);
                 break;
-              case "animateBlend":
-                this._animateBlend = this._prefs.getBoolPref(aData);
-                break;
             }
           }
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
-          if (aEvent.type == "mousedown" &&
-              aEvent.button == 0 && aEvent.detail == 2 &&
-              this.doubleClickSelectsAll) {
-            this.editor.selectAll();
-            aEvent.preventDefault();
+          switch (aEvent.type) {
+            case "mousedown":
+              if (this.doubleClickSelectsAll &&
+                  aEvent.button == 0 && aEvent.detail == 2) {
+                this.editor.selectAll();
+                aEvent.preventDefault();
+              }
+              break;
+            case "mousemove":
+              this._initURLTooltip();
+              break;
+            case "mouseout":
+              this._hideURLTooltip();
+              break;
           }
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
-      <handler event="input"
-               action="this._syncValue();"/>
-
-      <handler event="mousemove"><![CDATA[
-        if (!this._focused && this._contentIsCropped)
-          this._initURLTooltip(function() {
-            return this.plain ? this.value : null;
-          }, this, "start");
-      ]]></handler>
-
-      <handler event="mouseover"><![CDATA[
-        if (this._mouseover)
-          return;
-        if (!this.plain) {
-          // do nothing if we're over the favicon, history dropmarker et al
-          var pBO = this._presentationBox.boxObject;
-          if (event.screenX < pBO.screenX || event.screenX > pBO.screenX + pBO.width)
-            return;
-        }
-        this._mouseover = true;
-        setTimeout(function(self) {
-          if (self._mouseover) {
-            self.plain = true;
-            if (!self._focused && self._contentIsCropped)
-              self._initURLTooltip(function() {
-                return this.plain ? this.value : null;
-              }, self, "start");
-          }
-        }, 60, this);
-      ]]></handler>
-
-      <handler event="mouseout" phase="target"><![CDATA[
-        this._mouseover = false;
-        if (!this._focused && this.plain)
-          this._prettyView(true);
-        else
-          this._hideURLTooltip();
-      ]]></handler>
-
-      <handler event="focus" phase="capturing"><![CDATA[
-        if (!this._focused) {
-          this._focused = true;
-          this.plain = true;
-        }
-      ]]></handler>
-
-      <handler event="blur" phase="capturing"><![CDATA[
-        if (this._focused && !this._dontBlur) {
-          this._focused = false;
-          this._syncValue();
-          if (!this._mouseover)
-            this._prettyView(true);
-        }
-      ]]></handler>
+      <handler event="focus" phase="capturing" action="this._hideURLTooltip();"/>
     </handlers>
 
   </binding>
 
   <binding id="urlbar-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup">
     <implementation>
       <method name="onPopupClick">
         <parameter name="aEvent"/>
--- a/browser/components/migration/src/nsIEProfileMigrator.cpp
+++ b/browser/components/migration/src/nsIEProfileMigrator.cpp
@@ -1527,29 +1527,54 @@ nsIEProfileMigrator::CopyPreferences(PRB
 
 /* Fetch and translate the current user's cookies.
    Return true if successful. */
 nsresult
 nsIEProfileMigrator::CopyCookies(PRBool aReplace) 
 {
   // IE cookies are stored in files named <username>@domain[n].txt
   // (in <username>'s Cookies folder. isn't the naming redundant?)
-  PRBool rv = NS_OK;
+  nsresult rv = NS_OK;
 
   nsCOMPtr<nsIFile> cookiesDir;
   nsCOMPtr<nsISimpleEnumerator> cookieFiles;
 
   nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
   if (!cookieManager)
     return NS_ERROR_FAILURE;
 
   // find the cookies directory
   NS_GetSpecialDirectory(NS_WIN_COOKIES_DIR, getter_AddRefs(cookiesDir));
-  if (cookiesDir)
-    cookiesDir->GetDirectoryEntries(getter_AddRefs(cookieFiles));
+  if (!cookiesDir)
+    return NS_ERROR_FAILURE;
+
+  // Check for Vista's UAC, if so, tack on a "Low" sub dir
+  nsCOMPtr<nsIWindowsRegKey> regKey =
+    do_CreateInstance("@mozilla.org/windows-registry-key;1");
+  if (regKey) {
+    NS_NAMED_LITERAL_STRING(regPath,"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
+    if (NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+                                  regPath,
+                                  nsIWindowsRegKey::ACCESS_QUERY_VALUE))) {
+      PRUint32 value;
+      if (NS_SUCCEEDED(regKey->ReadIntValue(NS_LITERAL_STRING("EnableLUA"),
+                                    &value)) &&
+          value == 1) {
+          nsAutoString dir;
+          // For cases where we are running under protected mode, check
+          // cookiesDir for the Low sub directory. (Simpler than using
+          // process token calls to check our Vista integrity level.)
+          cookiesDir->GetLeafName(dir);
+          if (!dir.EqualsLiteral("Low"))
+            cookiesDir->Append(NS_LITERAL_STRING("Low"));
+      }
+    }
+  }
+
+  cookiesDir->GetDirectoryEntries(getter_AddRefs(cookieFiles));
   if (!cookieFiles)
     return NS_ERROR_FAILURE;
 
   // fetch the current user's name from the environment
   PRUnichar username[sUsernameLengthLimit+2];
   ::GetEnvironmentVariableW(L"USERNAME", username,
                             sizeof(username)/sizeof(PRUnichar));
   username[sUsernameLengthLimit] = L'\0';
--- a/browser/components/places/content/bookmarksPanel.js
+++ b/browser/components/places/content/bookmarksPanel.js
@@ -39,11 +39,11 @@ function init() {
   document.getElementById('search-box').focus();
 }
 
 function searchBookmarks(aSearchString) {
   var tree = document.getElementById('bookmarks-view');
   if (!aSearchString)
     tree.place = tree.place;
   else
-    tree.applyFilter(aSearchString, true);
+    tree.applyFilter(aSearchString, true,
+                     [PlacesUtils.bookmarksRootId, PlacesUtils.unfiledRootId]);
 }
-
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksPanel.xul
@@ -62,21 +62,21 @@
 
   <hbox align="center">
     <label value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
     <textbox id="search-box" flex="1"
              type="timed" timeout="500"
              oncommand="searchBookmarks(this.value);"/>
   </hbox>
 
-  <tree id="bookmarks-view" class="placesTree" type="places"
+  <tree id="bookmarks-view" class="sidebar-placesTree" type="places"
         flex="1"
         hidecolumnpicker="true"
         place="place:folder=2&amp;queryType=1"
         context="placesContext"
         onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
         onclick="SidebarUtils.handleClick(this, event);">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
-    <treechildren id="bookmarks-view-children" view="bookmarks-view" flex="1"/>
+    <treechildren id="bookmarks-view-children" view="bookmarks-view" class="sidebar-placesTreechildren" flex="1"/>
   </tree>
 </page>
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -1025,114 +1025,129 @@ PlacesController.prototype = {
    * Get a TransferDataSet containing the content of the selection that can be
    * dropped elsewhere. 
    * @param   dragAction
    *          The action to happen when dragging, i.e. copy
    * @returns A TransferDataSet object that can be dragged and dropped 
    *          elsewhere.
    */
   getTransferData: function PC_getTransferData(dragAction) {
-    var nodes = null;
-    if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY)
-      nodes = this._view.getCopyableSelection();
-    else
-      nodes = this._view.getDragableSelection();
-    var dataSet = new TransferDataSet();
-    for (var i = 0; i < nodes.length; ++i) {
-      var node = nodes[i];
+    var result = this._view.getResult();
+    var oldViewer = result.viewer;
+    try {
+      result.viewer = null;
+      var nodes = null;
+      if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY)
+        nodes = this._view.getCopyableSelection();
+      else
+        nodes = this._view.getDragableSelection();
+      var dataSet = new TransferDataSet();
+      for (var i = 0; i < nodes.length; ++i) {
+        var node = nodes[i];
 
-      var data = new TransferData();
-      function addData(type, overrideURI) {
-        data.addDataForFlavour(type, PlacesUtils._wrapString(
-                               PlacesUtils.wrapNode(node, type, overrideURI)));
-      }
+        var data = new TransferData();
+        function addData(type, overrideURI) {
+          data.addDataForFlavour(type, PlacesUtils._wrapString(
+                                 PlacesUtils.wrapNode(node, type, overrideURI)));
+        }
 
-      function addURIData(overrideURI) {
-        addData(PlacesUtils.TYPE_X_MOZ_URL, overrideURI);
-        addData(PlacesUtils.TYPE_UNICODE, overrideURI);
-        addData(PlacesUtils.TYPE_HTML, overrideURI);
-      }
+        function addURIData(overrideURI) {
+          addData(PlacesUtils.TYPE_X_MOZ_URL, overrideURI);
+          addData(PlacesUtils.TYPE_UNICODE, overrideURI);
+          addData(PlacesUtils.TYPE_HTML, overrideURI);
+        }
 
-      // This order is _important_! It controls how this and other 
-      // applications select data to be inserted based on type.
-      addData(PlacesUtils.TYPE_X_MOZ_PLACE);
+        // This order is _important_! It controls how this and other 
+        // applications select data to be inserted based on type.
+        addData(PlacesUtils.TYPE_X_MOZ_PLACE);
       
-      var uri;
+        var uri;
       
-      // Allow dropping the feed uri of live-bookmark folders
-      if (PlacesUtils.nodeIsLivemarkContainer(node))
-        uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec;
+        // Allow dropping the feed uri of live-bookmark folders
+        if (PlacesUtils.nodeIsLivemarkContainer(node))
+          uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec;
       
-      addURIData(uri);
-      dataSet.push(data);
+        addURIData(uri);
+        dataSet.push(data);
+      }
+    }
+    finally {
+      if (oldViewer)
+        result.viewer = oldViewer;
     }
     return dataSet;
   },
 
   /**
    * Copy Bookmarks and Folders to the clipboard
    */
   copy: function PC_copy() {
-    var nodes = this._view.getCopyableSelection();
+    var result = this._view.getResult();
+    var oldViewer = result.viewer;
+    try {
+      result.viewer = null;
+      var nodes = this._view.getCopyableSelection();
 
-    var xferable = 
-        Cc["@mozilla.org/widget/transferable;1"].
-        createInstance(Ci.nsITransferable);
-    var foundFolder = false, foundLink = false;
-    var copiedFolders = [];
-    var placeString = mozURLString = htmlString = unicodeString = "";
+      var xferable =  Cc["@mozilla.org/widget/transferable;1"].
+                      createInstance(Ci.nsITransferable);
+      var foundFolder = false, foundLink = false;
+      var copiedFolders = [];
+      var placeString = mozURLString = htmlString = unicodeString = "";
     
-    for (var i = 0; i < nodes.length; ++i) {
-      var node = nodes[i];
-      if (this._shouldSkipNode(node, copiedFolders))
-        continue;
-      if (PlacesUtils.nodeIsFolder(node))
-        copiedFolders.push(node);
+      for (var i = 0; i < nodes.length; ++i) {
+        var node = nodes[i];
+        if (this._shouldSkipNode(node, copiedFolders))
+          continue;
+        if (PlacesUtils.nodeIsFolder(node))
+          copiedFolders.push(node);
         
-      function generateChunk(type, overrideURI) {
-        var suffix = i < (nodes.length - 1) ? NEWLINE : "";
-        var uri = overrideURI;
+        function generateChunk(type, overrideURI) {
+          var suffix = i < (nodes.length - 1) ? NEWLINE : "";
+          var uri = overrideURI;
         
-        if (PlacesUtils.nodeIsLivemarkContainer(node))
-          uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
-          
-        mozURLString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_X_MOZ_URL,
-                                               uri) + suffix);
-        unicodeString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_UNICODE,
-                                               uri) + suffix);
-        htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
-                                               uri) + suffix);
+          if (PlacesUtils.nodeIsLivemarkContainer(node))
+            uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
+
+          mozURLString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_X_MOZ_URL,
+                                                 uri) + suffix);
+          unicodeString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_UNICODE,
+                                                 uri) + suffix);
+          htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
+                                                 uri) + suffix);
         
-        var placeSuffix = i < (nodes.length - 1) ? "," : "";
-        return PlacesUtils.wrapNode(node, type, overrideURI) + placeSuffix;
+          var placeSuffix = i < (nodes.length - 1) ? "," : "";
+          return PlacesUtils.wrapNode(node, type, overrideURI) + placeSuffix;
+        }
+
+        // all items wrapped as TYPE_X_MOZ_PLACE
+        placeString += generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE);
       }
 
-      // all items wrapped as TYPE_X_MOZ_PLACE
-      placeString += generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE);
-    }
+      function addData(type, data) {
+        xferable.addDataFlavor(type);
+        xferable.setTransferData(type, PlacesUtils._wrapString(data), data.length * 2);
+      }
+      // This order is _important_! It controls how this and other applications 
+      // select data to be inserted based on type.
+      if (placeString)
+        addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
+      if (mozURLString)
+        addData(PlacesUtils.TYPE_X_MOZ_URL, mozURLString);
+      if (unicodeString)
+        addData(PlacesUtils.TYPE_UNICODE, unicodeString);
+      if (htmlString)
+        addData(PlacesUtils.TYPE_HTML, htmlString);
 
-    function addData(type, data) {
-      xferable.addDataFlavor(type);
-      xferable.setTransferData(type, PlacesUtils._wrapString(data), data.length * 2);
+      if (placeString || unicodeString || htmlString || mozURLString) {
+        PlacesUtils.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
+      }
     }
-    // This order is _important_! It controls how this and other applications 
-    // select data to be inserted based on type.
-    if (placeString)
-      addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
-    if (mozURLString)
-      addData(PlacesUtils.TYPE_X_MOZ_URL, mozURLString);
-    if (unicodeString)
-      addData(PlacesUtils.TYPE_UNICODE, unicodeString);
-    if (htmlString)
-      addData(PlacesUtils.TYPE_HTML, htmlString);
-
-    if (placeString || unicodeString || htmlString || mozURLString) {
-      var clipboard = 
-          Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
-      clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
+    finally {
+      if (oldViewer)
+        result.viewer = oldViewer;
     }
   },
 
   /**
    * Cut Bookmarks and Folders to the clipboard
    */
   cut: function PC_cut() {
     this.copy();
@@ -1161,18 +1176,17 @@ PlacesController.prototype = {
       var xferable = 
           Cc["@mozilla.org/widget/transferable;1"].
           createInstance(Ci.nsITransferable);
       for (var i = 0; i < types.length; ++i) 
         xferable.addDataFlavor(types[i]);
       return xferable;
     }
 
-    var clipboard = Cc["@mozilla.org/widget/clipboard;1"].
-                    getService(Ci.nsIClipboard);
+    var clipboard = PlacesUtils.clipboard;
 
     var ip = this._view.insertionPoint;
     if (!ip)
       throw Cr.NS_ERROR_NOT_AVAILABLE;
 
     /**
      * Gets a list of transactions to perform the paste of specific types.
      * @param   types
@@ -1216,16 +1230,295 @@ PlacesController.prototype = {
     var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
                                         PlacesUtils.TYPE_X_MOZ_URL, 
                                         PlacesUtils.TYPE_UNICODE]);
     var txn = PlacesUtils.ptm.aggregateTransactions("Paste", transactions);
     PlacesUtils.ptm.commitTransaction(txn);
   }
 };
 
+function PlacesMenuDNDObserver(aView, aPopup) {
+  this._view = aView;
+  this._popup = aPopup;
+  this._popup.addEventListener("draggesture", this, false);
+  this._popup.addEventListener("dragover", this, false);
+  this._popup.addEventListener("dragdrop", this, false);
+  this._popup.addEventListener("dragexit", this, false);
+}
+
+/**
+ * XXXmano-please-rewrite-me: This code was ported over from menu.xul in bug 399729.
+ * Unsurprisngly it's still mostly broken due to bug 337761, thus I didn't bother
+ * trying to cleaning up this extremely buggy  over-folder detection code yet.
+ */
+PlacesMenuDNDObserver.prototype = {
+  _view: null,
+  _popup: null,
+
+  // Sub-menus should be opened when the mouse drags over them, and closed
+  // when the mouse drags off.  The overFolder object manages opening and closing
+  // of folders when the mouse hovers.
+  _overFolder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
+
+  // If this menu's parent auto-opened it because it was dragged over, but didn't
+  // close it because the mouse dragged into it, the menu should close itself
+  // onDragExit.  This timer is set in dragExit to close the menu.
+  _closeMenuTimer: null,
+
+  _setTimer: function TBV_DO_setTimer(time) {
+    var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    timer.initWithCallback(this, time, timer.TYPE_ONE_SHOT);
+    return timer;
+  },
+
+  // Function to process all timer notifications.
+  notify: function TBV_DO_notify(timer) {
+    // Timer to open a submenu that's being dragged over.
+    if (timer == this._overFolder.openTimer) {
+      this._overFolder.node.lastChild.setAttribute("autoopened", "true");
+      this._overFolder.node.lastChild.showPopup(this._overFolder.node);
+      this._overFolder.openTimer = null;
+    }
+
+    // Timer to close a submenu that's been dragged off of.
+    if (timer == this._overFolder.closeTimer) {
+      // Only close the submenu if the mouse isn't being dragged over any
+      // of its child menus.
+      var draggingOverChild =
+        PlacesControllerDragHelper.draggingOverChildNode(this._overFolder.node);
+      if (draggingOverChild)
+        this._overFolder.node = null;
+      this._clearOverFolder();
+
+      // Close any parent folders which aren't being dragged over.
+      // (This is necessary because of the above code that keeps a folder
+      // open while its children are being dragged over.)
+      if (!draggingOverChild)
+        this._closeParentMenus();
+    }
+
+    // Timer to close this menu after the drag exit.
+    if (timer == this._closeMenuTimer) {
+      if (!PlacesControllerDragHelper.draggingOverChildNode(this._popup)) {
+        this._popup.hidePopup();
+        // Close any parent menus that aren't being dragged over;
+        // otherwise they'll stay open because they couldn't close
+        // while this menu was being dragged over.
+        this._closeParentMenus();
+      }
+    }
+  },
+
+  // Helper function to close all parent menus of this menu,
+  // as long as none of the parent's children are currently being
+  // dragged over.
+  _closeParentMenus: function TBV_DO_closeParentMenus() {
+    var parent = this._popup.parentNode;
+    while (parent) {
+      if (parent.nodeName == "menupopup" && parent._resultNode) {
+        if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
+          break;
+        parent.hidePopup();
+      }
+      parent = parent.parentNode;
+    }
+  },
+
+  // The mouse is no longer dragging over the stored menubutton.
+  // Close the menubutton, clear out drag styles, and clear all
+  // timers for opening/closing it.
+  _clearOverFolder: function TBV_DO_clearOverFolder() {
+    if (this._overFolder.node && this._overFolder.node.lastChild) {
+      if (!this._overFolder.node.lastChild.hasAttribute("dragover"))
+        this._overFolder.node.lastChild.hidePopup();
+      this._overFolder.node = null;
+    }
+    if (this._overFolder.openTimer) {
+      this._overFolder.openTimer.cancel();
+      this._overFolder.openTimer = null;
+    }
+    if (this._overFolder.closeTimer) {
+      this._overFolder.closeTimer.cancel();
+      this._overFolder.closeTimer = null;
+    }
+  },
+
+  // This function returns information about where to drop when
+  // dragging over this menu--insertion point, child index to drop
+  // before, and folder to drop into.
+  _getDropPoint: function TBV_DO_getDropPoint(event) {
+    // Can't drop if the menu isn't a folder
+    var resultNode = this._popup._resultNode;
+    if (!PlacesUtils.nodeIsFolder(resultNode))
+      return null;
+
+    var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
+    // Loop through all the nodes to see which one this should
+    // get dropped in/above/below.
+    var start = 0;
+    var end = this._popup.childNodes.length;
+    if (this._popup == this._view && this._view.localName == "menupopup") {
+      // Ignore static content at the top and bottom of the menu.
+      start = this._view._startMarker + 1;
+      if (this._view._endMarker != -1)
+        end = this._view._endMarker;
+    }
+
+    for (var i = start; i < end; i++) {
+      var xulNode = this._popup.childNodes[i];
+      var nodeY = xulNode.boxObject.y - this._popup.boxObject.y;
+      var nodeHeight = xulNode.boxObject.height;
+      if (xulNode.node &&
+          PlacesUtils.nodeIsFolder(xulNode.node) &&
+          !PlacesUtils.nodeIsReadOnly(xulNode.node)) {
+        // This is a folder. If the mouse is in the top 25% of the
+        // node, drop above the folder.  If it's in the middle
+        // 50%, drop into the folder.  If it's past that, drop below.
+        if (event.clientY < nodeY + (nodeHeight * 0.25)) {
+          // Drop above this folder.
+          dropPoint.ip = new InsertionPoint(resultNode.itemId, i - start,
+                                            -1);
+          dropPoint.beforeIndex = i;
+          return dropPoint;
+        }
+        else if (event.clientY < nodeY + (nodeHeight * 0.75)) {
+          // Drop inside this folder.
+          dropPoint.ip = new InsertionPoint(xulNode.node.itemId, -1, 1);
+          dropPoint.beforeIndex = i;
+          dropPoint.folderNode = xulNode;
+          return dropPoint;
+        }
+      } else {
+        // This is a non-folder node. If the mouse is above the middle,
+        // drop above the folder.  Otherwise, drop below.
+        if (event.clientY < nodeY + (nodeHeight / 2)) {
+          // Drop above this bookmark.
+          dropPoint.ip = new InsertionPoint(resultNode.itemId, i - start, -1);
+          dropPoint.beforeIndex = i;
+          return dropPoint;
+        }
+      }
+    }
+    // Should drop below the last node.
+    dropPoint.ip = new InsertionPoint(resultNode.itemId, -1, 1);
+    dropPoint.beforeIndex = -1;
+    return dropPoint;
+  },
+
+  // This function clears all of the dragover styles that were set when
+  // a menuitem was dragged over.
+  _clearStyles: function TBV_DO_clearStyles() {
+    this._popup.removeAttribute("dragover");
+    for (var i = 0; i < this._popup.childNodes.length; i++) {
+      this._popup.childNodes[i].removeAttribute("dragover-top");
+      this._popup.childNodes[i].removeAttribute("dragover-bottom");
+      this._popup.childNodes[i].removeAttribute("dragover-into");
+    }
+  },
+
+  onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
+    this._view._selection = event.target.node;
+    this._view._cachedInsertionPoint = undefined;
+    if (event.ctrlKey)
+      dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
+    xferData.data = this._view.controller.getTransferData(dragAction.action);
+  },
+
+  canDrop: function TBV_DO_canDrop(event, session) {
+    return PlacesControllerDragHelper.canDrop(this._view, -1);
+  },
+
+  onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
+    PlacesControllerDragHelper.currentDropTarget = event.target;
+    var dropPoint = this._getDropPoint(event);
+    if (dropPoint == null)
+      return;
+
+    this._clearStyles();
+    if (dropPoint.folderNode) {
+      // Dragging over a folder; set the appropriate styles.
+      if (this._overFolder.node != dropPoint.folderNode) {
+        this._clearOverFolder();
+        this._overFolder.node = dropPoint.folderNode;
+        this._overFolder.openTimer = this._setTimer(this._overFolder.hoverTime);
+      }
+      dropPoint.folderNode.setAttribute("dragover-into", "true");
+    }
+    else {
+      // Dragging over a menuitem, set dragover-top/bottom to show where
+      // the item will be dropped and clear out any old folder info.
+      if (dropPoint.beforeIndex == -1) {
+        if (this._popup == this._view && this._view.localName == "menupopup" &&
+            this._popup._endMarker != -1) {
+          this._popup.childNodes[this._popup._endMarker]
+                     .setAttribute("dragover-top", "true");
+        }
+        else
+          this._popup.lastChild.setAttribute("dragover-bottom", "true");
+      }
+      else {
+        this._popup.childNodes[dropPoint.beforeIndex]
+            .setAttribute("dragover-top", "true");
+      }
+
+      // Clear out old folder information
+      this._clearOverFolder();
+    }
+    this._popup.setAttribute("dragover", "true");
+  },
+
+  onDrop: function TBV_DO_onDrop(event, dropData, session) {
+    var dropPoint = this._getDropPoint(event);
+    if (!dropPoint)
+      return;
+
+    PlacesControllerDragHelper.onDrop(null, this._view, dropPoint.ip);
+  },
+
+  onDragExit: function TBV_DO_onDragExit(event, session) {
+    PlacesControllerDragHelper.currentDropTarget = null;
+    this._clearStyles();
+    // Close any folder being hovered over
+    if (this._overFolder.node)
+      this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
+    // The autoopened attribute is set when this folder was automatically
+    // opened after the user dragged over it.  If this attribute is set,
+    // auto-close the folder on drag exit.
+    if (this._popup.hasAttribute("autoopened"))
+      this._closeMenuTimer = this._setTimer(this._overFolder.hoverTime);
+  },
+
+  getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
+    var flavorSet = new FlavourSet();
+    for (var i = 0; i < this._view.peerDropTypes.length; ++i)
+      flavorSet.appendFlavour(this._view.peerDropTypes[i]);
+    return flavorSet;
+  },
+
+  handleEvent: function(aEvent) {
+    switch (aEvent.type) {
+    case "draggesture":
+      if (aEvent.target.localName != "menu" && aEvent.target.node) {
+        // TODO--allow menu drag if shift (or alt??) key is down
+        nsDragAndDrop.startDrag(aEvent, this);
+      }
+      break;
+    case "dragover":
+      nsDragAndDrop.dragOver(aEvent, this);
+      break;
+    case "dragdrop":
+      nsDragAndDrop.drop(aEvent, this);
+      break;
+    case "dragexit":
+      nsDragAndDrop.dragExit(aEvent, this);
+      break;
+    }
+  }
+}
+
 /**
  * Handles drag and drop operations for views. Note that this is view agnostic!
  * You should not use PlacesController._view within these methods, since
  * the view that the item(s) have been dropped on was not necessarily active. 
  * Drop functions are passed the view that is being dropped on. 
  */
 var PlacesControllerDragHelper = {
 
@@ -1268,19 +1561,19 @@ var PlacesControllerDragHelper = {
    * @param   view
    *          An object implementing the AVI
    * @param   orientation
    *          The orientation of the drop
    * @returns true if the data being dragged is of a type supported by the view
    *          it is being dragged over, false otherwise. 
    */
   canDrop: function PCDH_canDrop(view, orientation) {
-    var parent = view.getResult().root;
-    if (PlacesUtils.nodeIsReadOnly(parent) || 
-        !PlacesUtils.nodeIsFolder(parent))
+    var root = view.getResult().root;
+    if (PlacesUtils.nodeIsReadOnly(root) || 
+        !PlacesUtils.nodeIsFolder(root))
       return false;
 
     var session = this.getSession();
     if (session) {
       if (orientation != NHRVO.DROP_ON)
         var types = view.peerDropTypes;
       else
         types = view.childDropTypes;
@@ -1330,40 +1623,40 @@ var PlacesControllerDragHelper = {
    */
   onDrop: function PCDH_onDrop(sourceView, targetView, insertionPoint) {
     var session = this.getSession();
     var copy = session.dragAction & Ci.nsIDragService.DRAGDROP_ACTION_COPY;
     var transactions = [];
     var xferable = this._initTransferable(session, targetView, 
                                           insertionPoint.orientation);
     var dropCount = session.numDropItems;
-    
+
     var movedCount = 0;
-    
+
     for (var i = 0; i < dropCount; ++i) {
       session.getData(xferable, i);
-    
+
       var data = { }, flavor = { };
       xferable.getAnyTransferData(flavor, data, { });
       data.value.QueryInterface(Ci.nsISupportsString);
-      
+
       // There's only ever one in the D&D case. 
       var unwrapped = PlacesUtils.unwrapNodes(data.value.data, 
                                               flavor.value)[0];
       var index = insertionPoint.index;
-      
+
       // Adjust insertion index to prevent reversal of dragged items. When you
       // drag multiple elts upward: need to increment index or each successive
       // elt will be inserted at the same index, each above the previous.
       if ((index != -1) && ((index < unwrapped.index) ||
                            (unwrapped.folder && (index < unwrapped.folder.index)))) {
         index = index + movedCount;
         movedCount++;
       }
-        
+
       transactions.push(PlacesUtils.makeTransaction(unwrapped,
                         flavor.value, insertionPoint.itemId,
                         index, copy));
     }
 
     var txn = PlacesUtils.ptm.aggregateTransactions("DropItems", transactions);
     PlacesUtils.ptm.commitTransaction(txn);
   }
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -566,21 +566,38 @@ var gEditItemOverlay = {
       expander.setAttribute("tooltiptext",
                             expander.getAttribute("tooltiptextdown"));
       this._folderTree.collapsed = true;
     }
     else {
       expander.className = "expander-up"
       expander.setAttribute("tooltiptext",
                             expander.getAttribute("tooltiptextup"));
-      if (!this._folderTree.treeBoxObject.view.isContainerOpen(0))
+      this._folderTree.collapsed = false;
+      if (!this._folderTree.place) {
+        const FOLDER_TREE_PLACE_URI =
+          "place:folder=2&excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1";
+        this._folderTree.place = FOLDER_TREE_PLACE_URI;
+      }
+
+      var currentFolder = this._getFolderIdFromMenuList();
+      // Don't select anything in the tree if the item is "unfiled"
+      if (currentFolder == PlacesUtils.unfiledRootId)
+        this._folderTree.selectFolders([]);
+      else {
+        this._folderTree.selectFolders([currentFolder]);
+        this._folderTree.focus();
+      }
+
+      if ((currentFolder == PlacesUtils.bookmarksRootId ||
+           currentFolder == PlacesUtils.unfiledRootId) &&
+          !this._folderTree.treeBoxObject.view.isContainerOpen(0)) {
+        // Expand the root node if selectFolder didn't
         this._folderTree.treeBoxObject.view.toggleOpenState(0);
-      this._folderTree.selectFolders([this._getFolderIdFromMenuList()]);
-      this._folderTree.collapsed = false;
-      this._folderTree.focus();
+      }
     }
   },
 
   _getFolderIdFromMenuList:
   function EIO__getFolderIdFromMenuList() {
     var selectedItem = this._folderMenuList.selectedItem
     switch (selectedItem.id) {
       case "editBMPanel_unfiledRootItem":
--- a/browser/components/places/content/editBookmarkOverlay.xul
+++ b/browser/components/places/content/editBookmarkOverlay.xul
@@ -139,17 +139,16 @@
 
         <tree id="editBMPanel_folderTree"
               class="placesTree"
               type="places"
               height="150"
               collapsed="true"
               onselect="gEditItemOverlay.onFolderTreeSelect();"
               showRoot="true"
-              place="place:folder=2&amp;excludeItems=1&amp;excludeQueries=1&amp;excludeReadOnlyFolders=1"
               hidecolumnpicker="true"
               observes="paneElementsBroadcaster">
           <treecols>
             <treecol anonid="title" flex="1" primary="true" hideheader="true"/>
           </treecols>
           <treechildren flex="1"/>
         </tree>
 
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/history-panel.xul
@@ -109,20 +109,21 @@
                   accesskey="&byLastVisited.accesskey;"
                   type="radio"
                   oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'lastvisited'); GroupBy('lastvisited');"/>
       </menupopup>
     </button>
   </hbox>
 
   <tree id="historyTree"
+        class="sidebar-placesTree"
         flex="1"
         type="places"
         context="placesContext"
         onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
         hidecolumnpicker="true"
         onclick="SidebarUtils.handleClick(this, event, true);">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
-    <treechildren flex="1"/>
+    <treechildren class="sidebar-placesTreechildren" flex="1"/>
   </tree>
 </page>
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -75,486 +75,328 @@
       </method>
 
       <property name="controller"
                 readonly="true"
                 onget="return this._controller;"/>
 
       <field name="_built">false</field>
 
-      <field name="_ignoreInvalidateContainer">false</field>
-
       <method name="onPopupShowing">
+        <parameter name="aEvent"/>
         <body><![CDATA[
-          this._ensureInitialized();
-
-          if (!this._resultNode.containerOpen)
-            this._resultNode.containerOpen = true;
-          if (!this._built)
-            this._rebuild();
-
-          if (this.popupShowingCallback)
-            this.popupShowingCallback();
+          var popup = aEvent.target;
+          var resultNode = popup._resultNode;
+          resultNode.containerOpen = true;
+          if (!popup._built)
+            this._rebuild(popup);
+          if (!popup._DNDObserver)
+            popup._DNDObserver = new PlacesMenuDNDObserver(this, popup);
         ]]></body>
       </method>
 
       <field name="_selection">null</field>
 
-      <method name="setResultAndNode">
-        <parameter name="result"/>
-        <parameter name="resultNode"/>
-        <body><![CDATA[
-          this._result = result;
-          this._resultNode = resultNode;
-          this._rebuild();
-        ]]></body>
-      </method>
-
       <!-- nsIPlacesView -->
       <method name="getResult">
         <body><![CDATA[
           return this._result;
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <method name="getResultNode">
         <body><![CDATA[
+          this._ensureInitialized();
           return this._resultNode;
         ]]></body>
       </method>
 
-      <!-- These are the indices of the start and end
-           of dynamic content in the menu.  For index,
-           if this is a bookmark menu and it has two
-           static entries at the top, "Bookmark this page"
-           and "Bookmark all tabs", _startMarker will be
-           2.  If it has an "open in tabs" item at the end,
-           _endMarker will be the index of that item.
-           If there is no static content in the menu,
-           _startMarker and _endMarker are -1. -->
-      <field name="_startMarker">-1</field>
-      <field name="_endMarker">-1</field>
-
       <method name="_cleanMenu">
+        <parameter name="aPopup"/>
         <body><![CDATA[
           // Find static menuitems that should go at the start
           // and end of the menu, marked by builder="start" and
           // builder="end" attributes, and keep track of their indices.
           // All of the items between the start and end should be removed.
           var items = [];
-          this._startMarker = -1;
-          this._endMarker = -1;
-          for (var i = 0; i < this.childNodes.length; ++i) {
-            var item = this.childNodes[i];
+          aPopup._startMarker = -1;
+          aPopup._endMarker = -1;
+          for (var i = 0; i < aPopup.childNodes.length; ++i) {
+            var item = aPopup.childNodes[i];
             if (item.getAttribute("builder") == "start") {
-              this._startMarker = i;
+              aPopup._startMarker = i;
               continue;
             }
             if (item.getAttribute("builder") == "end") {
-              this._endMarker = i;
+              aPopup._endMarker = i;
               continue;
             }
-            if ((this._startMarker != -1) && (this._endMarker == -1))
+            if ((aPopup._startMarker != -1) && (aPopup._endMarker == -1))
               items.push(item);
           }
 
           // If static items at the beginning were found, remove all items between
           // them and the static content at the end.
           for (var i = 0; i < items.length; ++i) { 
             // skip the empty menu item
-            if (this._emptyMenuItem != items[i]) {
-              items[i].parentNode.removeChild(items[i]);
+            if (aPopup._emptyMenuItem != items[i]) {
+              aPopup.removeChild(items[i]);
               if (this._endMarker > 0)
                 --this._endMarker;
             }
           }
 
           // If no static items were found at the beginning, remove all items before
           // the static items at the end.
-          if (this._startMarker == -1) {
-            var end = (this._endMarker == -1) ? this.childNodes.length - 1 : this._endMarker - 1;
+          if (aPopup._startMarker == -1) {
+            var end = aPopup._endMarker == -1 ?
+                      aPopup.childNodes.length - 1 : aPopup._endMarker - 1;
             for (var i = end; i >=0; i--) {
               // skip the empty menu item
-              if (this._emptyMenuItem != this.childNodes[i]) {
-                this.removeChild(this.childNodes[i]);
-                if (this._endMarker > 0)
-                  --this._endMarker;
+              if (aPopup._emptyMenuItem != aPopup.childNodes[i]) {
+                aPopup.removeChild(aPopup.childNodes[i]);
+                if (aPopup._endMarker > 0)
+                  --aPopup._endMarker;
               }
             }
           }
-          //LOG("KIDS = " + this.childNodes.length);
         ]]></body>
       </method>
 
       <method name="removeItem">
         <parameter name="child"/>
         <body><![CDATA[
           if (PlacesUtils.nodeIsContainer(child.node)) {
             for (var i=0; i < this._containerNodesMap.length; i++) {
-              if (this._containerNodesMap[i].resultNode == child.node)
+              if (this._containerNodesMap[i].resultNode == child.node) {
                 this._containerNodesMap.splice(i, 1);
+                break;
+              }
             }
           }
 
-          this.removeChild(child);
+          child.parentNode.removeChild(child);
         ]]></body>
       </method>
 
       <method name="insertNewItem">
-        <parameter name="child"/>
-        <parameter name="before"/>
+        <parameter name="aChild"/>
+        <parameter name="aParentPopup"/>
+        <parameter name="aBefore"/>
         <body><![CDATA[
-          const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-          var element = null;
-          if (PlacesUtils.nodeIsURI(child)) {
-            element = document.createElementNS(XULNS, "menuitem");
-            element.setAttribute("label", child.title);
-            element.setAttribute("url", child.uri);
-            element.setAttribute("statustext", child.uri);
-            element.className = "menuitem-iconic bookmark-item";
-          }
-          else if (PlacesUtils.nodeIsSeparator(child)) {
-            element = document.createElementNS(XULNS, "menuseparator");
-          }
-          else if (PlacesUtils.nodeIsContainer(child)) {
-            element = document.createElementNS(XULNS, "menu");
-            element.setAttribute("type", "menu");
-            element.setAttribute("container", "true");
-            element.setAttribute("label", child.title);
+          var element =
+            PlacesUtils.createMenuItemForNode(aChild, this._containerNodesMap);
 
-            if (PlacesUtils.nodeIsLivemarkContainer(child)) {
-              element.setAttribute("livemark", "true");
-              var folder = child.itemId;
-              var siteURI = PlacesUtils.livemarks.getSiteURI(folder);
-              if (siteURI)
-                element.setAttribute("siteURI", siteURI.spec);
-            }
-            var popup = document.createElementNS(XULNS, "menupopup");
-            popup.setAttribute("type", "places");
-            element.appendChild(popup);
-#ifndef XP_MACOSX
-            // No context menus on menus on Mac
-            // The context menu is set here instead of in the xbl constructor
-            // because it doesn't get initialized properly if set in the constructor.
-            popup.setAttribute("context", "placesContext");
-#endif
-            popup._result = this._result;
-            popup._resultNode = asContainer(child);
-            element.className = "menu-iconic bookmark-item";
-#ifdef XP_MACOSX
-            // If this is a child of the bookmarks menubar, we have to manually attach
-            // its xbl binding, because it's not a dom node and the style rules don't
-            // get applied correctly.
-            if (this._needsBindingAttachment) {
-              const MENU_URI = "chrome://browser/content/places/menu.xml#places-menupopup";
-              document.addBinding(popup, MENU_URI);
-            }
-#endif
-            popup._containerNodesMap = this._containerNodesMap;
-            this._containerNodesMap.push({ resultNode: child, domNode: popup });
-          }
-          
-          if (element) {
-            element.node = child;
-            element.node.viewIndex = 0;
-            if (child.icon)
-              element.setAttribute("image", child.icon.spec);
-
-            if (before)
-              this.insertBefore(element, before);
-            else {
-              // Add the new element to the menu.  If there is static content at
-              // the end of the menu, add the element before that.  Otherwise,
-              // just add to the end.
-              if (this._endMarker != -1)
-                this.insertBefore(element, this.childNodes[this._endMarker++]);
-              else
-                this.appendChild(element);
-            }
+          if (aBefore)
+            aParentPopup.insertBefore(element, aBefore);
+          else {
+            // Add the new element to the menu.  If there is static content at
+            // the end of the menu, add the element before that.  Otherwise,
+            // just add to the end.
+            if (aParentPopup._endMarker != -1)
+              aParentPopup.insertBefore(element,
+                                        aParentPopup.childNodes[this._endMarker++]);
+            else
+              aParentPopup.appendChild(element);
           }
         ]]></body>
       </method>
 
-#ifdef XP_MACOSX
-      <field name="_needsBindingAttachment">false</field>
-#endif
-
-      <field name="_emptyMenuItem">null</field>
       <method name="_showEmptyMenuItem">
+        <parameter name="aPopup"/>
         <body><![CDATA[
-          if (this._emptyMenuItem) {
-            this._emptyMenuItem.hidden = false;
+          if (aPopup._emptyMenuItem) {
+            aPopup._emptyMenuItem.hidden = false;
             return;
           }
 
           var label = PlacesUtils.getString("bookmarksMenuEmptyFolder");
-          const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-          this._emptyMenuItem = document.createElementNS(XULNS, "menuitem");
-          this._emptyMenuItem.setAttribute("label", label);
-          this._emptyMenuItem.setAttribute("disabled", true);
-          this.appendChild(this._emptyMenuItem);
+          aPopup._emptyMenuItem = document.createElement("menuitem");
+          aPopup._emptyMenuItem.setAttribute("label", label);
+          aPopup._emptyMenuItem.setAttribute("disabled", true);
+          aPopup.appendChild(aPopup._emptyMenuItem);
         ]]></body>
       </method>
 
       <method name="_rebuild">
+        <parameter name="aPopup"/>
         <body><![CDATA[
-          // Make sure not to hold onto any references to menu nodes when we
-          // rebuild, since rebuilding deletes all the nodes in the menu and
-          // re-adds them.  If we use a reference to a deleted node, all kinds
-          // of exceptions and asserts will fire.
-          if (this._DNDObserver._overFolder.node)
-            this._DNDObserver._clearOverFolder();
-
-          this._cleanMenu();
-
-          NS_ASSERT(PlacesUtils.nodeIsContainer(this._resultNode),
-                    "Result-node of a places popup has to be a container node");
+          this._cleanMenu(aPopup);
 
-#ifdef XP_MACOSX
-          // On Mac OSX, we need to manually attach the XBL binding for the bookmarks menu,
-          // because menus in the OSX menubar aren't real DOM nodes, and they don't get styles
-          // applied.
-          var currentNode = this.parentNode;
-          while (currentNode && !this._needsBindingAttachment) {
-            if (currentNode.id && currentNode.id == "bookmarksMenu")
-              this._needsBindingAttachment = true;
-            currentNode = currentNode.parentNode;
-          }
-#endif
-
-          NS_ASSERT(this._resultNode.containerOpen,
-                    "container must be opened when _rebuild is called");
-
-          var cc = this._resultNode.childCount;
+          var cc = aPopup._resultNode.childCount;
           if (cc > 0) {
-            if (this._emptyMenuItem)
-              this._emptyMenuItem.hidden = true;
+            if (aPopup._emptyMenuItem)
+              aPopup._emptyMenuItem.hidden = true;
 
             for (var i = 0; i < cc; ++i) {
-              var child = this._resultNode.getChild(i);
-              this.insertNewItem(child, null);
+              var child = aPopup._resultNode.getChild(i);
+              this.insertNewItem(child, aPopup, null);
             }
           }
           else {
             // This menu is empty.  If there is no static content, add
             // an element to show it is empty.
-            if (this._startMarker == -1 && this._endMarker == -1)
-              this._showEmptyMenuItem();
+            if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
+              this._showEmptyMenuItem(aPopup);
           }
-          this._built = true;
+          aPopup._built = true;
         ]]></body>
       </method>
 
       <!-- nsINavHistoryResultViewer -->
       <field name="_viewer"><![CDATA[({
         _self: this,
 
-        _forwardToChildView:
-        function PMV__forwardToChildView(aNode, aFunction, aArguments) {
+        _getPopupForContainer:
+        function PMV__getPopupForContainer(aNode) {
+          if (this._self._resultNode == aNode)
+            return this._self;
+
           for (var i=0; i < this._self._containerNodesMap.length; i++) {
-            if (this._self._containerNodesMap[i].resultNode == aNode) {
-              var childView = this._self._containerNodesMap[i].domNode._viewer;
-              childView[aFunction].apply(childView, aArguments);
-              return;
-            }
+            if (this._self._containerNodesMap[i].resultNode == aNode)
+              return this._self._containerNodesMap[i].domNode;
           }
           throw("Container view not found");
         },
 
         itemInserted: function PMV_itemInserted(aParentNode, aNode, aIndex) {
-          if (!this._self._built)
+          var popup = this._getPopupForContainer(aParentNode);
+          if (!popup._built)
             return;
 
-          if (aParentNode == this._self.getResultNode()) {
-            var index = this._self._startMarker + 1 + aIndex;
-            var before = this._self.childNodes[index] || null;
-            this._self.insertNewItem(aNode, before);
-            if (this._self._emptyMenuItem)
-              this._self._emptyMenuItem.hidden = true;
-          }
-          else
-            this._forwardToChildView(aParentNode, "itemInserted", arguments);
+          var index = popup._startMarker + 1 + aIndex;
+          var before = popup.childNodes[index] || null;
+          this._self.insertNewItem(aNode, popup, before);
+          if (popup._emptyMenuItem)
+            popup._emptyMenuItem.hidden = true;
         },
 
         itemRemoved: function PMV_itemRemoved(aParentNode, aNode, aIndex) {
-          if (!this._self._built)
+          var popup = this._getPopupForContainer(aParentNode);
+          if (!popup._built)
             return;
 
-          if (aParentNode == this._self.getResultNode()) {
-            var children = this._self.childNodes;
-
-            for (var i = 0; i < children.length; i++) {
-              if (children[i].node == aNode) {
-                this._self.removeItem(children[i]);
-                if (!this._self.hasChildNodes() ||
-                    (this._self.childNodes.length == 1 &&
-                     this._self.firstChild == this._self._emptyMenuItem)) {
-                  this._self._showEmptyMenuItem();
-                }
+          var children = popup.childNodes;
+          for (var i = 0; i < children.length; i++) {
+            if (children[i].node == aNode) {
+              this._self.removeItem(children[i]);
+              if (!popup.hasChildNodes() ||
+                  (popup.childNodes.length == 1 &&
+                   popup.firstChild == popup._emptyMenuItem)) {
+                this._self._showEmptyMenuItem(popup);
               }
             }
           }
-          else
-            this._forwardToChildView(aParentNode, "itemRemoved", arguments);
         },
 
         itemChanged: function PMV_itemChanged(aNode) {
-          if (!this._self._built)
-            return;
-
           // this check can be removed once we fix bug #382397
           var parentNode = aNode.parent;
           if (!parentNode)
             return;
 
-          if (parentNode != this._self.getResultNode()) {
-            this._forwardToChildView(parentNode, "itemChanged", arguments);
+          var popup = this._getPopupForContainer(parentNode);
+          if (!popup._built)
             return;
-          }
 
+          var children = popup.childNodes;
           var menuitem;
-
-          var children = this._self.childNodes;
           for (var i = 0; i < children.length; i++) {
             if (children[i].node == aNode) {
               menuitem = children[i];
               break;
             }
           }
 
-          NS_ASSERT(menuitem, "unable to find menuitem");
-          if (!menuitem)
-            return;
-
-          var title = aNode.title;
-
           if (PlacesUtils.nodeIsSeparator(aNode)) {
             // nothing to do when a separator changes
             return;
           }
-          else if (PlacesUtils.nodeIsContainer(aNode)) {
-            if (PlacesUtils.nodeIsLivemarkContainer(aNode)) {
-              var folder = aNode.itemId;
-              var siteURIString = PlacesUtils.livemarks.getSiteURI(folder);
-              if (siteURIString) {
-                if (menuitem.getAttribute("siteURI") != siteURIString)
-                  menuitem.setAttribute("siteURI", siteURIString);
-              }
-              else
-                menuitem.removeAttribute("siteURI");
-            }
-          }
 
-          if (aNode.icon) {
-            if (menuitem.getAttribute("image") != aNode.icon.spec)
-              menuitem.setAttribute("image", aNode.icon.spec);
+          var iconURI = aNode.icon;
+          if (iconURI) {
+            var spec = iconURI.spec;
+            if (menuitem.getAttribute("image") != spec)
+              menuitem.setAttribute("image", spec);
           }
           else
             menuitem.removeAttribute("image");
 
+          var title = aNode.title;
           if (menuitem.getAttribute("label") != title)
             menuitem.setAttribute("label", title);
         },
 
         itemReplaced:
         function PMV_itemReplaced(aParentNode, aOldNode, aNewNode, aIndex) {
-          if (!this._self._built)
+          var popup = this._getPopupForContainer(aParentNode);
+          if (!popup._built)
             return;
 
-          if (aParentNode == this._self.getResultNode()) {
-            var children = this._self.childNodes;
-            for (var i = 0; i < children.length; i++) {
-              if (children[i].node == aOldNode) {
-                var next = children[i].nextSibling;
-                this._self.removeItem(children[i]);
-                this._self.insertNewItem(aNewNode, next);
-                return;
-              }
+          var children = popup.childNodes;
+          for (var i = 0; i < children.length; i++) {
+            if (children[i].node == aOldNode) {
+              var next = children[i].nextSibling;
+              this._self.removeItem(children[i]);
+              this._self.insertNewItem(aNewNode, popup, next);
+              return;
             }
           }
-          else
-            this._forwardToChildView(aParentNode, "itemReplaced", arguments);
         },
 
         containerOpened: function PMV_containerOpened(aNode) {
           this.invalidateContainer(aNode);
         },
 
         containerClosed: function PMV_containerClosed(aNode) {
           this.invalidateContainer(aNode);
         },
  
-        get ignoreInvalidateContainer() {
-          return this._self._ignoreInvalidateContainer;
-        },
-
-        set ignoreInvalidateContainer(val) {
-          return this._self._ignoreInvalidateContainer = val;
-        },
-
         invalidateContainer: function PMV_invalidateContainer(aContainer) {
-          if (this._self_ignoreInvalidateContainer)
-            return;
-
           if (!this._self._built)
             return;
 
           function isChildOf(node, container) {
             var parent = node.parent;
             while (parent) {
               if (parent == container)
                 return true;
               parent = parent.parent;
             }
             return false;
           }
 
-          var viewerToRebuild = null;
+          var popupToRebuild = null;
           for (var i=0; i < this._self._containerNodesMap.length; i++) {
             var node = this._self._containerNodesMap[i].resultNode;
 
             if (node == aContainer)
-              viewerToRebuild = this._self._containerNodesMap[i].domNode._viewer;
-            if (isChildOf(node, aContainer))
+              popupToRebuild = this._self._containerNodesMap[i].domNode;
+            if (isChildOf(node, aContainer)) {
               this._self._containerNodesMap.splice(i,1);
+              i--;
+            }
           }
 
-          if (aContainer.containerOpen) {
-            if (viewerToRebuild)
-              viewerToRebuild._built = false;
-            else
-              this._self._built = false;
-          }
+          if (popupToRebuild)
+            popupToRebuild._built = false;
+          else
+            this._self._built = false;
         },
 
         invalidateAll: function PMV_invalidateAll() {
           this._self._containerNodesMap.splice(0);
           this._self._built = false;
         },
 
         sortingChanged: function PMV_sortingChanged(aSortingMode) {
         }
       })]]></field>
 
-      <!-- Sometimes calling hidePopup() on a menu can leave submenus
-           open.  This calls hidePopup() on the menu and recursively
-           hides its submenus as well. -->
-      <method name="hidePopupAndChildPopups">
-        <body><![CDATA[
-          for (var i = 0; i < this.childNodes.length; i++) {
-            if (this.childNodes[i].getAttribute("type") == "menu" &&
-                this.childNodes[i].lastChild &&
-                this.childNodes[i].lastChild.getAttribute("type") == "places")
-              this.childNodes[i].lastChild.hidePopupAndChildPopups();
-          }
-          this.hidePopup();
-        ]]></body>
-      </method>
-
       <!-- nsIPlacesView -->
       <property name="place">
         <getter><![CDATA[
           return this.getAttribute("place");
         ]]></getter>
         <setter><![CDATA[
           // Map for containerNodes<->domNodes. There's only one map per
           // result/viewer, the field is initialized once for the root menu,
@@ -650,16 +492,17 @@
           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.
+              folderId = this.selectedNode.parent.itemId;
               index = PlacesUtils.getIndexOfNode(this.selectedNode)
             }
           }
           this._cachedInsertionPoint = new InsertionPoint(folderId, index);
           return this._cachedInsertionPoint;
         ]]></getter>
       </property>
 
@@ -681,251 +524,16 @@
         <body><![CDATA[
         ]]></body>
       </method>
       <method name="restoreSelection">
         <body><![CDATA[
         ]]></body>
       </method>
 
-      <field name="_DNDObserver"><![CDATA[({
-        // Inside the _DNDObserver object's functions, this points to
-        // the _DNDObserver object.  _self points to the menu xbl object.
-        _self: this,
-        // Subfolders should be opened when the mouse drags over them, and closed
-        // when the mouse drags off.  The overFolder object manages opening and closing
-        // of folders when the mouse hovers.
-        _overFolder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
-        // If this menu's parent auto-opened it because it was dragged over, but didn't
-        // close it because the mouse dragged into it, the menu should close itself
-        // onDragExit.  This timer is set in dragExit to close the menu.
-        _closeMenuTimer: null,
-
-        _setTimer: function TBV_DO_setTimer(time) {
-          var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-          timer.initWithCallback(this, time, timer.TYPE_ONE_SHOT);
-          return timer;
-        },
-
-        // Function to process all timer notifications.
-        notify: function TBV_DO_notify(timer) {
-
-          // Timer to open a submenu that's being dragged over.
-          if (timer == this._overFolder.openTimer) {
-            this._overFolder.node.lastChild.setAttribute("autoopened", "true");
-            this._overFolder.node.lastChild.showPopup(this._overFolder.node);
-            this._overFolder.openTimer = null;
-          }
-
-          // Timer to close a submenu that's been dragged off of.
-          if (timer == this._overFolder.closeTimer) {
-            // Only close the submenu if the mouse isn't being dragged over any
-            // of its child menus.
-            var draggingOverChild =
-              PlacesControllerDragHelper.draggingOverChildNode(this._overFolder.node);
-            if (draggingOverChild)
-              this._overFolder.node = null;
-            this._clearOverFolder();
-
-            // Close any parent folders which aren't being dragged over.
-            // (This is necessary because of the above code that keeps a folder
-            // open while its children are being dragged over.)
-            if (!draggingOverChild)
-              this._closeParentMenus();
-          }
-
-          // Timer to close this menu after the drag exit.
-          if (timer == this._closeMenuTimer) {
-            if (!PlacesControllerDragHelper.draggingOverChildNode(this._self)) {
-              this._self.hidePopupAndChildPopups();
-              // Close any parent menus that aren't being dragged over;
-              // otherwise they'll stay open because they couldn't close
-              // while this menu was being dragged over.
-              this._closeParentMenus();
-            }
-          }
-        },
-
-        // Helper function to close all parent menus of this menu,
-        // as long as none of the parent's children are currently being
-        // dragged over.
-        _closeParentMenus: function TBV_DO_closeParentMenus() {
-          var parent = this._self.parentNode;
-          while(parent) {
-            if (parent.nodeName == "menupopup" &&
-                parent.getAttribute("type") == "places") {
-              if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
-                break;
-              parent.hidePopup();
-            }
-            parent = parent.parentNode;
-          }
-        },
-
-        // The mouse is no longer dragging over the stored menubutton.
-        // Close the menubutton, clear out drag styles, and clear all
-        // timers for opening/closing it.
-        _clearOverFolder: function TBV_DO_clearOverFolder() {
-          if (this._overFolder.node && this._overFolder.node.lastChild) {
-            if (!this._overFolder.node.lastChild.hasAttribute("dragover"))
-              this._overFolder.node.lastChild.hidePopupAndChildPopups();
-            this._overFolder.node = null;
-          }
-          if (this._overFolder.openTimer) {
-            this._overFolder.openTimer.cancel();
-            this._overFolder.openTimer = null;
-          }
-          if (this._overFolder.closeTimer) {
-            this._overFolder.closeTimer.cancel();
-            this._overFolder.closeTimer = null;
-          }
-        },
-
-        // This function returns information about where to drop when
-        // dragging over this menu--insertion point, child index to drop
-        // before, and folder to drop into.
-        _getDropPoint: function TBV_DO_getDropPoint(event) {
-          // Can't drop if the menu isn't a folder
-          var resultNode = this._self._resultNode;
-          if (!PlacesUtils.nodeIsFolder(this._self._result.root) ||
-              !PlacesUtils.nodeIsFolder(resultNode))
-            return null;
-
-          var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
-          // Loop through all the nodes to see which one this should
-          // get dropped in/above/below.
-          // Ignore static content at the top and bottom of the menu.
-          var start = (this._self._startMarker != -1) ? (this._self._startMarker + 1) : 0;
-          var end = (this._self._endMarker != -1) ? this._self._endMarker : this._self.childNodes.length;
-          for (var i = start; i < end; i++) {
-            var xulNode = this._self.childNodes[i];
-            var nodeY = xulNode.boxObject.y - this._self.boxObject.y;
-            var nodeHeight = xulNode.boxObject.height;
-            if (xulNode.node &&
-                PlacesUtils.nodeIsFolder(xulNode.node) &&
-                !PlacesUtils.nodeIsReadOnly(xulNode.node)) {
-              // This is a folder. If the mouse is in the top 25% of the
-              // node, drop above the folder.  If it's in the middle
-              // 50%, drop into the folder.  If it's past that, drop below.
-              if (event.clientY < nodeY + (nodeHeight * 0.25)) {
-                // Drop above this folder.
-                dropPoint.ip = new InsertionPoint(resultNode.itemId, i - start,
-                                                  -1);
-                dropPoint.beforeIndex = i;
-                return dropPoint;
-              }
-              else if (event.clientY < nodeY + (nodeHeight * 0.75)) {
-                // Drop inside this folder.
-                dropPoint.ip = new InsertionPoint(xulNode.node.itemId, -1, 1);
-                dropPoint.beforeIndex = i;
-                dropPoint.folderNode = xulNode;
-                return dropPoint;
-              }
-            } else {
-              // This is a non-folder node. If the mouse is above the middle,
-              // drop above the folder.  Otherwise, drop below.
-              if (event.clientY < nodeY + (nodeHeight / 2)) {
-                // Drop above this bookmark.
-                dropPoint.ip = new InsertionPoint(resultNode.itemId, i - start, -1);
-                dropPoint.beforeIndex = i;
-                return dropPoint;
-              }
-            }
-          }
-          // Should drop below the last node.
-          dropPoint.ip = new InsertionPoint(resultNode.itemId, -1, 1);
-          dropPoint.beforeIndex = -1;
-          return dropPoint;
-        },
-
-        // This function clears all of the dragover styles that were set when
-        // a menuitem was dragged over.
-        _clearStyles: function TBV_DO_clearStyles() {
-          this._self.removeAttribute("dragover");
-          for (var i = 0; i < this._self.childNodes.length; i++) {
-            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);
-        },
-
-        onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
-          PlacesControllerDragHelper.currentDropTarget = event.target;
-          var dropPoint = this._getDropPoint(event);
-          if (dropPoint == null)
-            return;
-
-          this._clearStyles();
-          if (dropPoint.folderNode) {
-            // Dragging over a folder; set the appropriate styles.
-            if (this._overFolder.node != dropPoint.folderNode) {
-              this._clearOverFolder();
-              this._overFolder.node = dropPoint.folderNode;
-              this._overFolder.openTimer = this._setTimer(this._overFolder.hoverTime);
-            }
-            dropPoint.folderNode.setAttribute("dragover-into", "true");
-          }
-          else {
-            // Dragging over a menuitem, set dragover-top/bottom to show where
-            // the item will be dropped and clear out any old folder info.
-            if (dropPoint.beforeIndex == -1) {
-              if (this._self.endMatch)
-                this._self.childNodes[this._self.endMatch].setAttribute("dragover-top", "true");
-              else
-                this._self.lastChild.setAttribute("dragover-bottom", "true");
-            }
-            else {
-              this._self.childNodes[dropPoint.beforeIndex].setAttribute("dragover-top", "true");
-            }
-            // Clear out old folder information
-            this._clearOverFolder();
-          }
-          this._self.setAttribute("dragover", "true");
-        },
-
-        onDrop: function TBV_DO_onDrop(event, dropData, session) {
-          var dropPoint = this._getDropPoint(event);
-          if (dropPoint == null)
-            return;
-          PlacesControllerDragHelper.onDrop(null, this._self, dropPoint.ip);
-        },
-
-        onDragExit: function TBV_DO_onDragExit(event, session) {
-          PlacesControllerDragHelper.currentDropTarget = null;
-          this._clearStyles();
-          // Close any folder being hovered over
-          if (this._overFolder.node)
-            this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
-          // The autoopened attribute is set when this folder was automatically
-          // opened after the user dragged over it.  If this attribute is set,
-          // auto-close the folder on drag exit.
-          if (this._self.hasAttribute("autoopened"))
-            this._closeMenuTimer = this._setTimer(this._overFolder.hoverTime);
-        },
-
-        getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
-          var flavorSet = new FlavourSet();
-          for (var i = 0; i < this._self.peerDropTypes.length; ++i)
-            flavorSet.appendFlavour(this._self.peerDropTypes[i]);
-          return flavorSet;
-        }
-      })]]></field>
-
       <property name="selType" readonly="true" onget="return 'single';"/>
 
       <method name="buildContextMenu">
         <parameter name="aPopup"/>
         <body><![CDATA[
           this._ensureInitialized();
           this.focus();
           return this.controller.buildContextMenu(aPopup);
@@ -938,71 +546,55 @@
           <![CDATA[
             if (window.content)
               window.content.focus();
           ]]>
         </body>
       </method>
     </implementation>
     <handlers>
-      <handler event="popupshowing">
-        if (event.target == this)
-          this.onPopupShowing();
+      <handler event="popupshowing" phase="capturing">
+        this._ensureInitialized();
+        if (event.target._resultNode)
+          this.onPopupShowing(event);
       </handler>
 
       <handler event="popuphidden">
-        if (event.target != this)
+        var popup = event.target;
+        if (!popup._resultNode)
           return;
 
         // UI performance: folder queries are cheap, keep the resultnode open
         // so we don't rebuild its contents whenever the popup is reopened.
-        if (!PlacesUtils.nodeIsFolder(this._resultNode)) {
-          this._resultNode.containerOpen = false;
-          this._built = false;
-        }
+        if (!PlacesUtils.nodeIsFolder(popup._resultNode))
+          popup._resultNode.containerOpen = false;
 
         // The autoopened attribute is set for folders which have been
         // automatically opened when dragged over.  Turn off this attribute
         // when the folder closes because it is no longer applicable.
-        this.removeAttribute("autoopened");
+        popup.removeAttribute("autoopened");
       </handler>
 
       <!-- 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.
+        // 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.
+        if (event.target.parentNode._resultNode) {
           this._cachedInsertionPoint = undefined;
-          this._selection = event.target.node || this._resultNode;
+          this._selection = event.target.node ||
+                            event.target.parentNode._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) {
-          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[
-        nsDragAndDrop.dragOver(event, this._DNDObserver);
-      ]]></handler>
-      <handler event="dragdrop"><![CDATA[
-        nsDragAndDrop.drop(event, this._DNDObserver);
-      ]]></handler>
-      <handler event="dragexit"><![CDATA[
-        nsDragAndDrop.dragExit(event, this._DNDObserver);
+        // |popupNode == menupopup| happens when the area between
+        // menuseparators is clicked.
+        this._selection = popupNode.node || popupNode.parentNode._resultNode;
+        this._cachedInsertionPoint = undefined;
       ]]></handler>
     </handlers>
   </binding>
 
 </bindings>
--- a/browser/components/places/content/moveBookmarks.js
+++ b/browser/components/places/content/moveBookmarks.js
@@ -47,22 +47,19 @@ var gMoveBookmarksDialog = {
 
     return this._foldersTree;
   },
 
   init: function() {
     this._nodes = window.arguments[0];
     this._tm = window.arguments[1];
 
-    // setTimeout until bug 373944 is fixed
-    setTimeout(function(aSelf) {
-        // select and expand the root node
-        aSelf.foldersTree.selectFolders([PlacesUtils.bookmarksRootId]);
-        aSelf.foldersTree.selectedNode.containerOpen = true;
-      }, 0, this);
+    // select and expand the root node
+    this.foldersTree.selectFolders([PlacesUtils.bookmarksRootId]);
+    this.foldersTree.selectedNode.containerOpen = true;
   },
 
   onOK: function MBD_onOK(aEvent) {
     var selectedNode = this.foldersTree.selectedNode;
     NS_ASSERT(selectedNode,
               "selectedNode must be set in a single-selection tree with initial selection set");
     var selectedFolderID = selectedNode.itemId;
 
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -49,23 +49,16 @@ function selectPlaceURI(placeURI) {
   PlacesOrganizer._places.selectPlaceURI(placeURI);
 }
 
 var PlacesOrganizer = {
   _places: null,
   _content: null,
 
   init: function PO_init() {
-    var self = this;
-    // on timeout because of the corresponding setTimeout()
-    // in the places tree binding's constructor
-    setTimeout(function() { self._init(); }, 0);
-  },
-
-  _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.
     var placeURI = "place:";
@@ -571,17 +564,18 @@ var PlacesOrganizer = {
     canvas.height = height;
   },
 
   onContentTreeSelect: function PO_onContentTreeSelect() {
     // If a textbox within a panel is focused, force-blur it so its contents
     // are saved
     if (gEditItemOverlay.itemId != -1) {
       var focusedElement = document.commandDispatcher.focusedElement;
-      if (focusedElement instanceof HTMLInputElement &&
+      if ((focusedElement instanceof HTMLInputElement ||
+           focusedElement instanceof HTMLTextAreaElement) &&
           /^editBMPanel.*/.test(focusedElement.parentNode.parentNode.id))
         focusedElement.blur();
     }
 
     var contentTree = document.getElementById("placeContent");
     var detailsDeck = document.getElementById("detailsDeck");
     if (contentTree.hasSelection) {
       detailsDeck.selectedIndex = 1;
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -119,17 +119,17 @@
   </broadcasterset>
 
   <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"
+         key="e" modifiers="accel,shift"
          oncommand="PlacesOrganizer.toggleDebugPanel();"/>
          
     <!-- Command Keys -->
     <key id="placesKey_find:all"
          command="OrganizerCommand_find:all" 
          key="&cmd.find.key;"
          modifiers="accel"/>
     <key id="placesKey_find:current"
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -49,17 +49,17 @@
           xmlns:xbl="http://www.mozilla.org/xbl"
           xmlns:html="http://www.w3.org/1999/xhtml"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="places-bar">
     <resources>
       <stylesheet src="chrome://browser/skin/places/places.css"/>
     </resources>
-    
+
     <content>
       <xul:vbox>
         <xul:hbox class="toolbar-drop-indicator-bar">
           <xul:hbox class="toolbar-drop-indicator"/>
         </xul:hbox>
         <xul:hbox flex="1">
           <xul:hbox class="bookmarks-toolbar-items places-toolbar-items" flex="1">
             <children/>
@@ -70,82 +70,69 @@
         </xul:hbox>
       </xul:vbox>
       <xul:hbox mousethrough="always"
                 flex="1"
                 pack="end">
         <xul:toolbarbutton type="menu"
                            class="chevron"
                            mousethrough="never"
-                           collapsed="true">
-          <xul:menupopup type="places"
-                         anonid="chevronPopup"
+                           collapsed="true"
+                           onpopupshowing="chevronPopupShowing(event);">
+          <xul:menupopup anonid="chevronPopup"
 #ifndef XP_MACOSX
                          context="placesContext"
 #endif
           />
         </xul:toolbarbutton>
       </xul:hbox>
     </content>
-    
+
     <implementation>
       <constructor><![CDATA[
-        // Support an asyncinit attribute that causes the view to populate 
-        // itself only after the window has been shown. This is to ensure we
-        // do not regress browser window show time (Ts/Txul)
-#if 0
-        if (this.hasAttribute("asyncinit")) {
-          var self = this;
-          //setTimeout(function() { self._init(); }, 0);
+        this._init();
+      ]]></constructor>
+
+      <destructor><![CDATA[
+        if (this._result) {
+          this._result.viewer = null;
+          this._result = null;
         }
-        else
-#endif
-          this._init();
-      ]]></constructor>
-      
-      <destructor><![CDATA[ 
-        PlacesUtils.annotations.removeObserver(this.genericAnnoObserver);
-        this._result.viewer = null;
-        this._result = null;
       ]]></destructor>
 
       <property name="controller"
                 readonly="true"
                 onget="return this._controller;"/>
 
       <method name="_init">
         <body><![CDATA[
         this._controller = new PlacesController(this);
         this.controllers.appendController(this._controller);
 
         var t = this;
         window.addEventListener("resize",
                                 function f(e) { t.updateChevron(e); },
                                 false);
 
-        PlacesUtils.annotations.addObserver(this.genericAnnoObserver);
-
         if (this.hasAttribute("place")) {
           // Do the initial build. 
           this.place = this.place;
         }
         ]]></body>
       </method>
 
       <field name="_dropIndicatorBar">document.getAnonymousElementByAttribute(this, "class", "toolbar-drop-indicator-bar")</field>
       <field name="_chevron">document.getAnonymousElementByAttribute(this, "class", "chevron")</field>
-      
+
       <field name="_selection">null</field>
-      
+
       <field name="_openedMenuButton">null</field>
-      
+
       <field name="_result">null</field>
 
-      <field name="_ignoreInvalidateContainer">false</field>
-
       <!-- nsIPlacesView -->
       <method name="getResult">
         <body><![CDATA[
           return this._result;
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
@@ -159,134 +146,124 @@
         <body><![CDATA[
           // Clear out references to existing nodes, since we'll be deleting and re-adding.
           if (this._DNDObserver._overFolder.node)
             this._DNDObserver._clearOverFolder();
           this._openedMenuButton = null;
 
           while (this.hasChildNodes())
             this.removeChild(this.firstChild);
-          const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-          var cc = this._result.root.childCount;
+
+          var rootNode = this._result.root;
+          var cc = rootNode.childCount;
           for (var i = 0; i < cc; ++i)
-            this.insertNewItem(this._result.root.getChild(i), null);
+            this.insertNewItem(rootNode.getChild(i), null);
 
-          var popup = this._chevron.firstChild;
-          popup.setAttribute("type", "places");
-          // This is set here and not in the XBL constructor for the menu because
-          // it doesn't get initialized properly in the constructor.
-#ifndef XP_MACOSX
-          // No context menus on menuitems on Mac
-          popup.setAttribute("context", "placesContext");
-#endif
-          popup.place = this.place;
-          var t = this;
-          popup.popupShowingCallback = function() { t.chevronPopupShowing(); };
+          var chevronPopup = this._chevron.lastChild;
+          if (chevronPopup.hasAttribute("type")) {
+            // Otherwise we'll set it when the chevron is enabled (see updateChevron)
+            chevronPopup.place = this.place;
+          }
+
+          while (chevronPopup.hasChildNodes())
+            chevronPopup.removeChild(chevronPopup.lastChild);
 
           // This needs to be in a timeout to make sure our boxObject has time
           // to get its proper size
+          var t = this;
           setTimeout(function() { t.updateChevron(); }, 0);
         ]]></body>
       </method>
 
       <method name="insertNewItem">
-        <parameter name="child"/>
-        <parameter name="before"/>
+        <parameter name="aChild"/>
+        <parameter name="aBefore"/>
         <body><![CDATA[
-          const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-          var title = child.title;
-          var button = null;
-          if (PlacesUtils.nodeIsURI(child)) {
-            button = document.createElementNS(XULNS, "toolbarbutton");
-          } else if (PlacesUtils.nodeIsSeparator(child)) {
-            button = document.createElementNS(XULNS, "toolbarseparator");
-          } else if (PlacesUtils.nodeIsContainer(child)) {
-            button = document.createElementNS(XULNS, "toolbarbutton");
-            button.setAttribute("type", "menu");
-            button.setAttribute("container", "true");
-            if (PlacesUtils.nodeIsLivemarkContainer(child)) {
-              button.setAttribute("livemark", "true");
-              var folder = child.itemId;
+          var type = aChild.type;
+          var button;
+          if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
+            button = document.createElement("toolbarseparator");
+          else {
+            button = document.createElement("toolbarbutton");
+            button.className = "bookmark-item";
+            button.setAttribute("label", aChild.title);
+            var iconURI = aChild.icon;
+            var iconURISpec = "";
+            if (iconURI) {
+              iconURISpec = iconURI.spec;
+              button.setAttribute("image", iconURISpec);
+            }
 
-              // duplicate nsLivemarkService.getSiteURI to avoid instantiating
-              // the service on startup.
-              var siteURIString;
-              try {
-                siteURIString = 
-                  PlacesUtils.annotations.getItemAnnotation(folder, "livemark/siteURI");
-              }
-              catch (ex) {}
-              // end duplication
+            if (PlacesUtils.containerTypes.indexOf(type) != -1) {
+              button.setAttribute("type", "menu");
+              button.setAttribute("container", "true");
+              if (iconURISpec == "chrome://browser/skin/places/livemarkItem.png")
+                button.setAttribute("livemark", "true");
 
-              if (siteURIString)
-                button.setAttribute("siteURI", siteURIString);
+              var popup = document.createElement("menupopup");
+              button.appendChild(popup);
+              popup._result = this._result;
+              popup._resultNode = asContainer(aChild);
+#ifndef XP_MACOSX
+              popup.setAttribute("context", "placesContext");
+#endif
+              this._containerNodesMap.push({ resultNode: aChild,
+                                             domNode: popup });
             }
-            var popup = document.createElementNS(XULNS, "menupopup");
-            popup.setAttribute("type", "places");
-            // This is set here and not in the XBL constructor for the menu because
-            // it doesn't get initialized properly in the constructor.
-#ifndef XP_MACOSX
-            // No context menus on menuitems on Mac
-            popup.setAttribute("context", "placesContext");
-#endif
-            button.appendChild(popup);
-            popup._result = this._result;
-            popup._resultNode = asContainer(child);
-            popup._containerNodesMap = this._containerNodesMap;
-            this._containerNodesMap.push({ resultNode: child,
-                                           domNode: popup });
           }
 
-          button.setAttribute("label", title);
-          if (child.icon)
-            button.setAttribute("image", child.icon.spec);
-          button.className = "menuitem-iconic bookmark-item";
-          button.node = child;
+          button.node = aChild;
           button.node.viewIndex = 0;
-          if (before)
-            this.insertBefore(button, before);
+          if (aBefore)
+            this.insertBefore(button, aBefore);
           else
             this.appendChild(button);
         ]]></body>
       </method>
 
       <method name="removeItem">
         <parameter name="child"/>
         <body><![CDATA[
           if (PlacesUtils.nodeIsContainer(child.node)) {
             for (var i=0; i < this._containerNodesMap.length; i++) {
-              if (this._containerNodesMap[i].resultNode == child.node)
+              if (this._containerNodesMap[i].resultNode == child.node) {
                 this._containerNodesMap.splice(i, 1);
+                break;
+              }
             }
           }
 
-          this.removeChild(child);
+          child.parentNode.removeChild(child);
         ]]></body>
       </method>
 
       <method name="chevronPopupShowing">
+        <parameter name="aEvent"/>
         <body><![CDATA[
-          var popup = this._chevron.firstChild;
+          var popup = aEvent.target;
+          if (popup != this._chevron.firstChild)
+            return;
+
           for (var i = 0; i < popup.childNodes.length; i++)
             popup.childNodes[i].hidden = !this.childNodes[i].collapsed;
         ]]></body>
       </method>
 
       <method name="getElementWidth">
         <parameter name="element"/>
         <body><![CDATA[
           var style = document.defaultView.getComputedStyle(element, "");
           var leftMargin = style.getPropertyValue("margin-left");
           leftMargin = leftMargin ? Math.round(parseFloat(leftMargin)) : 0;
           var rightMargin = style.getPropertyValue("margin-right");
           rightMargin = rightMargin ? Math.round(parseFloat(rightMargin)) : 0;
           return element.boxObject.width + leftMargin + rightMargin;
         ]]></body>
       </method>
-      
+
       <method name="updateChevron">
         <parameter name="event"/>
         <body><![CDATA[
           // Ignore events that aren't on the document or the window
           // (html document, tooltips, etc)
           // Do not ignore content window resizes, because they may
           // be the result of the toolbar being shown/hidden
           if (event && event.target != document && event.target != window &&
@@ -307,20 +284,27 @@
             child.collapsed = false;
             spaceLeft -= this.getElementWidth(child);
             var spaceNeeded = (i == this.childNodes.length - 1) ? 0 : chevronWidth;
             if (spaceLeft < spaceNeeded) {
               overflowed = true;
               child.collapsed = true;
             }
           }
-          this._chevron.collapsed = !overflowed;
+          if (!(this._chevron.collapsed = !overflowed)) {
+            // Attach the popup binding to the chevron popup
+            var popup = this._chevron.firstChild;
+            if (!popup.hasAttribute("type")) {
+              popup.setAttribute("place", this.place);
+              popup.setAttribute("type", "places");
+            }
+          }
         ]]></body>
       </method>
-      
+
       <!-- nsIPlacesView -->
       <property name="place">
         <getter><![CDATA[
           return this.getAttribute("place");
         ]]></getter>
         <setter><![CDATA[ 
           this.setAttribute("place", val);
 
@@ -409,17 +393,17 @@
           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 (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)
             }
@@ -437,129 +421,143 @@
 
       <!-- nsIPlacesView -->
       <method name="selectAll">
         <body><![CDATA[ 
           // Nothing
         ]]></body>
       </method>
 
-      <!-- Map for containerNodes<->domNodes. There's only one map per
-          result/viewer, i.e. the field is initialized just for the toolbar,
-          for sub menus it is set to the root's map -->
+      <!-- Map for containerNodes<->domNodes. -->
       <field name="_containerNodesMap">[]</field>
 
       <!-- nsINavHistoryResultViewer -->
       <field name="_viewer"><![CDATA[({
         _self: this,
 
-        _forwardToChildView:
-        function TV_V__forwardToChildView(aNode, aFunction, aArguments) {
+        _getPopupForContainer:
+        function PMV__getPopupForContainer(aNode) {
+          if (this._self._resultNode == aNode)
+            return this._self;
+
           for (var i=0; i < this._self._containerNodesMap.length; i++) {
-            if (this._self._containerNodesMap[i].resultNode == aNode) {
-              var childView = this._self._containerNodesMap[i].domNode._viewer;
-              childView[aFunction].apply(childView, aArguments);
-              return;
-            }
+            if (this._self._containerNodesMap[i].resultNode == aNode)
+              return this._self._containerNodesMap[i].domNode;
           }
           throw("Container view not found");
         },
 
         itemInserted: function TV_V_itemInserted(aParentNode, aNode, aIndex) {
           // don't insert new items into the toolbar
           // if the parent is not the root 
-          if (aParentNode == this._self.getResult().root) {
+          if (aParentNode == this._self.getResultNode()) {
             var children = this._self.childNodes;
             this._self.insertNewItem(aNode,
               aIndex < children.length ? children[aIndex] : null);
             this._self.updateChevron();
           }
           else {
-            this._forwardToChildView(aParentNode, "itemInserted", arguments);
+            var popup = this._getPopupForContainer(aParentNode);
+            if (!popup._built)
+              return;
+
+            var before = popup.childNodes[aIndex] || null;
+            this._self.insertNewItemToPopup(aNode, popup, before);
+            if (popup._emptyMenuItem)
+              popup._emptyMenuItem.hidden = true;
           }
         },
 
         itemRemoved: function TV_V_itemRemoved(aParentNode, aNode, aIndex) {
-          if (aParentNode == this._self.getResult().root) {
+          if (aParentNode == this._self.getResultNode()) {
             var children = this._self.childNodes;
             for (var i = 0; i < children.length; i++) {
               if (children[i].node == aNode) {
                 this._self.removeItem(children[i]);
                 this._self.updateChevron();
                 return;
               }
             }
           }
-          else
-            this._forwardToChildView(aParentNode, "itemRemoved", arguments);
+          else {
+            var popup = this._getPopupForContainer(aParentNode);
+            if (!popup._built)
+              return;
+
+            var children = popup.childNodes;
+            for (var i = 0; i < children.length; i++) {
+              if (children[i].node == aNode) {
+                this._self.removeItem(children[i]);
+                if (!popup.hasChildNodes() ||
+                    (popup.childNodes.length == 1 &&
+                     popup.firstChild == popup._emptyMenuItem)) {
+                  this._self._showEmptyMenuItem(popup);
+                }
+              }
+            }
+          }
         },
 
         itemChanged: function TV_V_itemChanged(aNode) {
           // this check can be removed once we fix bug #382397
           var parentNode = aNode.parent;
           if (!parentNode)
             return;
 
-          if (parentNode != this._self.getResult().root) {
-            this._forwardToChildView(parentNode, "itemChanged", arguments);
-            return;
-          }
-
-          var button;
-
-          var children = this._self.childNodes;
-          for (var i = 0; i < children.length; i++) {
-            if (children[i].node == aNode) {
-              button = children[i];
-              break;
+          var element;
+          var onToolbar = false;
+          if (parentNode == this._self.getResultNode()) {
+            onToolbar = true;
+            var children = this._self.childNodes;
+            for (var i = 0; i < children.length; i++) {
+              if (children[i].node == aNode) {
+                element = children[i];
+                break;
+              }
             }
           }
+          else {
+            var popup = this._getPopupForContainer(parentNode);
+            if (!popup._built)
+              return;
 
-          NS_ASSERT(button, "unable to find a toolbar element");
-
-          var title = aNode.title;
+            var children = popup.childNodes;
+            for (var i = 0; i < children.length; i++) {
+              if (children[i].node == aNode) {
+                element = children[i];
+                break;
+              }
+            }            
+          }
 
           if (PlacesUtils.nodeIsSeparator(aNode)) {
             // nothing to do when a separator changes
             return;
-          } 
-          else if (PlacesUtils.nodeIsContainer(aNode)) {
-            if (PlacesUtils.nodeIsLivemarkContainer(aNode)) {
-              var folder = aNode.itemId;
-              var siteURIString = "";
-              var siteURI = PlacesUtils.livemarks.getSiteURI(folder);
-              if (siteURI)
-                siteURIString = siteURI.spec;
-              if (siteURIString) {
-                if (button.getAttribute("siteURI") != siteURIString)
-                  button.setAttribute("siteURI", siteURIString);
-              }
-              else
-                button.removeAttribute("siteURI");
-            }
           }
 
-          if (aNode.icon) {
-            if (button.getAttribute("image") != aNode.icon.spec)
-              button.setAttribute("image", aNode.icon.spec);
+          var iconURI = aNode.icon;
+          if (iconURI) {
+            var spec = iconURI.spec;
+            if (element.getAttribute("image") != spec)
+              element.setAttribute("image", spec);
           }
           else
-            button.removeAttribute("image");
-        
-          // the only change that might require a chevron update
-          // is when the title changes
-          if (button.getAttribute("label") != title) {
-            button.setAttribute("label", title);
-            this._self.updateChevron();
+            element.removeAttribute("image");
+
+          var title = aNode.title;
+          if (element.getAttribute("label") != title) {
+            element.setAttribute("label", title);
+            if (onToolbar)
+              this._self.updateChevron();
           }
         },
 
         itemReplaced:
         function TV_V_itemReplaced(aParentNode, aOldNode, aNewNode, aIndex) {
-          if (aParentNode == this._self.getResult().root) {
+          if (aParentNode == this._self.getResultNode()) {
             var children = this._self.childNodes;
             for (var i = 0; i < children.length; i++) {
               if (children[i].node == aOldNode) {
                 var next = children[i].nextSibling;
                 this._self.removeItem(children[i]);
                 this._self.insertNewItem(aNewNode, next);
                 this._self.updateChevron();
                 return;
@@ -573,54 +571,47 @@
         containerOpened: function TV_V_containerOpened(aNode) {
           this.invalidateContainer(aNode);
         },
 
         containerClosed: function TV_V_containerClosed(aNode) {
           this.invalidateContainer(aNode);
         },
 
-        get ignoreInvalidateContainer() {
-          return this._self._ignoreInvalidateContainer;
-        },
-
-        set ignoreInvalidateContainer(val) {
-          return this._self._ignoreInvalidateContainer = val;
-        },
-
         invalidateContainer: function TV_V_invalidateContainer(aContainer) {
-          if (this._self._ignoreInvalidateContainer)
+          if (aContainer == this._self.getResultNode()) {
+            this._self._containerNodesMap.splice(0);
+            this._self._rebuild();
             return;
+          }
 
           function isChildOf(node, container) {
             var parent = node.parent;
             while (parent) {
               if (parent == container)
                 return true;
               parent = parent.parent;
             }
             return false;
           }
 
-          var viewerToRebuild = null;
+          var popupToRebuild = null;
           for (var i=0; i < this._self._containerNodesMap.length; i++) {
             var node = this._self._containerNodesMap[i].resultNode;
             
             if (node == aContainer)
-              viewerToRebuild = this._self._containerNodesMap[i].domNode._viewer;
-            if (isChildOf(node, aContainer))
+              popupToRebuild = this._self._containerNodesMap[i].domNode;
+            if (isChildOf(node, aContainer)) {
               this._self._containerNodesMap.splice(i,1);
+              i--;
+            }
           }
 
-          if (aContainer.containerOpen) {
-            if (viewerToRebuild)
-              viewerToRebuild._self._built = false;
-            else
-              this._self._rebuild();
-          }
+          if (popupToRebuild)
+            popupToRebuild._built = false;
         },
 
         invalidateAll: function TV_V_invalidateAll() {
           this._self._containerNodesMap.splice(0);
           this._self._rebuild();
         },
 
         sortingChanged: function TV_V_sortingChanged(aSortingMode) {
@@ -634,32 +625,31 @@
 
         // Menu buttons should be opened when the mouse drags over them, and closed
         // when the mouse drags off.  The overFolder object manages opening and closing
         // of folders when the mouse hovers.
         _overFolder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
 
         // timer for turning of indicator bar, to get rid of flicker
         _ibTimer: null, 
-        
+ 
         _setTimer: function TBV_DO_setTimer(time) {
           var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
           timer.initWithCallback(this, time, timer.TYPE_ONE_SHOT);
           return timer;
         },
-        
+
         // Function to process all timer notifications.
         notify: function TBV_DO_notify(timer) {
-        
           // Timer to turn off indicator bar.
           if (timer == this._ibTimer) {
             ib = this._self._dropIndicatorBar.removeAttribute('dragging');
             this._ibTimer = null;
           }
-          
+
           // Timer to open a menubutton that's being dragged over.
           if (timer == this._overFolder.openTimer) {
             // Set the autoopen attribute on the folder's menupopup so that
             // the menu will automatically close when the mouse drags off of it.
             this._overFolder.node.lastChild.setAttribute("autoopened", "true");
             this._overFolder.node.open = true;
             this._overFolder.openTimer = null;
           }
@@ -689,17 +679,17 @@
         },
         
         // The mouse is no longer dragging over the stored menubutton.
         // Close the menubutton, clear out drag styles, and clear all
         // timers for opening/closing it.
         _clearOverFolder: function TBV_DO_clearOverFolder() {
           if (this._overFolder.node && this._overFolder.node.lastChild) {
             if (!this._overFolder.node.lastChild.hasAttribute("dragover")) {
-              this._overFolder.node.lastChild.hidePopupAndChildPopups();
+              this._overFolder.node.lastChild.hidePopup();
             }
             this._overFolder.node.removeAttribute("dragover");
             this._overFolder.node = null;
           }
           if (this._overFolder.openTimer) {
             this._overFolder.openTimer.cancel();
             this._overFolder.openTimer = null;
           }
@@ -830,133 +820,45 @@
                 ind.style.marginRight = (this._self.childNodes[this._self.childNodes.length - 1].boxObject.x +
                                          this._self.childNodes[this._self.childNodes.length - 1].boxObject.width) -
                                         (this._self.childNodes[dropPoint.beforeIndex].boxObject.x) - 5 + 'px';
             }
             // Clear out old folder information
             this._clearOverFolder();
           }
         },
-        
+
         onDrop: function TBV_DO_onDrop(event, dropData, session) {
           var dropPoint = this._getDropPoint(event);
           if (dropPoint == null)
             return;
           PlacesControllerDragHelper.onDrop(null, this._self, dropPoint.ip);
         },
-        
+
         onDragExit: function TBV_DO_onDragExit(event, session) {
           // Set timer to turn off indicator bar (if we turn it off
           // here, dragenter might be called immediately after, creating
           // flicker.)
           if (this._ibTimer)
             this._ibTimer.cancel();
           this._ibTimer = this._setTimer(10);
           // Close any folder being hovered over
           if (this._overFolder.node)
             this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
           PlacesControllerDragHelper.currentDropTarget = null;
         },
-        
+
         getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
           var flavorSet = new FlavourSet();
           for (var i = 0; i < this._self.peerDropTypes.length; ++i)
             flavorSet.appendFlavour(this._self.peerDropTypes[i]);
           return flavorSet;
         }
-        
       })]]></field>
 
-      <!-- nsIAnnotationObserver -->
-      <field name="genericAnnoObserver"><![CDATA[({
-        // A generic nsIAnnotationObserver that provides methods for registering
-        // annotation-specific observers for this view.
-
-        // Inside this observer object's functions, "this" points to this
-        // observer object, while "_self" points to the toolbar XBL object.
-        _self: this,
-        
-        // Observers, indexed by annotation name.
-        _observers: {},
-        
-        addObserver: function TBV_GAO_addObserver(annoName, observer) {
-          if (!this._observers[annoName])
-            this._observers[annoName] = [];
-
-          // Register the observer, but only if it isn't already registered,
-          // so that we don't call the same observer twice for any given change.
-          if (this._observers[annoName].indexOf(observer) == -1)
-            this._observers[annoName].push(observer);
-        },
-        
-        removeObserver: function TBV_GAO_removeObserver(annoName, observer) {
-          NS_ASSERT(this._observers[annoName] &&
-                    this._observers[annoName].indexOf(observer) != -1,
-                    "can't remove annotation observer " + observer +
-                    " for annotation " + annoName + ": not registered");
-
-          this._observers[annoName] =
-            this._observers[annoName].filter(function(i) { observer != i });
-
-          if (this._observers[annoName].length == 0)
-            delete this._observers[annoName];
-        },
-
-        // Determines whether or not a given annotation change applies to
-        // this view.  A change applies if the annotation being changed is one
-        // we're observing, and the change is happening to a URI currently
-        // in this view.
-        _applies: function TBV_GAO_applies(uri, annoName) {
-          if (!this._observers[annoName])
-            return false;
-
-          return true;
-        },
-
-        onPageAnnotationSet:
-        function TBV_GAO_onPageAnnotationSet(uri, annoName) {
-          if (!this._applies(uri, annoName))
-            return;
-          
-          for (var i = 0; i < this._observers[annoName].length; i++)
-            this._observers[annoName][i].onPageAnnotationSet(uri, annoName);
-        },
-
-        onPageAnnotationRemoved:
-        function TBV_GAO_onPageAnnotationRemoved(uri, annoName) {
-          if (!this._applies(uri, annoName))
-            return;
-
-          for ( var i = 0; i < this._observers[annoName].length; i++)
-            this._observers[annoName][i].onPageAnnotationRemoved(uri, annoName);
-        },
-
-        onItemAnnotationSet:
-        function TBV_GAO_onItemAnnotationSet(aItemId, aAnnoName) {
-          if (!this._applies(aItemId, aAnnoName))
-            return;
-          
-          for (var i = 0; i < this._observers[aAnnoName].length; i++) {
-            this._observers[aAnnoName][i]
-                .onItemAnnotationSet(aItemId, aAnnoName);
-          }
-        },
-
-        onItemAnnotationRemoved:
-        function TBV_GAO_onItemAnnotationRemoved(aItemId, aAnnoName) {
-          if (!this._applies(aItemId, aAnnoName))
-            return;
-
-          for (var i = 0; i < this._observers[aAnnoName].length; i++) {
-            this._observers[aAnnoName][i]
-                .onItemAnnotationRemoved(aItemId, aAnnoName);
-          }
-        }
-      })]]></field>
-      
       <method name="checkForMenuEvent">
         <parameter name="event"/>
         <parameter name="action"/>
         <body><![CDATA[
           // It seems that even if the menu drag/drop event
           // handlers set their phase to capturing, toolbarbutton
           // menu events come to the toolbar first, and don't bubble.
           // So if this is a menu/menuitem, try to send the event to its
@@ -993,31 +895,121 @@
         <body><![CDATA[
           this.focus();
           return this.controller.buildContextMenu(aPopup);
         ]]></body>
       </method>
 
       <method name="destroyContextMenu">
         <parameter name="aPopup"/>
-        <body>
-          <![CDATA[
-            if (window.content)
-              window.content.focus();
-          ]]>
-        </body>
+        <body><![CDATA[
+          if (window.content)
+            window.content.focus();
+        ]]></body>
+      </method>
+
+      <method name="_showEmptyMenuItem">
+        <parameter name="aPopup"/>
+        <body><![CDATA[
+          if (aPopup._emptyMenuItem) {
+            aPopup._emptyMenuItem.hidden = false;
+            return;
+          }
+
+          var label = PlacesUtils.getString("bookmarksMenuEmptyFolder");
+          aPopup._emptyMenuItem = document.createElement("menuitem");
+          aPopup._emptyMenuItem.setAttribute("label", label);
+          aPopup._emptyMenuItem.setAttribute("disabled", true);
+          aPopup.appendChild(aPopup._emptyMenuItem);
+        ]]></body>
+      </method>
+
+      <method name="insertNewItemToPopup">
+        <parameter name="aChild"/>
+        <parameter name="aParentPopup"/>
+        <parameter name="aBefore"/>
+        <body><![CDATA[
+          var element =
+            PlacesUtils.createMenuItemForNode(aChild, this._containerNodesMap);
+          if (aBefore)
+            aParentPopup.insertBefore(element, aBefore);
+          else
+            aParentPopup.appendChild(element);
+        ]]></body>
+      </method>
+
+      <method name="_containerPopupShowing">
+        <parameter name="aPopup"/>
+        <body><![CDATA[
+          if (aPopup._built)
+            return;
+
+          // remove previous menu items
+          while (aPopup.hasChildNodes())
+            aPopup.removeChild(aPopup.firstChild);
+          // restore the empty-menu item if has been created already
+          if (aPopup._emptyMenuItem)
+            aPopup.appendChild(aPopup._emptyMenuItem);
+
+          var resultNode = aPopup._resultNode;
+          if (!resultNode.containerOpen)
+            resultNode.containerOpen = true;
+
+          var cc = resultNode.childCount;
+          if (cc > 0) {
+            if (aPopup._emptyMenuItem)
+              aPopup._emptyMenuItem.hidden = true;
+
+            for (var i = 0; i < cc; ++i) {
+              var child = resultNode.getChild(i);
+              this.insertNewItemToPopup(child, aPopup, null);
+            }
+          }
+          else {
+            // add element to show it is empty.
+            this._showEmptyMenuItem(aPopup);
+          }
+          aPopup._built = true;
+
+          if (!aPopup._DNDObserver)
+            aPopup._DNDObserver = new PlacesMenuDNDObserver(this, aPopup);
+        ]]></body>
+      </method>
+
+      <method name="_isChevronChild">
+        <parameter name="aChild"/>
+        <body><![CDATA[
+          if (!this._chevron.firstChild.hasAttribute("type"))
+            return false;
+
+          var parent = aChild.parentNode;
+          while (parent != this) {
+            if (parent == this._chevron)
+              return true;
+
+            parent = parent.parentNode;
+          }
+          return false;
+        ]]></body>
       </method>
     </implementation>
+
     <handlers>
       <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;
+        //
+        // Sub-menus are handled by the DOMMenuItemActive handler
+        var target = event.target;
+        if (target.parentNode != this)
+          return;
+
+        if (target.localName == "toolbarbutton" ||
+            target.localName == "toolbarseparator")
+          this._selection = 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>
@@ -1028,32 +1020,84 @@
       <handler event="dragdrop"><![CDATA[
         if (!this.checkForMenuEvent(event, "drop"))
           nsDragAndDrop.drop(event, this._DNDObserver);
       ]]></handler>
       <handler event="dragexit"><![CDATA[
         if (!this.checkForMenuEvent(event, "dragExit"))
           nsDragAndDrop.dragExit(event, this._DNDObserver);
       ]]></handler>
-      <handler event="popupshowing"><![CDATA[
-        var targetParent = event.originalTarget.parentNode;
+      <handler event="popupshowing" phase="capturing"><![CDATA[
+        var target = event.originalTarget;
+
+        // the chevron has its own view
+        if (this._isChevronChild(target))
+          return;
+
+        if (target._resultNode)
+          this._containerPopupShowing(target);
+
+        var targetParent = target.parentNode;
         if (targetParent.localName == "toolbarbutton" &&
             !PlacesControllerDragHelper.getSession())
           this._openedMenuButton = targetParent;
       ]]></handler>
       <handler event="popuphidden"><![CDATA[
-        var targetParent = event.originalTarget.parentNode;
+        var target = event.originalTarget;
+        if (!target._resultNode)
+          return;
+
+        // the chevron has its own view
+        if (this._isChevronChild(target))
+          return;
+
+        // UI performance: folder queries are cheap, keep the resultnode open
+        // so we don't rebuild its contents whenever the popup is reopened.
+        if (!PlacesUtils.nodeIsFolder(target._resultNode))
+          target._resultNode.containerOpen = false;
+
+        var targetParent = target.parentNode;
         if (targetParent.localName == "toolbarbutton" &&
             !PlacesControllerDragHelper.getSession())
           this._openedMenuButton = null;
       ]]></handler>
+
+       <!-- Set selected node on DOMMenuItemActive/contextmenu events
+           so that they're set up when command and click events fire. -->
+      <handler event="DOMMenuItemActive"><![CDATA[
+        // 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.
+        if (event.target.parentNode._resultNode) {
+          // the chevron has its own view
+          if (this._isChevronChild(event.target))
+            return;
+
+          this._cachedInsertionPoint = undefined;
+          this._selection = event.target.node ||
+                            event.target.parentNode._resultNode;
+        }
+      ]]></handler>
+      <handler event="contextmenu"><![CDATA[
+        // DOMMenuItemActive is not dispatched for disabled menuitems and
+        // menuseparators. Set the selection here manually.
+        var popupNode = document.popupNode;
+        // the chevron has its own view
+        if (this._isChevronChild(popupNode))
+          return;
+
+        // |popupNode == menupopup| happens when the area between menuseparators
+        // is clicked.
+        this._selection = popupNode.node || popupNode.parentNode._resultNode;
+        this._cachedInsertionPoint = undefined;
+      ]]></handler>
       <handler event="mousemove"><![CDATA[
         if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
           return;
-      
+
         var target = event.originalTarget;
         if (this._openedMenuButton != target &&
             target.localName == "toolbarbutton" &&
             target.type == "menu") {
           this._openedMenuButton.open = false;
           target.open = true;
         }
       ]]></handler>
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -44,24 +44,19 @@
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   
   <binding id="places-tree" extends="chrome://global/content/bindings/tree.xml#tree">
     <implementation implements="nsINavHistoryResultViewObserver">
       <constructor><![CDATA[
         this._controller = new PlacesController(this);
         this.controllers.appendController(this._controller);
 
-        // Force an initial build. 
-        // but do it on setTimeout() for bugs #373719 and bug #373721
-        // caused by a change for bug #267833
-        // note the corresponding setTimeout() in PO_init()
-        if (this.place) {
-          var self = this;
-          setTimeout(function() { self.place = self.place; }, 0);
-        }
+        // Force an initial build.
+        if (this.place)
+          this.place = this.place;
       ]]></constructor>
 
       <destructor><![CDATA[
         // Break the treeviewer->result->treeviewer cycle.
         // Note: unsetting the result's viewer also unsets
         // the viewer's reference to our treeBoxObject.
         var result = this.getResult();
         if (result)
@@ -78,21 +73,23 @@
         <getter><![CDATA[
           return this.treeBoxObject.view;
         ]]></getter>
         <setter><![CDATA[ 
           // Make sure the last result doesn't hold a reference to us anymore
           var resultview = this.getResultView();
           if (resultview)
             resultview.removeViewObserver(this._viewObserver);
+
           this.treeBoxObject.view = val;
           if (val) {
             val.QueryInterface(Ci.nsINavHistoryResultViewer)
                .addViewObserver(this._viewObserver, false);
           }
+          return val;
         ]]></setter>
       </property>
 
       <method name="getBestOptions">
         <body><![CDATA[
           // Get the best set of grouping options to use, either reuse the 
           // existing ones or create new ones. 
           var options = this.getResult().queryOptions;
@@ -109,21 +106,21 @@
         <parameter name="optionsFilter"/>
         <body><![CDATA[
           // preserve grouping
           var queryNode = asQuery(this.getResultNode());
           var options = queryNode.queryOptions.clone();
           if (optionsFilter)
             options = optionsFilter.filter(queryNode.getQueries({}), options, 
                                            optionsFilter.historyHandler);
-          
+
           var query = PlacesUtils.history.getNewQuery();
           query.searchTerms = filterString;
           query.onlyBookmarked = onlyBookmarks;
-          
+
           // Remove "group by folder" from the options list, because
           // nsNavHistory::RecursiveGroup doesn't support it.
           function isFolderGrouping(grouping, index, ary) {
             return grouping != Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER;
           }
           var groupings = options.getGroupingMode({});
           var folderGroupings = groupings.filter(isFolderGrouping);
           options.setGroupingMode(folderGroupings, folderGroupings.length);
@@ -151,17 +148,18 @@
       <property name="showRoot">
         <getter><![CDATA[
           return this.getAttribute("showRoot") == "true";
         ]]></getter>
         <setter><![CDATA[
           if (this.showRoot != val) {
             this.setAttribute("showRoot", val);
             // reload with the last place set
-            this.place = this.place;
+            if (this.place)
+              this.place = this.place;
           }
           return val;
         ]]></setter>
       </property>
 
       <!-- 
         Causes a particular node represented by the specified placeURI to be
         selected in the tree. All containers above the node in the hierarchy
@@ -273,17 +271,17 @@
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <property name="place">
         <getter><![CDATA[
           return this.getAttribute("place");
         ]]></getter>
-        <setter><![CDATA[ 
+        <setter><![CDATA[
           this.setAttribute("place", val);
 
           var queriesRef = { };
           var queryCountRef = { };
           var optionsRef = { };
           PlacesUtils.history.queryStringToQueries(val, queriesRef, queryCountRef, optionsRef);
           if (queryCountRef.value == 0)
             queriesRef.value = [PlacesUtils.history.getNewQuery()];
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -210,55 +210,59 @@ PlacesTreeView.prototype = {
       return;  // nothing to do
 
     const openLiteral = PlacesUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
     const trueLiteral = PlacesUtils.RDF.GetLiteral("true");
 
     var cc = aContainer.childCount;
     for (var i=0; i < cc; i++) {
       var curChild = aContainer.getChild(i);
+      var curChildType = curChild.type;
 
       // collapse all duplicates starting from here
       if (this._collapseDuplicates) {
         var showThis = { value: false };
         while (i <  cc - 1 &&
                this._canCollapseDuplicates(curChild, aContainer.getChild(i+1),
                                            showThis)) {
           if (showThis.value) {
             // collapse the first and use the second
             curChild.viewIndex = -1;
             curChild = aContainer.getChild(i+1);
+            curChildType = curChild.type;
           }
           else {
             // collapse the second and use the first
             aContainer.getChild(i+1).viewIndex = -1;
           }
           i++;
         }
       }
 
       // don't display separators when sorted
-      if (PlacesUtils.nodeIsSeparator(curChild)) {
+      if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
         if (this._result.sortingMode !=
             Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
           curChild.viewIndex = -1;
           continue;
         }
       }
 
       // add item
       curChild.viewIndex = aVisibleStartIndex + aVisible.length;
       aVisible.push(curChild);
 
       // recursively do containers
-      if (PlacesUtils.nodeIsContainer(curChild)) {
+      if (PlacesUtils.containerTypes.indexOf(curChildType) != -1) {
+        asContainer(curChild);
+
         var resource = this._getResourceForNode(curChild);
         var isopen = resource != null &&
-                     PlacesUtils.localStore.HasAssertion(resource, openLiteral, trueLiteral, true);
-        asContainer(curChild);
+                     PlacesUtils.localStore.HasAssertion(resource, openLiteral,
+                                                         trueLiteral, true);
         if (isopen != curChild.containerOpen)
           aToOpen.push(curChild);
         else if (curChild.containerOpen && curChild.childCount > 0)
           this._buildVisibleSection(curChild, aVisible, aToOpen, aVisibleStartIndex);
       }
     }
   },
 
@@ -366,17 +370,17 @@ PlacesTreeView.prototype = {
     if (replaceCount)
       this._tree.rowCountChanged(startReplacement, -replaceCount);
     if (newElements.length)
       this._tree.rowCountChanged(startReplacement, newElements.length);
     this._tree.endUpdateBatch();
 
     // now, open any containers that were persisted
     for (var i = 0; i < toOpenElements.length; i++) {
-      var item = asContainer(toOpenElements[i]);
+      var item = toOpenElements[i];
       var parent = item.parent;
       // avoid recursively opening containers
       while (parent) {
         if (parent.uri == item.uri)
           break;
         parent = parent.parent;
       }
       // if we don't have a parent, we made it all the way to the root
@@ -729,30 +733,19 @@ PlacesTreeView.prototype = {
   },
 
   containerOpened: function PTV_containerOpened(aItem) {
     this.invalidateContainer(aItem);
   },
 
   containerClosed: function PTV_containerClosed(aItem) {
     this.invalidateContainer(aItem);
-  },
-
-  get ignoreInvalidateContainer() {
-    return this._ignoreInvalidateContainer;
   },
 
-  set ignoreInvalidateContainer(val) {
-    return this._ignoreInvalidateContainer = val;
-  },
-
-  invalidateContainer: function PTV_invalidateContainer(aItem) {
-    if (this._ignoreInvalidateContainer)
-      return;
-
+  invalidateContainer: function PTV_invalidateContainer(aItem) {
     NS_ASSERT(this._result, "Got a notification but have no result!");
     if (!this._tree)
       return; // nothing to do, container is not visible
     var viewIndex = aItem.viewIndex;
     if (viewIndex >= this._visibleElements.length) {
       // be paranoid about visible indices since others can change it
       throw Cr.NS_ERROR_UNEXPECTED;
     }
@@ -803,18 +796,20 @@ PlacesTreeView.prototype = {
     }
   },
 
   get result() {
     return this._result;
   },
 
   set result(val) {
-    this._result = val;
-    this._finishInit();
+    if (this._result != val) {
+      this._result = val;
+      this._finishInit();
+    }
     return val;
   },
 
   addViewObserver: function PTV_addViewObserver(aObserver, aWeak) {
     if (aWeak)
       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
 
     if (this._observers.indexOf(aObserver) == -1)
@@ -870,17 +865,17 @@ PlacesTreeView.prototype = {
     if (viewIndex < 0)
       return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
 
     NS_ASSERT(this._visibleElements[viewIndex] == aNode,
               "Node's visible index and array out of sync");
     return viewIndex;
   },
 
-  _getResourceForNode : function PTV_getResourceForNode(aNode)
+  _getResourceForNode: function PTV_getResourceForNode(aNode)
   {
     var uri = aNode.uri;
     NS_ASSERT(uri, "if there is no uri, we can't persist the open state");
     return uri ? PlacesUtils.RDF.GetResource(uri) : null;
   },
 
   // nsITreeView
   get rowCount() {
@@ -911,63 +906,61 @@ PlacesTreeView.prototype = {
         break;
       case this.SESSION_STATUS_CONTINUE:
         aProperties.AppendElement(this._sessionContinueAtom);
         break
     }
   },
 
   getCellProperties: function PTV_getCellProperties(aRow, aColumn, aProperties) {
-    var columnType = aColumn.id || aColumn.element.getAttribute("anonid") ;
+    var columnType = aColumn.id || aColumn.element.getAttribute("anonid");
     if (columnType != "title")
       return;
 
     this._ensureValidRow(aRow);
     var node = this._visibleElements[aRow];
 
     if (PlacesUtils.nodeIsSeparator(node))
       aProperties.AppendElement(this._separatorAtom);
   },
 
   getColumnProperties: function(aColumn, aProperties) { },
 
   isContainer: function PTV_isContainer(aRow) {
     this._ensureValidRow(aRow);
     var node = this._visibleElements[aRow];
     if (PlacesUtils.nodeIsContainer(node)) {
+      // the root node is always expandable
+      if (!node.parent)
+        return true;
+
       // treat non-expandable queries as non-containers
       if (PlacesUtils.nodeIsQuery(node)) {
         asQuery(node);
-        if (node.queryOptions.expandQueries)
-          return true;
-        // the root node is always expandable
-        if (!node.parent)
-          return true;
-
-        return false;
+        return node.queryOptions.expandQueries;
       }
       return true;
     }
     return false;
   },
 
   isContainerOpen: function PTV_isContainerOpen(aRow) {
     this._ensureValidRow(aRow);
     if (!PlacesUtils.nodeIsContainer(this._visibleElements[aRow]))
       throw Cr.NS_ERROR_INVALID_ARG;
 
-    return asContainer(this._visibleElements[aRow]).containerOpen;
+    return this._visibleElements[aRow].containerOpen;
   },
 
   isContainerEmpty: function PTV_isContainerEmpty(aRow) {
     this._ensureValidRow(aRow);
     if (!PlacesUtils.nodeIsContainer(this._visibleElements[aRow]))
       throw Cr.NS_ERROR_INVALID_ARG;
 
-    return !asContainer(this._visibleElements[aRow]).hasChildren;
+    return !this._visibleElements[aRow].hasChildren;
   },
 
   isSeparator: function PTV_isSeparator(aRow) {
     this._ensureValidRow(aRow);
     return PlacesUtils.nodeIsSeparator(this._visibleElements[aRow]);
   },
 
   isSorted: function PTV_isSorted() {
@@ -998,18 +991,25 @@ PlacesTreeView.prototype = {
 
   hasNextSibling: function PTV_hasNextSibling(aRow, aAfterIndex) {
     this._ensureValidRow(aRow);
     if (aRow == this._visibleElements.length -1) {
       // this is the last thing in the list -> no next sibling
       return false;
     }
 
-    return this._visibleElements[aRow].indentLevel ==
-           this._visibleElements[aRow + 1].indentLevel;
+    var thisLevel = this._visibleElements[aRow].indentLevel;
+    for (var i = aAfterIndex + 1; i < this._visibleElements.length; ++i) {
+      var nextLevel = this._visibleElements[i].indentLevel;
+      if (nextLevel == thisLevel)
+        return true;
+      if (nextLevel < thisLevel)
+        break;
+    }
+    return false;
   },
 
   getLevel: function PTV_getLevel(aRow) {
     this._ensureValidRow(aRow);
 
     // Level is 0 for items at the root level, 1 for its children and so on.
     // If we don't show the result's root node, the level is simply the node's
     // indentLevel; if we do, it is the node's indentLevel increased by 1.
@@ -1128,17 +1128,16 @@ PlacesTreeView.prototype = {
     this._ensureValidRow(aRow);
 
     this._enumerateObservers("onToggleOpenState", [aRow]);
 
     var node = this._visibleElements[aRow];
     if (!PlacesUtils.nodeIsContainer(node))
       return; // not a container, nothing to do
 
-    asContainer(node);
     var resource = this._getResourceForNode(node);
     if (resource) {
       const openLiteral = PlacesUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
       const trueLiteral = PlacesUtils.RDF.GetLiteral("true");
 
       if (node.containerOpen)
         PlacesUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
       else
@@ -1299,10 +1298,9 @@ function PlacesTreeView(aShowRoot) {
   this._tree = null;
   this._result = null;
   this._collapseDuplicates = true;
   this._showSessions = false;
   this._selection = null;
   this._visibleElements = [];
   this._observers = [];
   this._showRoot = aShowRoot;
-  this._ignoreInvalidateContainer = false;
 }
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -90,142 +90,113 @@ var PlacesUtils = {
   // Place entries formatted as HTML anchors
   TYPE_HTML: "text/html",
   // Place entries as raw URL text
   TYPE_UNICODE: "text/unicode",
 
   /**
    * The Bookmarks Service.
    */
-  _bookmarks: null,
   get bookmarks() {
-    if (!this._bookmarks) {
-      this._bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-                        getService(Ci.nsINavBookmarksService);
-    }
-    return this._bookmarks;
+    delete this.bookmarks;
+    return this.bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
+                            getService(Ci.nsINavBookmarksService);
   },
 
   /**
    * The Nav History Service.
    */
-  _history: null,
   get history() {
-    if (!this._history) {
-      this._history = Cc["@mozilla.org/browser/nav-history-service;1"].
-                      getService(Ci.nsINavHistoryService);
-    }
-    return this._history;
+    delete this.history;
+    return this.history = Cc["@mozilla.org/browser/nav-history-service;1"].
+                          getService(Ci.nsINavHistoryService);
   },
 
   /**
    * The Live Bookmark Service.
    */
-  _livemarks: null,
   get livemarks() {
-    if (!this._livemarks) {
-      this._livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
-                        getService(Ci.nsILivemarkService);
-    }
-    return this._livemarks;
+    delete this.livemarks;
+    return this.livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
+                            getService(Ci.nsILivemarkService);
   },
 
   /**
    * The Annotations Service.
    */
-  _annotations: null,
   get annotations() {
-    if (!this._annotations) {
-      this._annotations = Cc["@mozilla.org/browser/annotation-service;1"].
-                          getService(Ci.nsIAnnotationService);
-    }
-    return this._annotations;
+    delete this.annotations;
+    return this.annotations = Cc["@mozilla.org/browser/annotation-service;1"].
+                              getService(Ci.nsIAnnotationService);
   },
 
   /**
    * The Favicons Service
    */
-  _favicons: null,
   get favicons() {
-    if (!this._favicons) {
-      this._favicons = Cc["@mozilla.org/browser/favicon-service;1"].
-                       getService(Ci.nsIFaviconService);
-    }
-    return this._favicons;
+    delete this.favicons;
+    return this.favicons = Cc["@mozilla.org/browser/favicon-service;1"].
+                           getService(Ci.nsIFaviconService);
   },
 
   /**
    * The Microsummary Service
    */
-  _microsummaries: null,
   get microsummaries() {
-    if (!this._microsummaries)
-      this._microsummaries = Cc["@mozilla.org/microsummary/service;1"].
-                             getService(Ci.nsIMicrosummaryService);
-    return this._microsummaries;
+    delete this.microsummaries;
+    return this.microsummaries = Cc["@mozilla.org/microsummary/service;1"].
+                                 getService(Ci.nsIMicrosummaryService);
   },
 
   /**
    * The Places Tagging Service
    */
   get tagging() {
-    if (!this._tagging)
-      this._tagging = Cc["@mozilla.org/browser/tagging-service;1"].
-                      getService(Ci.nsITaggingService);
-    return this._tagging;
+    delete this.tagging;
+    return this.tagging = Cc["@mozilla.org/browser/tagging-service;1"].
+                          getService(Ci.nsITaggingService);
   },
 
-  _RDF: null,
   get RDF() {
-    if (!this._RDF)
-      this._RDF = Cc["@mozilla.org/rdf/rdf-service;1"].
-                  getService(Ci.nsIRDFService);
-    return this._RDF;
+    delete this.RDF;
+    return this.RDF = Cc["@mozilla.org/rdf/rdf-service;1"].
+                      getService(Ci.nsIRDFService);
   },
 
-  _localStore: null,
   get localStore() {
-    if (!this._localStore)
-      this._localStore = this.RDF.GetDataSource("rdf:local-store");
-    return this._localStore;
+    delete this.localStore;
+    return this.localStore = this.RDF.GetDataSource("rdf:local-store");
   },
 
   get tm() {
-    return this.ptm.transactionManager;
+    delete this.tm;
+    return this.tm = this.ptm.transactionManager;
   },
 
-  _ptm: null,
   get ptm() {
-    if (!this._ptm) {
-      this._ptm = Cc["@mozilla.org/browser/placesTransactionsService;1"].
-                  getService(Components.interfaces.nsIPlacesTransactionsService);
-    }
-    return this._ptm;
+    delete this.ptm;
+    return this.ptm = Cc["@mozilla.org/browser/placesTransactionsService;1"].
+                      getService(Ci.nsIPlacesTransactionsService);
   },
 
-  _clipboard: null,
   get clipboard() {
-    if (!this._clipboard) {
-      this._clipboard = Cc["@mozilla.org/widget/clipboard;1"].
-                        getService(Ci.nsIClipboard);
-    }
-    return this._clipboard;
+    delete this.clipboard;
+    return this.clipboard = Cc["@mozilla.org/widget/clipboard;1"].
+                            getService(Ci.nsIClipboard);
   },
 
   /**
    * 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");
-    var ios = Cc["@mozilla.org/network/io-service;1"].
-              getService(Ci.nsIIOService);
-    return ios.newURI(aSpec, null, null);
+    return IO.newURI(aSpec);
   },
 
   /**
    * Wraps a string in a nsISupportsString wrapper
    * @param   aString
    *          The string to wrap
    * @returns A nsISupportsString object containing a string.
    */
@@ -234,26 +205,23 @@ var PlacesUtils = {
             createInstance(Ci.nsISupportsString);
     s.data = aString;
     return s;
   },
 
   /**
    * String bundle helpers
    */
-  __bundle: null,
   get _bundle() {
-    if (!this.__bundle) {
-      const PLACES_STRING_BUNDLE_URI =
+    const PLACES_STRING_BUNDLE_URI =
         "chrome://browser/locale/places/places.properties";
-      this.__bundle = Cc["@mozilla.org/intl/stringbundle;1"].
-                      getService(Ci.nsIStringBundleService).
-                      createBundle(PLACES_STRING_BUNDLE_URI);
-    }
-    return this.__bundle;
+    delete this._bundle;
+    return this._bundle = Cc["@mozilla.org/intl/stringbundle;1"].
+                          getService(Ci.nsIStringBundleService).
+                          createBundle(PLACES_STRING_BUNDLE_URI);
   },
 
   getFormattedString: function PU_getFormattedString(key, params) {
     return this._bundle.formatStringFromName(key, params, params.length);
   },
 
   getString: function PU_getString(key) {
     return this._bundle.GetStringFromName(key);
@@ -310,35 +278,32 @@ var PlacesUtils = {
   },
 
   /**
    * Determines whether or not a ResultNode is a URL item or not
    * @param   aNode
    *          A result node
    * @returns true if the node is a URL item, false otherwise
    */
+  uriTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI,
+             Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT,
+             Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT],
   nodeIsURI: function PU_nodeIsURI(aNode) {
     NS_ASSERT(aNode, "null node");
-
-    const NHRN = Ci.nsINavHistoryResultNode;
-    var type = aNode.type;
-    return type == NHRN.RESULT_TYPE_URI ||
-           type == NHRN.RESULT_TYPE_VISIT ||
-           type == NHRN.RESULT_TYPE_FULL_VISIT;
+    return this.uriTypes.indexOf(aNode.type) != -1;
   },
 
   /**
    * Determines whether or not a ResultNode is a Query item or not
    * @param   aNode
    *          A result node
    * @returns true if the node is a Query item, false otherwise
    */
   nodeIsQuery: function PU_nodeIsQuery(aNode) {
     NS_ASSERT(aNode, "null node");
-
     return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY;
   },
 
   /**
    * Determines if a node is read only (children cannot be inserted, sometimes
    * they cannot be removed depending on the circumstance)
    * @param   aNode
    *          A result node
@@ -357,36 +322,33 @@ var PlacesUtils = {
   /**
    * Determines whether or not a ResultNode is a host folder or not
    * @param   aNode
    *          A result node
    * @returns true if the node is a host item, false otherwise
    */
   nodeIsHost: function PU_nodeIsHost(aNode) {
     NS_ASSERT(aNode, "null node");
-
     return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST;
   },
 
   /**
    * Determines whether or not a ResultNode is a container item or not
    * @param   aNode
    *          A result node
    * @returns true if the node is a container item, false otherwise
    */
+  containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
+                   Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
+                   Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST,
+                   Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY,
+                   Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
   nodeIsContainer: function PU_nodeIsContainer(aNode) {
     NS_ASSERT(aNode, "null node");
-
-    const NHRN = Ci.nsINavHistoryResultNode;
-    var type = aNode.type;
-    return type == NHRN.RESULT_TYPE_HOST ||
-           type == NHRN.RESULT_TYPE_QUERY ||
-           type == NHRN.RESULT_TYPE_FOLDER ||
-           type == NHRN.RESULT_TYPE_DAY ||
-           type == NHRN.RESULT_TYPE_DYNAMIC_CONTAINER;
+    return this.containerTypes.indexOf(aNode.type) != -1;
   },
 
   /**
    * Determines whether or not a result-node is a dynamic-container item.
    * The dynamic container result node type is for dynamically created
    * containers (e.g. for the file browser service where you get your folders
    * in bookmark menus).
    * @param   aNode
@@ -443,24 +405,32 @@ var PlacesUtils = {
    *          The node to look up
    * @returns The index of the node within its parent container, or -1 if the
    *          node was not found or the node specified has no parent.
    */
   getIndexOfNode: function PU_getIndexOfNode(aNode) {
     NS_ASSERT(aNode, "null node");
 
     var parent = aNode.parent;
-    if (!parent || !PlacesUtils.nodeIsContainer(parent))
+    if (!parent)
       return -1;
     var wasOpen = parent.containerOpen;
-    parent.containerOpen = true;
+    var result, oldViewer;
+    if (!wasOpen) {
+      result = parent.parentResult;
+      oldViewer = result.viewer;
+      result.viewer = null;
+      parent.containerOpen = true;
+    }
     var cc = parent.childCount;
-    asContainer(parent);
     for (var i = 0; i < cc && parent.getChild(i) != aNode; ++i);
-    parent.containerOpen = wasOpen;
+    if (!wasOpen) {
+      parent.containerOpen = false;
+      result.viewer = oldViewer;
+    }
     return i < cc ? i : -1;
   },
 
   /**
    * String-wraps a result node according to the rules of the specified
    * content type.
    * @param   aNode
    *          The Result node to wrap (serialize)
@@ -645,17 +615,17 @@ var PlacesUtils = {
    *          The URI of the item being copied
    * @param   aContainer
    *          The container being copied into
    * @param   aIndex
    *          The index within the container the item is copied to
    * @returns A nsITransaction object that performs the copy.
    */
   _getURIItemCopyTransaction: function (aData, aContainer, aIndex) {
-    return this.ptm.createItem(this._uri(aData.uri), aContainer, aIndex,
+    return this.ptm.createItem(IO.newURI(aData.uri), aContainer, aIndex,
                                aData.title, "");
   },
 
   /**
    * Get a transaction for copying a bookmark item from one container to
    * another.
    * @param   aID
    *          The identifier of the bookmark item being copied
@@ -666,17 +636,17 @@ var PlacesUtils = {
    * @param   [optional] aExcludeAnnotations
    *          Optional, array of annotations (listed by their names) to exclude
    *          when copying the item.
    * @returns A nsITransaction object that performs the copy.
    */
   _getBookmarkItemCopyTransaction:
   function PU__getBookmarkItemCopyTransaction(aData, aContainer, aIndex,
                                               aExcludeAnnotations) {
-    var itemURL = this._uri(aData.uri);
+    var itemURL = IO.newURI(aData.uri);
     var itemTitle = aData.title;
     var keyword = aData.keyword;
     var annos = aData.annos;
     if (aExcludeAnnotations) {
       annos =
         annos.filter(function(aValue, aIndex, aArray) {
                        return aExcludeAnnotations.indexOf(aValue.name) == -1;
                     });
@@ -719,18 +689,18 @@ var PlacesUtils = {
             var title = node.folder.title;
             var annos = node.folder.annos;
             var folderItemsTransactions =
               getChildItemsTransactions(node.children);
             txn = self.ptm.createFolder(title, -1, index, annos,
                                         folderItemsTransactions);
           }
           else { // node is a livemark
-            var feedURI = self._uri(node.uri.feed);
-            var siteURI = self._uri(node.uri.site);
+            var feedURI = IO.newURI(node.uri.feed);
+            var siteURI = IO.newURI(node.uri.site);
             txn = self.ptm.createLivemark(feedURI, siteURI, node.title,
                                           aContainer, index, node.annos);
           }
         }
         else if (node.type == self.TYPE_X_MOZ_PLACE_SEPARATOR)
           txn = self.ptm.createSeparator(-1, index);
         else if (node.type == self.TYPE_X_MOZ_PLACE)
           txn = self._getBookmarkItemCopyTransaction(node, -1, index);
@@ -771,29 +741,29 @@ var PlacesUtils = {
         var parts = blob.split("\n");
         // data in this type has 2 parts per entry, so if there are fewer
         // than 2 parts left, the blob is malformed and we should stop
         if (parts.length % 2)
           break;
         for (var i = 0; i < parts.length; i=i+2) {
           var uriString = parts[i];
           var titleString = parts[i+1];
-          // note:  this._uri() will throw if uriString is not a valid URI
-          if (this._uri(uriString)) {
+          // note:  IO.newURI() will throw if uriString is not a valid URI
+          if (IO.newURI(uriString)) {
             nodes.push({ uri: uriString,
                          title: titleString ? titleString : uriString });
           }
         }
         break;
       case this.TYPE_UNICODE:
         var parts = blob.split("\n");
         for (var i = 0; i < parts.length; i++) {
           var uriString = parts[i];
-          // note: this._uri() will throw if uriString is not a valid URI
-          if (uriString != "" && this._uri(uriString))
+          // note: IO.newURI() will throw if uriString is not a valid URI
+          if (uriString != "" && IO.newURI(uriString))
             nodes.push({ uri: uriString, title: uriString });
         }
         break;
       default:
         LOG("Cannot unwrap data of type " + type);
         throw Cr.NS_ERROR_INVALID_ARG;
     }
     return nodes;
@@ -821,18 +791,18 @@ var PlacesUtils = {
     case this.TYPE_X_MOZ_PLACE_CONTAINER:
       if (data.folder) {
         // Place is a folder.
         if (copy)
           return this._getFolderCopyTransaction(data, container, index);
       }
       else if (copy) {
         // Place is a Livemark Container, should be reinstantiated
-        var feedURI = this._uri(data.uri.feed);
-        var siteURI = this._uri(data.uri.site);
+        var feedURI = IO.newURI(data.uri.feed);
+        var siteURI = IO.newURI(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);
 
@@ -850,17 +820,17 @@ var PlacesUtils = {
         // There is no data in a separator, so copying it just amounts to
         // inserting a new separator.
         return this.ptm.createSeparator(container, index);
       }
       break;
     default:
       if (type == this.TYPE_X_MOZ_URL || type == this.TYPE_UNICODE) {
         var title = (type == this.TYPE_X_MOZ_URL) ? data.title : data.uri;
-        return this.ptm.createItem(this._uri(data.uri), container, index,
+        return this.ptm.createItem(IO.newURI(data.uri), container, index,
                                    title);
       }
       return null;
     }
     if (data.id <= 0)
       return null;
 
     // Move the item otherwise
@@ -887,17 +857,16 @@ var PlacesUtils = {
     var query = this.history.getNewQuery();
     query.setFolders([aFolderId], 1);
     var options = this.history.getNewQueryOptions();
     options.excludeItems = aExcludeItems;
     options.expandQueries = aExpandQueries;
 
     var result = this.history.executeQuery(query, options);
     result.root.containerOpen = true;
-    asContainer(result.root);
     return result;
   },
 
   /**
    * Methods to show the bookmarkProperties dialog in its various modes.
    *
    * The showMinimalAdd* methods open the dialog by its alternative URI. Thus
    * they persist the dialog dimensions separately from the showAdd* methods.
@@ -1265,17 +1234,17 @@ var PlacesUtils = {
    * bookmarked (see bug 224521).
    * @param aURINode
    *        a URI node
    * @return true if it's safe to open the node in the browser, false otherwise.
    *
    */
   checkURLSecurity: function PU_checkURLSecurity(aURINode) {
     if (!this.nodeIsBookmark(aURINode)) {
-      var uri = this._uri(aURINode.uri);
+      var uri = IO.newURI(aURINode.uri);
       if (uri.schemeIs("javascript") || uri.schemeIs("data")) {
         const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
         var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
                              getService(Ci.nsIStringBundleService).
                              createBundle(BRANDING_BUNDLE_URI).
                              GetStringFromName("brandShortName");
         var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                             getService(Ci.nsIPromptService);
@@ -1552,25 +1521,37 @@ var PlacesUtils = {
       let contents = this.getFolderContents(aNode.itemId, false, false).root;
       for (let i = 0; i < contents.childCount; ++i) {
         let child = contents.getChild(i);
         if (this.nodeIsURI(child))
           urls.push(child.uri);
       }
     }
     else {
-      let wasOpen = aNode.containerOpen;
-      if (!wasOpen)
-        aNode.containerOpen = true;
-      for (let i = 0; i < aNode.childCount; ++i) {
-        let child = aNode.getChild(i);
-        if (this.nodeIsURI(child))
-          urls.push(child.uri);
+      let result, oldViewer;
+      try {
+        let wasOpen = aNode.containerOpen;
+        if (!wasOpen) {
+          result = aNode.parentResult;
+          oldViewer = result.viewer;
+          result.viewer = null;
+          aNode.containerOpen = true;
+        }
+        for (let i = 0; i < aNode.childCount; ++i) {
+          let child = aNode.getChild(i);
+          if (this.nodeIsURI(child))
+            urls.push(child.uri);
+        }
+        if (!wasOpen)
+          aNode.containerOpen = false;
       }
-      aNode.containerOpen = wasOpen;
+      finally {
+        if (oldViewer)
+          result.viewer = oldViewer;
+      }
     }
 
     return urls;
   },
 
   /**
    * Gives the user a chance to cancel loading lots of tabs at once
    */
@@ -1641,32 +1622,80 @@ var PlacesUtils = {
     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);
+    delete 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;
+  },
+
+  /**
+   * Helper for the toolbar and menu views
+   */
+  createMenuItemForNode: function(aNode, aContainersMap) {
+    var element;
+    var type = aNode.type;
+    if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
+      element = document.createElement("menuseparator");
+    else {
+      var iconURI = aNode.icon;
+      var iconURISpec = "";
+      if (iconURI)
+        iconURISpec = iconURI.spec;
+
+      if (this.uriTypes.indexOf(type) != -1) {
+        element = document.createElement("menuitem");
+        element.setAttribute("statustext", aNode.uri);
+        element.className = "menuitem-iconic bookmark-item";
       }
+      else if (this.containerTypes.indexOf(type) != -1) {
+        element = document.createElement("menu");
+        element.setAttribute("container", "true");
+        
+        if (iconURISpec == "chrome://browser/skin/places/livemarkItem.png")
+          element.setAttribute("livemark", "true");
+
+        var popup = document.createElement("menupopup");
+        popup._resultNode = asContainer(aNode);
+#ifndef XP_MACOSX
+        // no context menu on mac
+        popup.setAttribute("context", "placesContext");
+#endif
+        element.appendChild(popup);
+        if (aContainersMap)
+          aContainersMap.push({ resultNode: aNode, domNode: popup });
+        element.className = "menu-iconic bookmark-item";
+      }
+      else
+        throw "Unexpected node";
+
+      element.setAttribute("label", aNode.title);
+      if (iconURISpec)
+        element.setAttribute("image", iconURISpec);
     }
-    return this._placesFlavors;
+    element.node = aNode;
+    element.node.viewIndex = 0;
+
+    return element;
   }
 };
 
 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
@@ -116,21 +116,23 @@ static NS_DEFINE_CID(kParserCID, NS_PARS
 #define KEY_ICON_LOWER "icon"
 #define KEY_ICON_URI_LOWER "icon_uri"
 #define KEY_SHORTCUTURL_LOWER "shortcuturl"
 #define KEY_POST_DATA_LOWER "post_data"
 #define KEY_NAME_LOWER "name"
 #define KEY_MICSUM_GEN_URI_LOWER "micsum_gen_uri"
 #define KEY_DATE_ADDED_LOWER "add_date"
 #define KEY_LAST_MODIFIED_LOWER "last_modified"
+#define KEY_GENERATED_TITLE_LOWER "generated_title"
 
 #define LOAD_IN_SIDEBAR_ANNO NS_LITERAL_CSTRING("bookmarkProperties/loadInSidebar")
 #define DESCRIPTION_ANNO NS_LITERAL_CSTRING("bookmarkProperties/description")
 #define POST_DATA_ANNO NS_LITERAL_CSTRING("URIProperties/POSTData")
 #define LAST_CHARSET_ANNO NS_LITERAL_CSTRING("URIProperties/characterSet")
+#define STATIC_TITLE_ANNO NS_LITERAL_CSTRING("bookmarks/staticTitle")
 
 #define BOOKMARKS_MENU_ICON_URI "chrome://browser/skin/places/bookmarksMenu.png"
 
 // define to get debugging messages on console about import/export
 //#define DEBUG_IMPORT
 //#define DEBUG_EXPORT
 
 #if defined(XP_WIN) || defined(XP_OS2)
@@ -203,16 +205,23 @@ public:
   // This is cleared whenever we hit a <h3>, so that we know NOT to save this
   // with a bookmark, but to keep it until 
   nsCOMPtr<nsIURI> mPreviousLink;
 
   // contains the URL of the previous livemark, so that when the link ends,
   // and the livemark title is known, we can create it.
   nsCOMPtr<nsIURI> mPreviousFeed;
 
+  // contains the text content of the previous microsummary, so that when the
+  // link ends, we can replace the bookmark's title with it and store the user's
+  // title in the staticTitle annotation.
+  nsString mPreviousMicrosummaryText;
+
+  nsCOMPtr<nsIMicrosummary> mPreviousMicrosummary;
+
   void ConsumeHeading(nsAString* aHeading, ContainerType* aContainerType)
   {
     *aHeading = mPreviousText;
     *aContainerType = mLastContainerType;
     mPreviousText.Truncate();
   }
 
   // Contains the id of an imported, or newly created bookmark.
@@ -786,28 +795,33 @@ BookmarkContentSink::HandleLinkBegin(con
   // We need to make sure that the feed URIs from previous frames are emptied. 
   frame.mPreviousFeed = nsnull;
 
   // We need to make sure that the bookmark id from previous frames are emptied. 
   frame.mPreviousId = 0;
 
   // mPreviousText will hold our link text, clear it so that can be appended to
   frame.mPreviousText.Truncate();
+
+  // Empty our microsummary items from the previous frame.
+  frame.mPreviousMicrosummary = nsnull;
+  frame.mPreviousMicrosummaryText.Truncate();
   
   // get the attributes we care about
   nsAutoString href;
   nsAutoString feedUrl;
   nsAutoString icon;
   nsAutoString iconUri;
   nsAutoString lastCharset;
   nsAutoString keyword;
   nsAutoString postData;
   nsAutoString webPanel;
   nsAutoString itemId;
   nsAutoString micsumGenURI;
+  nsAutoString generatedTitle;
   nsAutoString dateAdded;
   nsAutoString lastModified;
 
   PRInt32 attrCount = node.GetAttributeCount();
   for (PRInt32 i = 0; i < attrCount; i ++) {
     const nsAString& key = node.GetKeyAt(i);
     if (key.LowerCaseEqualsLiteral(KEY_HREF_LOWER)) {
       href = node.GetValueAt(i);
@@ -822,32 +836,35 @@ BookmarkContentSink::HandleLinkBegin(con
     } else if (key.LowerCaseEqualsLiteral(KEY_SHORTCUTURL_LOWER)) {
       keyword = node.GetValueAt(i);
     } else if (key.LowerCaseEqualsLiteral(KEY_POST_DATA_LOWER)) {
       postData = node.GetValueAt(i);
     } else if (key.LowerCaseEqualsLiteral(KEY_WEB_PANEL_LOWER)) {
       webPanel = node.GetValueAt(i);
     } else if (key.LowerCaseEqualsLiteral(KEY_MICSUM_GEN_URI_LOWER)) {
       micsumGenURI = node.GetValueAt(i);
+    } else if (key.LowerCaseEqualsLiteral(KEY_GENERATED_TITLE_LOWER)) {
+      generatedTitle = node.GetValueAt(i);
     } else if (key.LowerCaseEqualsLiteral(KEY_DATE_ADDED_LOWER)) {
       dateAdded = node.GetValueAt(i);
     } else if (key.LowerCaseEqualsLiteral(KEY_LAST_MODIFIED_LOWER)) {
       lastModified = node.GetValueAt(i);
     }
   }
   href.Trim(kWhitespace);
   feedUrl.Trim(kWhitespace);
   icon.Trim(kWhitespace);
   iconUri.Trim(kWhitespace);
   lastCharset.Trim(kWhitespace);
   keyword.Trim(kWhitespace);
   postData.Trim(kWhitespace);
   webPanel.Trim(kWhitespace);
   itemId.Trim(kWhitespace);
   micsumGenURI.Trim(kWhitespace);
+  generatedTitle.Trim(kWhitespace);
   dateAdded.Trim(kWhitespace);
   lastModified.Trim(kWhitespace);
 
   // For feeds, get the feed URL. If it is invalid, it will leave mPreviousFeed
   // NULL and we'll continue trying to create it as a normal bookmark.
   if (!feedUrl.IsEmpty()) {
     NS_NewURI(getter_AddRefs(frame.mPreviousFeed),
               NS_ConvertUTF16toUTF8(feedUrl), nsnull);
@@ -941,25 +958,22 @@ BookmarkContentSink::HandleLinkBegin(con
   if (webPanel.LowerCaseEqualsLiteral("true")) {
     // set load-in-sidebar annotation for the bookmark
     mAnnotationService->SetItemAnnotationInt32(frame.mPreviousId, LOAD_IN_SIDEBAR_ANNO,
                                                1, 0,
                                                nsIAnnotationService::EXPIRE_NEVER);
   }
 
   // import microsummary
-  // Note: expiration and generated title are ignored, and will be recalculated
-  // by the microsummary service
   if (!micsumGenURI.IsEmpty()) {
     nsCOMPtr<nsIURI> micsumGenURIObject;
     if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(micsumGenURIObject), micsumGenURI))) {
-      nsCOMPtr<nsIMicrosummary> microsummary;
       mMicrosummaryService->CreateMicrosummary(frame.mPreviousLink, micsumGenURIObject,
-                                               getter_AddRefs(microsummary));
-      mMicrosummaryService->SetMicrosummary(frame.mPreviousId, microsummary);
+                                               getter_AddRefs(frame.mPreviousMicrosummary));
+      frame.mPreviousMicrosummaryText = generatedTitle;
     }
   }
 
   // import last charset
   if (!lastCharset.IsEmpty()) {
     PRBool hasCharset = PR_FALSE;
     mAnnotationService->PageHasAnnotation(frame.mPreviousLink,
                                           LAST_CHARSET_ANNO, &hasCharset);
@@ -1043,17 +1057,27 @@ BookmarkContentSink::HandleLinkEnd()
     }
   }
   else if (frame.mPreviousLink) {
 #ifdef DEBUG_IMPORT
     PrintNesting();
     printf("Creating bookmark '%s' %lld\n",
            NS_ConvertUTF16toUTF8(frame.mPreviousText).get(), frame.mPreviousId);
 #endif
-    mBookmarksService->SetItemTitle(frame.mPreviousId, frame.mPreviousText);
+    if (frame.mPreviousMicrosummary) {
+      rv = mAnnotationService->SetItemAnnotationString(frame.mPreviousId, STATIC_TITLE_ANNO,
+                                                       frame.mPreviousText, 0,
+                                                       nsIAnnotationService::EXPIRE_NEVER);
+      NS_ASSERTION(NS_SUCCEEDED(rv), "Could not store user's bookmark title!");
+
+      mBookmarksService->SetItemTitle(frame.mPreviousId, frame.mPreviousMicrosummaryText);
+      mMicrosummaryService->SetMicrosummary(frame.mPreviousId, frame.mPreviousMicrosummary);
+    }
+    else
+      mBookmarksService->SetItemTitle(frame.mPreviousId, frame.mPreviousText);
   }
 
   // Set last-modified-date for bookmarks and livemarks here so that the
   // imported date overrides the date from the call to that sets the description
   // that we made above.
   if (frame.mPreviousId > 0 && frame.mPreviousLastModifiedDate > 0) {
     rv = mBookmarksService->SetItemLastModified(frame.mPreviousId, frame.mPreviousLastModifiedDate);
     NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemLastModified failed");
--- a/browser/components/preferences/applications.js
+++ b/browser/components/preferences/applications.js
@@ -713,16 +713,24 @@ var feedHandlerInfo = {
 
   set alwaysAskBeforeHandling(aNewValue) {
     if (aNewValue == true)
       this.element(PREF_FEED_SELECTED_ACTION).value = "ask";
     else
       this.element(PREF_FEED_SELECTED_ACTION).value = "reader";
   },
 
+  // Whether or not we are currently storing the action selected by the user.
+  // We use this to suppress notification-triggered updates to the list when
+  // we make changes that may spawn such updates, specifically when we change
+  // the action for the feed type, which results in feed preference updates,
+  // which spawn "pref changed" notifications that would otherwise cause us
+  // to rebuild the view unnecessarily.
+  _storingAction: false,
+
 
   //**************************************************************************//
   // nsIMIMEInfo
 
   get primaryExtension() {
     return "xml";
   },
 
@@ -876,17 +884,17 @@ var gApplicationsPane = {
 
 
   //**************************************************************************//
   // nsIObserver
 
   observe: function (aSubject, aTopic, aData) {
     // Rebuild the list when there are changes to preferences that influence
     // whether or not to show certain entries in the list.
-    if (aTopic == "nsPref:changed") {
+    if (aTopic == "nsPref:changed" && !this._storingAction) {
       // These two prefs alter the list of visible types, so we have to rebuild
       // that list when they change.
       if (aData == PREF_SHOW_PLUGINS_IN_LIST ||
           aData == PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS) {
         this._rebuildVisibleTypes();
         this._sortVisibleTypes();
       }
 
@@ -1445,16 +1453,27 @@ var gApplicationsPane = {
     this._filter.select();
   },
 
 
   //**************************************************************************//
   // Changes
 
   onSelectAction: function(aActionItem) {
+    this._storingAction = true;
+
+    try {
+      this._storeAction(aActionItem);
+    }
+    finally {
+      this._storingAction = false;
+    }
+  },
+
+  _storeAction: function(aActionItem) {
     var typeItem = this._list.selectedItem;
     var handlerInfo = this._handledTypes[typeItem.type];
 
     if (aActionItem.hasAttribute("alwaysAsk")) {
       handlerInfo.alwaysAskBeforeHandling = true;
     }
     else if (aActionItem.hasAttribute("action")) {
       let action = parseInt(aActionItem.getAttribute("action"));
@@ -1494,36 +1513,67 @@ var gApplicationsPane = {
                           this._getIconURLForPreferredAction(handlerInfo));
   },
 
   chooseApp: function(aEvent) {
     // Don't let the normal "on select action" handler get this event,
     // as we handle it specially ourselves.
     aEvent.stopPropagation();
 
+    var handlerApp;
+
+#ifdef XP_WIN
+    var params = {};
+    var handlerInfo = this._handledTypes[this._list.selectedItem.type];
+
+    if (handlerInfo.type == TYPE_MAYBE_FEED) {
+      // MIME info will be null, create a temp object.
+      params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type, 
+                                                 handlerInfo.primaryExtension);
+    } else {
+      params.mimeInfo = handlerInfo.wrappedHandlerInfo;
+    }
+
+    params.title         = this._prefsBundle.getString("fpTitleChooseApp");
+    params.description   = handlerInfo.description;
+    params.filename      = null;
+    params.handlerApp    = null;
+
+    window.openDialog("chrome://global/content/appPicker.xul", null,
+                      "chrome,modal,centerscreen,titlebar,dialog=yes",
+                      params);
+
+    if (params.handlerApp && 
+        params.handlerApp.executable && 
+        params.handlerApp.executable.isFile()) {
+      handlerApp = params.handlerApp;
+
+      // Add the app to the type's list of possible handlers.
+      handlerInfo.possibleApplicationHandlers.appendElement(handlerApp, false);
+    }
+#else
     var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     var winTitle = this._prefsBundle.getString("fpTitleChooseApp");
     fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
     fp.appendFilters(Ci.nsIFilePicker.filterApps);
 
-    var handlerApp;
-
     // Prompt the user to pick an app.  If they pick one, and it's a valid
     // selection, then add it to the list of possible handlers.
     if (fp.show() == Ci.nsIFilePicker.returnOK && fp.file &&
         this._isValidHandlerExecutable(fp.file)) {
       handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
                    createInstance(Ci.nsILocalHandlerApp);
       handlerApp.name = getDisplayNameForFile(fp.file);
       handlerApp.executable = fp.file;
 
       // Add the app to the type's list of possible handlers.
       let handlerInfo = this._handledTypes[this._list.selectedItem.type];
       handlerInfo.possibleApplicationHandlers.appendElement(handlerApp, false);
     }
+#endif
 
     // 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();
 
     // If the user picked a new app from the menu, select it.
     if (handlerApp) {
--- a/browser/components/preferences/preferences.xul
+++ b/browser/components/preferences/preferences.xul
@@ -80,17 +80,17 @@
 #endif
 #endif
 #endif
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
 #ifdef USE_WIN_TITLE_STYLE
             style="&prefWin.styleWin;">
 #else
 #ifdef XP_MACOSX
-            style="&prefWindow.styleMac;">
+            style="&prefWin.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"/>
--- a/browser/components/preferences/security.js
+++ b/browser/components/preferences/security.js
@@ -229,19 +229,19 @@ var gSecurityPane = {
    */
   readOnloadPhishProvider: function ()
   {
     const Cc = Components.classes, Ci = Components.interfaces;
     const onloadPopupId = "onloadPhishPopup";
     var popup = document.getElementById(onloadPopupId);
 
     if (!popup) {
-      var providerBranch = Cc["@mozilla.org/preferences-service;1"]
-                             .getService(Ci.nsIPrefService)
-                             .getBranch("browser.safebrowsing.provider.");
+      var providerBranch = Cc["@mozilla.org/preferences-service;1"].
+                           getService(Ci.nsIPrefService).
+                           getBranch("browser.safebrowsing.provider.");
 
       // fill in onload phishing list data -- but require a privacy policy
       // URL be provided, and require it to be at a chrome URL so it's always
       // available
       var kids = providerBranch.getChildList("", {});
       var providers = [];
       var hasPrivacyPolicy = {};
       for (var i = 0; i < kids.length; i++) {
@@ -369,18 +369,18 @@ var gSecurityPane = {
   },
 
   /**
    * Returns true if the user has a master password set and false otherwise.
    */
   _masterPasswordSet: function ()
   {
     const Cc = Components.classes, Ci = Components.interfaces;
-    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"]
-                     .getService(Ci.nsIPKCS11ModuleDB);
+    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
+                   getService(Ci.nsIPKCS11ModuleDB);
     var slot = secmodDB.findSlotByName("");
     if (slot) {
       var status = slot.status;
       var hasMP = status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
                   status != Ci.nsIPKCS11Slot.SLOT_READY;
       return hasMP;
     } else {
       // XXX I have no bloody idea what this means
@@ -414,19 +414,22 @@ var gSecurityPane = {
 
   /**
    * Displays the "remove master password" dialog to allow the user to remove
    * the current master password.  When the dialog is dismissed, master password
    * UI is automatically updated.
    */
   _removeMasterPassword: function ()
   {
-    var secmodDB = Components.classes["@mozilla.org/security/pkcs11moduledb;1"]
-                              .getService(Components.interfaces.nsIPKCS11ModuleDB);
+    const Cc = Components.classes, Ci = Components.interfaces;
+    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
+                   getService(Ci.nsIPKCS11ModuleDB);
     if (secmodDB.isFIPSEnabled) {
+      var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
+                          getService(Ci.nsIPromptService);
       var bundle = document.getElementById("bundlePreferences");
       promptService.alert(window,
                           bundle.getString("pw_change_failed_title"),
                           bundle.getString("pw_change2empty_in_fips_mode"));
     }
     else {
       document.documentElement.openSubDialog("chrome://mozapps/content/preferences/removemp.xul",
                                              "", null);
--- a/browser/components/safebrowsing/content/application.js
+++ b/browser/components/safebrowsing/content/application.js
@@ -33,18 +33,18 @@
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # **** END LICENSE BLOCK ****
 
 // We instantiate this variable when we create the application.
 var gDataProvider = null;
 
 // An instance of our application is a PROT_Application object. It
-// basically just populates a few globals and instantiates wardens and
-// the listmanager.
+// basically just populates a few globals and instantiates wardens,
+// the listmanager, and the about:blocked error page.
 
 /**
  * An instance of our application. There should be exactly one of these.
  * 
  * Note: This object should instantiated only at profile-after-change
  * or later because the listmanager and the cryptokeymanager need to
  * read and write data files. Additionally, NSS isn't loaded until
  * some time around then (Moz bug #321024).
@@ -95,8 +95,35 @@ function PROT_Application() {
 
 /**
  * @param name String The type of url to get (either Phish or Error).
  * @return String the report phishing URL (localized).
  */
 PROT_Application.prototype.getReportURL = function(name) {
   return gDataProvider["getReport" + name + "URL"]();
 }
+
+/**
+ * about:blocked implementation
+ */
+PROT_Application.prototype.newChannel = function(uri) {
+  var ioService = Cc["@mozilla.org/network/io-service;1"]
+                 .getService(Ci.nsIIOService);
+  var childURI = ioService.newURI("chrome://browser/content/safebrowsing/blockedSite.xhtml",
+                                  null, null);
+  var channel = ioService.newChannelFromURI(childURI);
+  channel.originalURI = uri;
+
+  return channel;
+}
+
+PROT_Application.prototype.getURIFlags = function(uri) {
+  return Ci.nsIAboutModule.ALLOW_SCRIPT;
+}
+
+PROT_Application.prototype.QueryInterface = function(iid) {
+  if (iid.equals(Ci.nsISupports) ||
+      iid.equals(Ci.nsIAboutModule))
+    return this;
+
+  Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+  return null;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/safebrowsing/content/blockedSite.xhtml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+  %htmlDTD;
+  <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
+  %globalDTD;
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+  %brandDTD;
+  <!ENTITY % blockedSiteDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
+  %blockedSiteDTD;
+]>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is mozilla.org code.
+   -
+   - The Initial Developer of the Original Code is
+   - Netscape Communications Corporation.
+   - Portions created by the Initial Developer are Copyright (C) 1998
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Adam Lock <adamlock@netscape.com>
+   -   William R. Price <wrprice@alumni.rice.edu>
+   -   Henrik Skupin <mozilla@hskupin.info>
+   -   Jeff Walden <jwalden+code@mit.edu>
+   -   Johnathan Nightingale <johnath@mozilla.com>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - 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 ***** -->
+
+<html xmlns="http://www.w3.org/1999/xhtml" class="blacklist">
+  <head>
+    <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
+    <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/blacklist_favicon.png"/>
+
+    <script type="application/javascript" src="chrome://global/content/strres.js"/>
+    <script type="application/javascript"><![CDATA[
+      // Error url MUST be formatted like this:
+      //   about:blocked?e=error_code&u=url
+      
+      // Note that this file uses document.documentURI to get
+      // the URL (with the format from above). This is because
+      // document.location.href gets the current URI off the docshell,
+      // which is the URL displayed in the location bar, i.e.
+      // the URI that the user attempted to load.
+
+      function getErrorCode()
+      {
+        var url = document.documentURI;
+        var error = url.search(/e\=/);
+        var duffUrl = url.search(/\&u\=/);
+        return decodeURIComponent(url.slice(error + 2, duffUrl));
+      }
+
+      function getURL()
+      {
+        var url = document.documentURI;
+        var index = url.search(/u\=/);
+
+        // index == -1 if not found; if so, return an empty string
+        // instead of what would turn out to be portions of the URI
+        if (index == -1)
+          return "";
+
+        return decodeURIComponent(url.slice(index + 2));
+      }
+      
+      /**
+       * Attempt to parse the result of getURL and extract a hostname.  Fail back
+       * to getURL so that we always return something meaningful.
+       */
+      function getHostString()
+      {
+        var ios = Components.classes["@mozilla.org/network/io-service;1"]
+                            .getService(Components.interfaces.nsIIOService);
+        var url = getURL();
+        try {
+          return ios.newURI(url, null, null).host;
+        } catch (e) {
+          return url;
+        }
+      }
+      
+      // Elements that tend to need content set
+      var errorTitleText, errorShortDescText, errorLongDesc, errorLongDescText;
+
+      // The string bundles managing strings for various blocked page scenarios
+      var sb = srGetStrBundle("chrome://browser/locale/safebrowsing/blockedSite.properties");
+      var brandBundle = srGetStrBundle("chrome://branding/locale/brand.properties");
+      var brandShortName = brandBundle.GetStringFromName("brandShortName");
+      
+      function initPage()
+      {
+        // Set up the cached elements
+        errorTitleText = document.getElementById("errorTitleText");
+        errorShortDescText = document.getElementById("errorShortDescText");
+        errorLongDesc = document.getElementById("errorLongDesc");
+        errorLongDescText = document.getElementById("errorLongDescText");
+        
+        // Handoff to the appropriate initializer, based on error code
+        switch(getErrorCode()) {
+          case "malwareBlocked" :
+            initPage_malware();
+            break;
+          case "phishingBlocked" :
+            initPage_phishing();
+            break;
+        }
+      }        
+      
+      /**
+       * Initialize custom strings and functionality for blocked malware case
+       */
+      function initPage_malware()
+      {
+        document.title = sb.GetStringFromName("malware.title");
+        errorTitleText.textContent = document.title;
+        errorShortDescText.textContent = sb.formatStringFromName("malware.shortDesc",
+                                                                 [getHostString()], 1);
+        errorLongDesc.innerHTML = sb.GetStringFromName("malware.longDesc");
+      }
+      
+      /**
+       * Initialize custom strings and functionality for blocked phishing case
+       */
+      function initPage_phishing()
+      {
+        document.title = sb.GetStringFromName("phishing.title");
+        errorTitleText.textContent = document.title;
+        errorShortDescText.textContent = sb.formatStringFromName("phishing.shortDesc",
+                                                                 [getHostString()], 1);
+        
+        var longDesc = sb.GetStringFromName("phishing.longDesc");
+
+        // If we have a more-info link for the phishing information, add it in,
+        // otherwise just use the generic text
+        var faqURL = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
+                               .getService(Components.interfaces.nsIURLFormatter)
+                               .formatURLPref("browser.safebrowsing.warning.infoURL");
+        if(faqURL && faqURL != "about:blank") {
+          longDesc += sb.formatStringFromName("phishing.learnMoreLink",
+                                              [brandShortName], 1);
+          errorLongDesc.innerHTML = longDesc;          
+          document.getElementById("faqLink").setAttribute("href", faqURL);
+        }
+        else 
+          errorLongDesc.innerHTML = longDesc;
+      }
+    ]]></script>
+  </head>
+
+  <body dir="&locale.dir;">
+    <div id="errorPageContainer">
+    
+      <!-- Error Title -->
+      <div id="errorTitle">
+        <h1 id="errorTitleText" />
+      </div>
+      
+      <div id="errorLongContent">
+      
+        <!-- Short Description -->
+        <div id="errorShortDesc">
+          <p id="errorShortDescText" />
+        </div>
+
+        <!-- Long Description -->
+        <div id="errorLongDesc">
+          <p id="errorLongDescText" />
+        </div>
+        
+        <!-- Action buttons -->
+        <div id="buttons">
+          <xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+                      id="getMeOutButton" label="&safeb.palm.accept.label;" oncommand="window.home();" />
+        </div>
+      </div>
+    </div>
+    <!--
+    - Note: It is important to run the script this way, instead of using
+    - an onload handler. This is because error pages are loaded as
+    - LOAD_BACKGROUND, which means that onload handlers will not be executed.
+    -->
+    <script type="application/javascript">initPage();</script>
+  </body>
+</html>
--- a/browser/components/safebrowsing/content/malware-warden.js
+++ b/browser/components/safebrowsing/content/malware-warden.js
@@ -59,16 +59,23 @@ function PROT_MalwareWarden() {
   // Add a test chunk to the database
   var testData = "mozilla.com/firefox/its-an-attack.html";
 
   var testUpdate =
     "n:1000\ni:test-malware-simple\nad:1\n" +
     "a:1:" + testData.length + "\n" +
     testData +
     "\n";
+    
+  testData = "mozilla.com/firefox/its-a-trap.html";
+  testUpdate +=
+    "n:1000\ni:test-phish-simple\nad:1\n" +
+    "a:1:" + testData.length + "\n" +
+    testData +
+    "\n";
 
   var dbService_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
                    .getService(Ci.nsIUrlClassifierDBService);
 
   dbService_.update(testUpdate);
   dbService_.finish(function(result) {}, function(error) {});
 
   G_Debug(this, "malwareWarden initialized");
--- a/browser/components/safebrowsing/content/phishing-afterload-displayer.js
+++ b/browser/components/safebrowsing/content/phishing-afterload-displayer.js
@@ -203,17 +203,16 @@ PROT_PhishMsgDisplayerBase.prototype.bro
 
   // If messageshowing hasn't been set, then this is the first time this
   // problematic browser tab has been on top, so do our setup and show
   // the warning.
   if (this.messageShowing_ === undefined) {
     this.messageShouldShow_ = true;
   }
 
-  this.hideLockIcon_();        // Comes back when we are unselected or unloaded
   this.addWarningInUrlbar_();  // Goes away when we are unselected or unloaded
 
   // messageShouldShow might be false if the user dismissed the warning, 
   // switched tabs, and then switched back. We're still active, but don't
   // want to show the warning again. The user can cause it to show by
   // clicking our icon in the urlbar.
   if (this.messageShouldShow_)
     this.showMessage_();
@@ -229,17 +228,16 @@ PROT_PhishMsgDisplayerBase.prototype.exp
     this.showMessage_();
 }
 
 /** 
  * Invoked by the browser view when our browser is switched away from
  */
 PROT_PhishMsgDisplayerBase.prototype.browserUnselected = function() {
   this.removeWarningInUrlbar_();
-  this.unhideLockIcon_();
   if (this.messageShowing_)
     this.hideMessage_();
 }
 
 /**
  * Invoked to make this displayer active. The displayer will now start
  * responding to notifications such as commands and resize events. We
  * can't do this in the constructor because there might be many 
@@ -285,17 +283,16 @@ PROT_PhishMsgDisplayerBase.prototype.don
 
   // If the Document we're showing the warning for was nav'd away from
   // before we had a chance to get started, we have nothing to do.
   if (this.started_) {
 
     // If we were started, we must be the current problem, so these things
     // must be showing
     this.removeWarningInUrlbar_();
-    this.unhideLockIcon_();
 
     // Could be though that they've closed the warning dialog
     if (this.messageShowing_)
       this.hideMessage_();
 
     if (this.resizeHandler_) {
       this.browser_.removeEventListener("resize", 
                                         this.resizeHandler_, 
@@ -323,38 +320,16 @@ PROT_PhishMsgDisplayerBase.prototype.rem
   var pos = orig.indexOf(toRemove);
   if (pos != -1)
     orig = orig.substring(0, pos) + orig.substring(pos + toRemove.length);
 
   return orig;
 }
 
 /**
- * We don't want to confuse users if they land on a phishy page that uses
- * SSL, so ensure that the lock icon never shows when we're showing our 
- * warning.
- */
-PROT_PhishMsgDisplayerBase.prototype.hideLockIcon_ = function() {
-  var lockIcon = this.doc_.getElementById("lock-icon");
-  if (!lockIcon)
-    return;
-  lockIcon.hidden = true;
-}
-
-/**
- * Ensure they can see it after our warning is finished.
- */
-PROT_PhishMsgDisplayerBase.prototype.unhideLockIcon_ = function() {
-  var lockIcon = this.doc_.getElementById("lock-icon");
-  if (!lockIcon)
-    return;
-  lockIcon.hidden = false;
-}
-
-/**
  * This method makes our warning icon visible in the location bar. It will
  * be removed only when the problematic document is navigated awy from 
  * (i.e., when done() is called), and not when the warning is dismissed.
  */
 PROT_PhishMsgDisplayerBase.prototype.addWarningInUrlbar_ = function() {
   var urlbarIcon = this.doc_.getElementById(this.urlbarIconId_);
   if (!urlbarIcon)
     return;
@@ -552,36 +527,17 @@ function PROT_PhishMsgDisplayerCanvas(ms
 }
 
 PROT_PhishMsgDisplayerCanvas.inherits(PROT_PhishMsgDisplayerBase);
 
 /**
  * Displays the warning message.  First we make sure the overlay is loaded
  * then call showMessageAfterOverlay_.
  */
-PROT_PhishMsgDisplayerCanvas.prototype.showMessage_ = function() {
-  G_Debug(this, "Showing message.");
-
-  // Load the overlay if we haven't already.
-  var dimmer = this.doc_.getElementById('safebrowsing-dim-area-canvas');
-  if (!dimmer) {
-    var onOverlayMerged = BindToObject(this.showMessageAfterOverlay_,
-                                       this);
-    var observer = new G_ObserverWrapper("xul-overlay-merged",
-                                         onOverlayMerged);
-
-    this.doc_.loadOverlay(
-        "chrome://browser/content/safebrowsing/warning-overlay.xul",
-        observer);
-  } else {
-    // The overlay is already loaded so we go ahead and call
-    // showMessageAfterOverlay_.
-    this.showMessageAfterOverlay_();
-  }
-}
+PROT_PhishMsgDisplayerCanvas.prototype.showMessage_ = function() { }
 
 /**
  * This does the actual work of showing the warning message.
  */
 PROT_PhishMsgDisplayerCanvas.prototype.showMessageAfterOverlay_ = function() {
   this.messageShowing_ = true;
 
   // Position the canvas overlay. Order here is significant, but don't ask me
@@ -698,44 +654,17 @@ PROT_PhishMsgDisplayerCanvas.prototype.i
     return false;
 
   return true;
 }
 
 /**
  * Hide the warning message from the user.
  */
-PROT_PhishMsgDisplayerCanvas.prototype.hideMessage_ = function() {
-  G_Debug(this, "Hiding phishing warning.");
-  G_Assert(this, this.messageShowing_, "Hide message called but not showing?");
-
-  this.messageShowing_ = false;
-  this.repainter_.cancel();
-  this.repainter_ = null;
-
-  // Hide the warning popup.
-  var message = this.doc_.getElementById(this.messageId_);
-  message.hidden = true;
-  message.style.display = "none";
-  var content = this.doc_.getElementById(this.messageContentId_);
-  content.style.height = "";
-  content.style.overflow = "";
-
-  var tail = this.doc_.getElementById(this.messageTailId_);
-  tail.hidden = true;
-  tail.style.display = "none";
-
-  // Remove the canvas element from the chrome document.
-  var pageCanvas = this.doc_.getElementById(this.pageCanvasId_);
-  pageCanvas.parentNode.removeChild(pageCanvas);
-
-  // Hide the dimmer.
-  var dimarea = this.doc_.getElementById(this.dimAreaId_);
-  dimarea.hidden = true;
-}
+PROT_PhishMsgDisplayerCanvas.prototype.hideMessage_ = function() { }
 
 
 /**
  * Helper class that periodically repaints the canvas. We repaint
  * frequently at first, and then back off to a less frequent schedule
  * at "steady state," and finally just stop altogether. We have to do
  * this because we're not sure if the page has finished loading when
  * we first paint the canvas, and because we want to reflect any
--- a/browser/components/safebrowsing/jar.mn
+++ b/browser/components/safebrowsing/jar.mn
@@ -1,6 +1,7 @@
 browser.jar:
 # script file included into main browser.js
 * content/browser/safebrowsing/sb-loader.js                    (content/sb-loader.js)
 + content/browser/safebrowsing/warning-overlay.xul             (content/warning-overlay.xul)
 + content/browser/safebrowsing/report-phishing-overlay.xul     (content/report-phishing-overlay.xul)
++ content/browser/safebrowsing/blockedSite.xhtml               (content/blockedSite.xhtml)
 % overlay chrome://browser/content/browser.xul         chrome://browser/content/safebrowsing/report-phishing-overlay.xul
--- a/browser/components/safebrowsing/src/nsSafebrowsingApplication.js
+++ b/browser/components/safebrowsing/src/nsSafebrowsingApplication.js
@@ -56,16 +56,23 @@ SafebrowsingApplicationMod.prototype.reg
   }
   compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
   compMgr.registerFactoryLocation(this.cid,
                                   "Safebrowsing Application Module",
                                   this.progid,
                                   fileSpec,
                                   loc,
                                   type);
+  
+  compMgr.registerFactoryLocation(this.cid,
+                                  "UrlClassifier Blocked Error Page",
+                                  "@mozilla.org/network/protocol/about;1?what=blocked",
+                                  fileSpec,
+                                  loc,
+                                  type);
 };
 
 SafebrowsingApplicationMod.prototype.getClassObject = function(compMgr, cid, iid) {  
   if (!cid.equals(this.cid))
     throw Components.results.NS_ERROR_NO_INTERFACE;
   if (!iid.equals(Ci.nsIFactory))
     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
 
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1974,17 +1974,21 @@ SessionStoreService.prototype = {
       this._updateCrashReportURL = function(aWindow) {};
       return;
     }
     try {
       var currentUrl = aWindow.getBrowser().currentURI.spec;
       var cr = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsICrashReporter);
       cr.annotateCrashReport("URL", currentUrl);
     }
-    catch (ex) { debug(ex); }
+    catch (ex) {
+      // don't make noise when crashreporter is built but not enabled
+      if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED)
+        debug(ex);
+    }
   },
 
   /**
    * safe eval'ing
    */
   _safeEval: function sss_safeEval(aStr) {
     return Cu.evalInSandbox(aStr, new Cu.Sandbox("about:blank"));
   },
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -30,19 +30,19 @@
 # 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 *****
 
 # Required Plugins:
-# SetVistaDefaultApp http://nsis.sourceforge.net/SetVistaDefaultApp_plug-in
-# ShellLink          http://nsis.sourceforge.net/ShellLink_plug-in
-# UAC                http://nsis.sourceforge.net/UAC_plug-in
+# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
+# ShellLink   http://nsis.sourceforge.net/ShellLink_plug-in
+# UAC         http://nsis.sourceforge.net/UAC_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
@@ -105,35 +105,40 @@ Var AddDesktopSC
 !include version.nsh
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
 
 ; Must be inserted before other macros that use logging
 !insertmacro _LoggingCommon
 
 !insertmacro AddDDEHandlerValues
+!insertmacro ChangeMUIHeaderImage
 !insertmacro CloseApp
 !insertmacro CreateRegKey
 !insertmacro GetPathFromString
+!insertmacro GetParent
 !insertmacro IsHandlerForInstallDir
 !insertmacro ManualCloseAppPrompt
 !insertmacro RegCleanAppHandler
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
+!insertmacro SetBrandNameVars
+!insertmacro UnloadUAC
 !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 OnEndCommon
 !insertmacro PreDirectoryCommon
 
 Name "${BrandFullName}"
 OutFile "setup.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}\"
 ShowInstDetails nevershow
 
@@ -159,19 +164,21 @@ ReserveFile summary.ini
 !else
 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
 !endif
 
 /**
  * Installation Pages
  */
 ; Welcome Page
+!define MUI_PAGE_CUSTOMFUNCTION_PRE preWelcome
 !insertmacro MUI_PAGE_WELCOME
 
 ; License Page
+!define MUI_PAGE_CUSTOMFUNCTION_SHOW showLicense
 !define MUI_LICENSEPAGE_CHECKBOX
 !insertmacro MUI_PAGE_LICENSE license.rtf
 
 ; Custom Options Page
 Page custom preOptions leaveOptions
 
 ; Custom Components Page
 Page custom preComponents leaveComponents
@@ -212,30 +219,30 @@ Page custom preSummary leaveSummary
 # Install Sections
 
 ; Cleanup operations to perform at the start of the installation.
 Section "-InstallStartCleanup"
   SetDetailsPrint both
   DetailPrint $(STATUS_CLEANUP)
   SetDetailsPrint none
 
-  SetOutPath $INSTDIR
+  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.
   GetTempFileName $TmpVal "$TEMP"
-  ${DeleteFile} $TmpVal
-  SetOutPath $TmpVal
+  ${DeleteFile} "$TmpVal"
+  SetOutPath "$TmpVal"
 
   ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
     ClearErrors
     CopyFiles /SILENT "$INSTDIR\${FileMainEXE}" "$TmpVal\${FileMainEXE}"
     Delete "$INSTDIR\${FileMainEXE}"
     ${If} ${Errors}
       ClearErrors
       ${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
@@ -261,17 +268,17 @@ Section "-InstallStartCleanup"
   Call CheckInUse
 
   StrCpy $R1 "nspr4.dll"
   Call CheckInUse
 
   StrCpy $R1 "xpicleanup.exe"
   Call CheckInUse
 
-  SetOutPath $INSTDIR
+  SetOutPath "$INSTDIR"
   RmDir /r "$TmpVal"
   ClearErrors
 
   ${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.
@@ -384,16 +391,21 @@ Section "-Application" APP_IDX
   ${If} ${Errors}
     StrCpy $TmpVal "HKCU" ; used primarily for logging
   ${Else}
     SetShellVarContext all  ; Set SHCTX to HKLM
     DeleteRegKey HKLM "Software\Mozilla\InstallerTest"
     StrCpy $TmpVal "HKLM" ; used primarily for logging
     ${RegCleanMain} "Software\Mozilla"
     ${RegCleanUninstall}
+
+    ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
+    ${If} "$0" != "${GREVersion}"
+      WriteRegStr HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" "${GREVersion}"
+    ${EndIf}
   ${EndIf}
 
   ${RemoveDeprecatedKeys}
 
   ; The previous installer adds several regsitry values to both HKLM and HKCU.
   ; We now try to add to HKLM and if that fails to HKCU
 
   ; The order that reg keys and values are added is important if you use the
@@ -528,18 +540,19 @@ Function CheckInUse
       Delete "$INSTDIR\$R1"
     ${EndUnless}
     ${If} ${Errors}
       StrCpy $0 "$INSTDIR\$R1"
       ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
       MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
       Delete "$TmpVal\$R1"
       CopyFiles /SILENT "$TmpVal\*" "$INSTDIR\"
-      SetOutPath $INSTDIR
+      SetOutPath "$INSTDIR"
       RmDir /r "$TmpVal"
+      ${OnEndCommon}
       Quit
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
 Function DoCopyFiles
   StrLen $R2 $R0
   ${LocateNoDetails} "$R0" "/L=FD" "CopyFile"
@@ -607,39 +620,40 @@ Function CopyFile
     ; 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
 
 Function LaunchApp
+  ClearErrors
   ${GetParameters} $0
-  ${If} $0 != ""
-    ClearErrors
-    ${GetOptions} "$0" "/UAC:" $1
-    ${Unless} ${Errors}
-      GetFunctionAddress $0 LaunchAppFromElevatedProcess
-      UAC::ExecCodeSegment $0
-      Quit
-    ${EndUnless}
+  ${GetOptions} "$0" "/UAC:" $1
+  ${If} ${Errors}
+    ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
+    Exec "$INSTDIR\${FileMainEXE}"
+  ${Else}
+    GetFunctionAddress $0 LaunchAppFromElevatedProcess
+    UAC::ExecCodeSegment $0
   ${EndIf}
-
-  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
-  Exec "$INSTDIR\${FileMainEXE}"
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
   ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
 
   ; Find the installation directory when launching using GetFunctionAddress
   ; from an elevated installer since $INSTDIR will not be set in this installer
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
   ${GetPathFromString} "$0" $0
+  ${GetParent} "$0" $1
+  ; Set our current working directory to the application's install directory
+  ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
+  SetOutPath "$1"
   Exec "$0"
 FunctionEnd
 
 ################################################################################
 # Language
 
 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
 !verbose push
@@ -648,17 +662,33 @@ FunctionEnd
 !include "customLocale.nsh"
 !verbose pop
 
 ; Set this after the locale files to override it if it is in the locale
 ; using " " for BrandingText will hide the "Nullsoft Install System..." branding
 BrandingText " "
 
 ################################################################################
-# Page pre and leave functions
+# Page pre, show, and leave functions
+
+Function preWelcome
+  ${If} ${FileExists} "$EXEDIR\localized\distribution\modern-wizard.bmp"
+    Delete "$PLUGINSDIR\modern-wizard.bmp"
+    CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
+  ${EndIf}
+FunctionEnd
+
+Function showLicense
+  ${If} ${FileExists} "$EXEDIR\localized\distribution\modern-header.bmp"
+  ${AndIf} $hHeaderBitmap == ""
+    Delete "$PLUGINSDIR\modern-header.bmp"
+    CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
+    ${ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
+  ${EndIf}
+FunctionEnd
 
 Function preOptions
   !insertmacro MUI_HEADER_TEXT "$(OPTIONS_PAGE_TITLE)" "$(OPTIONS_PAGE_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "options.ini"
 FunctionEnd
 
 Function leaveOptions
   ${MUI_INSTALLOPTIONS_READ} $0 "options.ini" "Settings" "State"
@@ -753,43 +783,44 @@ Function preFinish
   ${EndInstallLog} "${BrandFullName}"
   !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
 FunctionEnd
 
 ################################################################################
 # Initialization Functions
 
 Function .onInit
+  StrCpy $LANGUAGE 0
+  ${SetBrandNameVars} "$EXEDIR\localized\distribution\setup.ini"
+
   ${InstallOnInitCommon} "$(WARN_UNSUPPORTED_MSG)"
 
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "options.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "components.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "shortcuts.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "summary.ini"
   !insertmacro createBasicCustomOptionsINI
   !insertmacro createComponentsINI
   !insertmacro createShortcutsINI
 
-  StrCpy $LANGUAGE 0
-
   ; There must always be nonlocalized and localized directories.
   ${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 ${DOMI_IDX} $0
   ${Else}
     ; Hide DOMi in the components page if it isn't available.
     SectionSetText ${DOMI_IDX} ""
   ${EndIf}
+
+  ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
+  ; the user clicks the back button
+  StrCpy $hHeaderBitmap ""
 FunctionEnd
 
-Function .OnInstFailed
-  UAC::Unload
+Function .onGUIEnd
+  ${OnEndCommon}
 FunctionEnd
-
-Function .OnInstSuccess
-  UAC::Unload
-FunctionEnd
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -50,16 +50,21 @@
     SetShellVarContext all    ; Set SHCTX to all users (e.g. HKLM)
     DeleteRegKey HKLM "Software\Mozilla\InstallerTest"
     StrCpy $TmpVal "HKLM" ; used primarily for logging
     ${RegCleanMain} "Software\Mozilla"
     ${RegCleanUninstall}
     ${SetStartMenuInternet}
     ${FixShellIconHandler}
     ${SetUninstallKeys}
+
+    ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
+    ${If} "$0" != "${GREVersion}"
+      WriteRegStr HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" "${GREVersion}"
+    ${EndIf}
   ${EndIf}
 
   ${RemoveDeprecatedKeys}
 
   ; Add Software\Mozilla\ registry entries
   ${SetAppKeys}
   ${FixClassKeys}
   ${UpdateProtocolHandlers}
@@ -105,17 +110,17 @@
 
 !ifdef ___WINVER__NSH___
   ${If} ${AtLeastWinVista}
     ClearErrors
     ReadRegStr $0 HKLM "Software\RegisteredApplications" "${AppRegName}"
     ; Only register as the handler on Vista if the app registry name exists
     ; under the RegisteredApplications registry key.
     ${Unless} ${Errors}
-      SetVistaDefaultApp::SetAsDefault "${AppRegName}"
+      AppAssocReg::SetAppAsDefaultAll "${AppRegName}"
     ${EndUnless}
   ${EndIf}
 !endif
 
   ${RemoveDeprecatedKeys}
 
   SetShellVarContext current  ; Set SHCTX to the current user (e.g. HKCU)
   ${SetHandlers}
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -30,19 +30,19 @@
 # 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 *****
 
 # Required Plugins:
-# SetVistaDefaultApp http://nsis.sourceforge.net/SetVistaDefaultApp_plug-in
-# ShellLink          http://nsis.sourceforge.net/ShellLink_plug-in
-# UAC                http://nsis.sourceforge.net/UAC_plug-in
+# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
+# ShellLink   http://nsis.sourceforge.net/ShellLink_plug-in
+# UAC         http://nsis.sourceforge.net/UAC_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
@@ -57,29 +57,29 @@ CRCCheck on
 !define NO_LOG
 
 Var TmpVal
 
 ; Other included files may depend upon these includes!
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
+!include MUI.nsh
 !include TextFunc.nsh
 !include WinMessages.nsh
 !include WordFunc.nsh
-!include MUI.nsh
 
 ; 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 user
 !else
-  !warning "Uninstaller will be created without Vista compatibility.$\n            \
+  !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 WordReplace
 
 !insertmacro un.GetParent
 !insertmacro un.LineFind
@@ -99,36 +99,43 @@ VIAddVersionKey "FileDescription" "${Bra
 !insertmacro AddDDEHandlerValues
 !insertmacro CleanVirtualStore
 !insertmacro GetLongPath
 !insertmacro GetPathFromString
 !insertmacro IsHandlerForInstallDir
 !insertmacro RegCleanAppHandler
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
+!insertmacro UnloadUAC
 !insertmacro WriteRegDWORD2
 !insertmacro WriteRegStr2
 
+!insertmacro un.ChangeMUIHeaderImage
 !insertmacro un.CleanVirtualStore
+!insertmacro un.DeleteRelativeProfiles
 !insertmacro un.GetLongPath
 !insertmacro un.GetSecondInstallPath
 !insertmacro un.ManualCloseAppPrompt
 !insertmacro un.ParseUninstallLog
 !insertmacro un.RegCleanAppHandler
 !insertmacro un.RegCleanFileHandler
 !insertmacro un.RegCleanMain
 !insertmacro un.RegCleanUninstall
 !insertmacro un.RegCleanProtocolHandler
 !insertmacro un.RemoveQuotesFromPath
+!insertmacro un.SetBrandNameVars
 
 !include shared.nsh
 
 ; Helper macros for ui callbacks. Insert these after shared.nsh
+!insertmacro OnEndCommon
 !insertmacro UninstallOnInitCommon
 
+!insertmacro un.OnEndCommon
+
 Name "${BrandFullName}"
 OutFile "helper.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}"
 ShowUnInstDetails nevershow
 
 ################################################################################
 # Modern User Interface - MUI
@@ -147,21 +154,21 @@ ShowUnInstDetails nevershow
 !else
 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
 !endif
 
 /**
  * Uninstall Pages
  */
 ; Welcome Page
+!define MUI_PAGE_CUSTOMFUNCTION_PRE un.preWelcome
 !insertmacro MUI_UNPAGE_WELCOME
 
 ; Uninstall Confirm Page
-!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.leaveConfirm
-!insertmacro MUI_UNPAGE_CONFIRM
+UninstPage custom un.preConfirm un.leaveConfirm
 
 ; Remove Files Page
 !insertmacro MUI_UNPAGE_INSTFILES
 
 ; Finish Page
 
 ; Don't setup the survey controls, functions, etc. when the application has
 ; defined NO_UNINSTALL_SURVEY
@@ -196,16 +203,21 @@ Section "Uninstall"
     ; If the user closed the application it can take several seconds for it to
     ; shut down completely. If the application is being used by another user we
     ; can still delete the files when the system is restarted. 
     Sleep 5000
     ${DeleteFile} "$INSTDIR\${FileMainEXE}"
     ClearErrors
   ${EndIf}
 
+  ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State"
+  ${If} "$0" == "1"
+    ${un.DeleteRelativeProfiles} "Mozilla\Firefox"
+  ${EndIf}
+
   SetShellVarContext current  ; Set SHCTX to HKCU
   ${un.RegCleanMain} "Software\Mozilla"
   ${un.RegCleanUninstall}
 
   ClearErrors
   WriteRegStr HKLM "Software\Mozilla\InstallerTest" "InstallerTest" "Test"
   ${If} ${Errors}
     StrCpy $TmpVal "HKCU" ; used primarily for logging
@@ -349,20 +361,60 @@ FunctionEnd
 !include "customLocale.nsh"
 !verbose pop
 
 ; Set this after the locale files to override it if it is in the locale. Using
 ; " " for BrandingText will hide the "Nullsoft Install System..." branding.
 BrandingText " "
 
 ################################################################################
-# Page pre and leave functions
+# Page pre, show, and leave functions
+
+Function un.preWelcome
+  ${If} ${FileExists} "$INSTDIR\distribution\modern-wizard.bmp"
+    Delete "$PLUGINSDIR\modern-wizard.bmp"
+    CopyFiles /SILENT "$INSTDIR\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
+  ${EndIf}
+FunctionEnd
+
+Function un.preConfirm
+  ${If} ${FileExists} "$INSTDIR\distribution\modern-header.bmp"
+  ${AndIf} $hHeaderBitmap == ""
+    Delete "$PLUGINSDIR\modern-header.bmp"
+    CopyFiles /SILENT "$INSTDIR\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
+    ${un.ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
+  ${EndIf}
 
-; Checks if the app being uninstalled is running.
+  !insertmacro un.createUnConfirmINI
+  !insertmacro MUI_HEADER_TEXT "$(UN_CONFIRM_PAGE_TITLE)" "$(UN_CONFIRM_PAGE_SUBTITLE)"
+  ; The Summary custom page has a textbox that will automatically receive
+  ; focus. This sets the focus to the Install button instead.
+  !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "unconfirm.ini"
+  GetDlgItem $0 $HWNDPARENT 1
+  ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND"
+  SetCtlColors $1 0x000000 0xFFFFEE
+  ShowWindow $1 ${SW_HIDE}
+  System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
+  !insertmacro MUI_INSTALLOPTIONS_SHOW
+FunctionEnd
+
 Function un.leaveConfirm
+  ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Settings" "State"
+  StrCmp $0 "3" +1 continue
+  ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State"
+  ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND"
+  StrCmp $0 1 +1 +3
+  ShowWindow $1 ${SW_SHOW}
+  Abort
+
+  ShowWindow $1 ${SW_HIDE}
+  Abort
+
+  continue:
+
   ; Try to delete the app executable and if we can't delete it try to find the
   ; app's message window and prompt the user to close the app. This allows
   ; running an instance that is located in another directory. If for whatever
   ; reason there is no message window we will just rename the app's files and
   ; then remove them on restart if they are in use.
   StrCpy $TmpVal ""
   ClearErrors
   ${DeleteFile} "$INSTDIR\${FileMainEXE}"
@@ -410,10 +462,24 @@ Function .onInit
 FunctionEnd
 
 Function un.onInit
   GetFullPathName $INSTDIR "$INSTDIR\.."
   ${un.GetLongPath} "$INSTDIR" $INSTDIR
   ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
     Abort
   ${EndUnless}
+
   StrCpy $LANGUAGE 0
+  ${un.SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
+
+  ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
+  ; the user clicks the back button
+  StrCpy $hHeaderBitmap ""
 FunctionEnd
+
+Function .onGUIEnd
+  ${OnEndCommon}
+FunctionEnd
+
+Function un.onGUIEnd
+  ${un.OnEndCommon}
+FunctionEnd
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -188,16 +188,20 @@ MOZ_PKG_MAC_RSRC=$(_ABS_DIST)/branding/l
 endif
 
 PACKAGER_NO_LIBS = 1
 include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
 include $(call EXPAND_LOCALE_SRCDIR,toolkit/locales)/installer/windows/charset.mk
 
 repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/install/sea/$(PKG_BASENAME).installer.exe
 repackage-win32-installer: $(WIN32_INSTALLER_IN) $(SUBMAKEFILES)
+ifneq (en-US,$(AB_CD))
+	@echo "Verifying $(AB_CD) installer variable usage"
+	@$(PERL) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/check-locales.pl $(LOCALE_SRCDIR)/installer
+endif
 	@echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
 ifdef MOZ_BRANDING_DIRECTORY
 	$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
 else
 	$(MAKE) -C ../installer/windows export
 endif
 	if test ! -d $(dir $(WIN32_INSTALLER_OUT)); then \
 	  $(NSINSTALL) -D $(dir $(WIN32_INSTALLER_OUT)); \
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -268,29 +268,29 @@
 <!ENTITY blockImageCmd.accesskey       "g">
 <!ENTITY metadataCmd.label            "Properties">
 <!ENTITY metadataCmd.accesskey        "P">
 <!ENTITY copyEmailCmd.label           "Copy Email Address">
 <!ENTITY copyEmailCmd.accesskey       "E">
 <!ENTITY thisFrameMenu.label              "This Frame">
 <!ENTITY thisFrameMenu.accesskey          "h">
 
-<!ENTITY textZoomEnlargeCmd.label       "Increase">
-<!ENTITY textZoomEnlargeCmd.accesskey   "I">
-<!ENTITY textZoomEnlargeCmd.commandkey  "+">
-<!ENTITY textZoomEnlargeCmd.commandkey2 "="> <!-- + is above this key on many keyboards -->
+<!ENTITY fullZoomEnlargeCmd.label       "Zoom In">
+<!ENTITY fullZoomEnlargeCmd.accesskey   "I">
+<!ENTITY fullZoomEnlargeCmd.commandkey  "+">
+<!ENTITY fullZoomEnlargeCmd.commandkey2 "="> <!-- + is above this key on many keyboards -->
 
-<!ENTITY textZoomReduceCmd.label        "Decrease">
-<!ENTITY textZoomReduceCmd.accesskey    "D">
-<!ENTITY textZoomReduceCmd.commandkey   "-">
-<!ENTITY textZoomResetCmd.commandkey    "0">
-<!ENTITY textZoomResetCmd.label         "Normal">
-<!ENTITY textZoomResetCmd.accesskey     "N">
-<!ENTITY textSize.label                 "Text Size">
-<!ENTITY textSize.accesskey             "z">
+<!ENTITY fullZoomReduceCmd.label        "Zoom Out">
+<!ENTITY fullZoomReduceCmd.accesskey    "O">
+<!ENTITY fullZoomReduceCmd.commandkey   "-">
+<!ENTITY fullZoomResetCmd.commandkey    "0">
+<!ENTITY fullZoomResetCmd.label         "Reset">
+<!ENTITY fullZoomResetCmd.accesskey     "R">
+<!ENTITY fullZoom.label                 "Zoom">
+<!ENTITY fullZoom.accesskey             "Z">
 
 <!ENTITY newTabButton.tooltip           "Open a new tab">
 <!ENTITY newWindowButton.tooltip        "Open a new window">
 <!ENTITY sidebarCloseButton.tooltip     "Close sidebar">
 
 <!ENTITY cutButton.tooltip              "Cut">
 <!ENTITY copyButton.tooltip             "Copy">
 <!ENTITY pasteButton.tooltip            "Paste">
@@ -340,8 +340,10 @@
 <!ENTITY findAgainCmd.commandkey "g">
 <!ENTITY findAgainCmd.commandkey2 "VK_F3">
 
 <!ENTITY spellAddDictionaries.label "Add dictionaries...">
 <!ENTITY spellAddDictionaries.accesskey "A">
 
 <!ENTITY editBookmark.done.label                      "Done">
 <!ENTITY editBookmark.delete.label                    "Delete">
+
+<!ENTITY identity.moreInfoLinkText "Tell me more about this web site...">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -78,17 +78,28 @@ menuOpenAllInTabs.label=Open All in Tabs
 menuOpenAllInTabs.accesskey=o
 
 # Block autorefresh
 refreshBlocked.goButton=Allow
 refreshBlocked.goButton.accesskey=A
 refreshBlocked.refreshLabel=%S prevented this page from automatically reloading.
 refreshBlocked.redirectLabel=%S prevented this page from automatically redirecting to another page.
 
-# Chromeless popup handling
-chromelessWindow.warningMessage=The web site at %S has hidden your toolbars.
-chromelessWindow.warningNoLocation=This web site has hidden your toolbars.
-chromelessWindow.showToolbarsButton=Show Toolbars
-chromelessWindow.accessKey=S
-
 # Star button
 starButtonOn.tooltip=Edit this bookmark
 starButtonOff.tooltip=Bookmark this page
+
+# Identity information
+identity.domainverified.title=Location Verified
+identity.domainverified.body=You are currently visiting:
+identity.domainverified.supplemental=Information identifying the owner of this web site may not have been validated.
+
+identity.identified.title=Identity Verified
+identity.identified.body=This web site is owned by:
+identity.identified.verifier=Verified by: %S
+identity.identified.state_and_country=%S, %S
+identity.identified.title_with_country=%S (%S)
+
+identity.unknown.title=Identity Unknown
+identity.unknown.body=This web site does not supply identity information.
+
+identity.encrypted=Your connection to this web site is encrypted to prevent eavesdropping.
+identity.unencrypted=Your connection to this web site is not encrypted.
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
@@ -1,15 +1,15 @@
 
 <!ENTITY  prefWindow.titleWin     "Options">
 <!ENTITY  prefWindow.titleGNOME   "&brandShortName; Preferences">
 <!-- When making changes to prefWindow.styleWin test both Windows Classic and
      Luna since widget heights are different based on the OS theme -->
 <!ENTITY  prefWin.styleWin        "width: 42em; min-height: 44em;">
-<!ENTITY  prefWindow.styleMac     "width: 47em;">
+<!ENTITY  prefWin.styleMac        "width: 47em; min-height: 45em;">
 <!ENTITY  prefWin.styleGNOME      "width: 42em; min-height: 44.5em;">
 
 <!ENTITY  paneMain.title          "Main">
 <!ENTITY  paneTabs.title          "Tabs">
 <!ENTITY  paneContent.title       "Content">
 <!ENTITY  paneApplications.title  "Applications">
 <!ENTITY  panePrivacy.title       "Privacy">
 <!ENTITY  paneSecurity.title      "Security">
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/safebrowsing/blockedSite.properties
@@ -0,0 +1,11 @@
+malware.title=Suspected Attack Site!
+malware.shortDesc=The web site at %S has been reported as an attack site and has been blocked based on your security preferences.
+malware.longDesc=<p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>\n<p>Web site owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
+
+phishing.title=Suspected Web Forgery!
+phishing.shortDesc=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
+phishing.longDesc=<p>Entering any personal information on this page may result in identity theft or other fraud.</p><p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
+
+# Localization note (phishing.learnMoreLink): please leave the <a id="faqLink" href=""> text
+# as-is.  A localized href is pulled in from user preferences automatically.
+phishing.learnMoreLink=<p>You can find out more about <a id="faqLink" href="">how %S protects you</a> from phishing attacks.</p>
--- a/browser/locales/en-US/chrome/overrides/appstrings.properties
+++ b/browser/locales/en-US/chrome/overrides/appstrings.properties
@@ -55,8 +55,9 @@ proxyConnectFailure=Firefox is configure
 contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression. Please contact the website owners to inform them of this problem.
 externalProtocolTitle=External Protocol Request
 externalProtocolPrompt=An external application must be launched to handle %1$S: links.\n\n\nRequested link:\n\n%2$S\n\nApplication: %3$S\n\n\nIf you were not expecting this request it may be an attempt to exploit a weakness in that other program. Cancel this request unless you are sure it is not malicious.\n
 #LOCALIZATION NOTE (externalProtocolUnknown): The following string is shown if the application name can't be determined
 externalProtocolUnknown=<Unknown>
 externalProtocolChkMsg=Remember my choice for all links of this type.
 externalProtocolLaunchBtn=Launch application
 malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
+phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -118,16 +118,27 @@
 <!ENTITY nssFailure2.title "Secure Connection Failed">
 <!ENTITY nssFailure2.longDesc "
 <ul>
   <li>The page you are trying to view can not be shown because the authenticity of the received data could not be verified.</li>
   <li>Please contact the web site owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.</li>
 </ul>
 ">
 
+<!ENTITY nssBadCert.title "Secure Connection Failed">
+<!ENTITY nssBadCert.longDesc "
+<ul>
+  <li>This could be a problem with the server's configuration, or it could be
+someone trying to impersonate the server.</li>
+  <li>If you have connected to this server successfully in the past, the error may
+be temporary, and you can try again later.</li>
+  <li>You can see and change your current list of servers with known security problems
+  in your advanced encryption settings.</li>
+</ul>
+">
 
 <!ENTITY sharedLongDesc "
 <ul>
   <li>The site could be temporarily unavailable or too busy. Try again in a few
     moments.</li>
   <li>If you are unable to load any pages, check your computer's network
     connection.</li>
   <li>If your computer or network is protected by a firewall or proxy, make sure
@@ -135,8 +146,14 @@
 </ul>
 ">
 
 <!ENTITY malwareBlocked.title "Suspected Attack Site!">
 <!ENTITY malwareBlocked.longDesc "
 <p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>
 <p>Web site owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
 ">
+
+<!ENTITY phishingBlocked.title "Suspected Web Forgery!">
+<!ENTITY phishingBlocked.longDesc "
+<p>Entering any personal information on this page may result in identity theft or other fraud.</p>
+<p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
+">
--- a/browser/locales/en-US/installer/custom.properties
+++ b/browser/locales/en-US/installer/custom.properties
@@ -36,66 +36,74 @@
 
 # LOCALIZATION NOTE:
 
 # This file must be saved as UTF8
 
 # Accesskeys are defined by prefixing the letter that is to be used for the
 # accesskey with an ampersand (e.g. &).
 
-# Do not replace ${BrandShortName} or ${BrandFullName} with a custom string.
+# Do not replace $BrandShortName, $BrandFullName, or $BrandFullNameDA with a
+# custom string and always use the same one as used by the en-US files.
+# $BrandFullNameDA allows the string to contain an ampersand (e.g. DA stands
+# for double ampersand) and prevents the letter following the ampersand from
+# being used as an accesskey.
 
 # You can use \n to create a newline in the string but only when the string
 # from en-US contains a \n.
 
-REG_APP_DESC=${BrandShortName} delivers safe, easy web browsing. A familiar user interface, enhanced security features including protection from online identity theft, and integrated search let you get the most out of the web.
+REG_APP_DESC=$BrandShortName delivers safe, easy web browsing. A familiar user interface, enhanced security features including protection from online identity theft, and integrated search let you get the most out of the web.
 OPTIONAL_COMPONENTS_TITLE=Choose Optional Components
-OPTIONAL_COMPONENTS_SUBTITLE=Choose which features of $(^NameDA) you want to install.
+OPTIONAL_COMPONENTS_SUBTITLE=Choose which features of $BrandShortName you want to install.
 OPTIONAL_COMPONENTS_LABEL=Optional Components:
-APP_DESC=Required files for the ${BrandShortName} application
 DOMI_TITLE=DOM Inspector
 DOMI_TEXT=Inspects the structure and properties of a window and its contents.
-QFA_TITLE=Quality Feedback Agent
-QFA_TEXT=Sends information about program crashes to Mozilla.
-CONTEXT_OPTIONS=${BrandShortName} &Options
-CONTEXT_SAFE_MODE=${BrandShortName} &Safe Mode
+CONTEXT_OPTIONS=$BrandShortName &Options
+CONTEXT_SAFE_MODE=$BrandShortName &Safe Mode
 SAFE_MODE=Safe Mode
 OPTIONS_PAGE_TITLE=Setup Type
 OPTIONS_PAGE_SUBTITLE=Choose setup options
 SHORTCUTS_PAGE_TITLE=Set Up Shortcuts
 SHORTCUTS_PAGE_SUBTITLE=Create Program Icons
 SUMMARY_PAGE_TITLE=Summary
-SUMMARY_PAGE_SUBTITLE=Ready to start installing ${BrandShortName}
-SUMMARY_INSTALLED_TO=${BrandShortName} will be installed to the following location:
+SUMMARY_PAGE_SUBTITLE=Ready to start installing $BrandShortName
+SUMMARY_INSTALLED_TO=$BrandShortName will be installed to the following location:
 SUMMARY_CLICK=Click Install to continue.
-SURVEY_TEXT=&Tell us what you thought of ${BrandShortName}
-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.
-CREATE_ICONS_DESC=Create icons for ${BrandShortName}:
+SURVEY_TEXT=&Tell us what you thought of $BrandShortName
+LAUNCH_TEXT=&Launch $BrandShortName now
+WARN_APP_RUNNING_INSTALL=$BrandShortName must be closed to proceed with the installation.\n\nClick "OK" to exit $BrandShortName 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_MANUALLY_CLOSE_APP_UNINSTALL=${BrandFullName} must be closed to proceed with the uninstall.\n\nPlease close ${BrandFullName} to continue.
-WARN_MANUALLY_CLOSE_APP_LAUNCH=${BrandFullName} is already running.\n\nPlease close ${BrandFullName} prior to launching the version you have just installed.
+WARN_MANUALLY_CLOSE_APP_UNINSTALL=$BrandShortName must be closed to proceed with the uninstall.\n\nPlease close $BrandShortName to continue.
+WARN_MANUALLY_CLOSE_APP_LAUNCH=$BrandShortName is already running.\n\nPlease close $BrandShortName prior to launching the version you have just installed.
 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.
-WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of ${BrandShortName}. Do you want to reboot now?
+WARN_UNSUPPORTED_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinUnsupportedVer} or newer.
+WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of $BrandShortName. Do you want to reboot now?
 ERROR_CREATE_DIRECTORY=Error creating directory:\n\n$0\n\nClick Cancel to stop the installation or\nRetry to try again.
 
-STATUS_INSTALL_APP=Installing ${BrandShortName}...
+UN_CONFIRM_PAGE_TITLE=Uninstall $BrandFullName
+UN_CONFIRM_PAGE_SUBTITLE=Remove $BrandFullName from your computer.
+UN_CONFIRM_UNINSTALLED_FROM=$BrandShortName will be uninstalled from the following location:
+UN_CONFIRM_CLICK=Click Uninstall to continue.
+UN_REMOVE_PROFILES=&Remove my $BrandShortName personal data and customizations
+UN_REMOVE_PROFILES_DESC=This will permanently remove your bookmarks, saved passwords, cookies and customizations. You may wish to keep this information if you plan on installing another version of $BrandShortName in the future.
+
+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_UNINSTALL_MAIN=Uninstalling $BrandShortName...
 STATUS_CLEANUP=A Little Housekeeping...
 
 # _DESC strings support approximately 65 characters per line.
 # One line
 OPTIONS_SUMMARY=Choose the type of setup you prefer, then click Next.
 # One line
-OPTION_STANDARD_DESC=${BrandShortName} will be installed with the most common options.
+OPTION_STANDARD_DESC=$BrandShortName will be installed with the most common options.
 OPTION_STANDARD_RADIO=&Standard
 # One line
-OPTION_COMPLETE_DESC=${BrandShortName} will be installed with all available options.
+OPTION_COMPLETE_DESC=$BrandShortName will be installed with all available options.
 OPTION_COMPLETE_RADIO=C&omplete
 # Two lines
 OPTION_CUSTOM_DESC=You may choose individual options to be installed. Recommended for experienced users.
 OPTION_CUSTOM_RADIO=&Custom
--- a/browser/locales/en-US/installer/mui.properties
+++ b/browser/locales/en-US/installer/mui.properties
@@ -39,59 +39,60 @@
 
 # LOCALIZATION NOTE:
 
 # This file must be saved as UTF8
 
 # Accesskeys are defined by prefixing the letter that is to be used for the
 # accesskey with an ampersand (e.g. &).
 
-# Do not replace $(^NameDA) or $(^Name) with a custom string.
-
-# Do not change $(^NameDA) to $(^Name) or $(^Name) to $(^NameDA). NameDA allows
-# Name to contain an ampersand (e.g. DA stands for double ampersand) and
-# prevents the letter following the ampersand being used as an accesskey.
+# Do not replace $BrandShortName, $BrandFullName, or $BrandFullNameDA with a
+# custom string and always use the same one as used by the en-US files.
+# $BrandFullNameDA allows the string to contain an ampersand (e.g. DA stands
+# for double ampersand) and prevents the letter following the ampersand from
+# being used as an accesskey.
 
 # 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_WELCOME_INFO_TITLE=Welcome to the $BrandFullNameDA Setup Wizard
+MUI_TEXT_WELCOME_INFO_TEXT=This wizard will guide you through the installation of $BrandFullNameDA.\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_TEXT_LICENSE_SUBTITLE=Please review the license terms before installing $BrandFullNameDA.
 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_INNERTEXT_LICENSE_BOTTOM_CHECKBOX=If you accept the terms of the agreement, click the check box below. You must accept the agreement to install $BrandFullNameDA. $_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 $BrandFullNameDA. $_CLICK
 MUI_TEXT_COMPONENTS_TITLE=Choose Components
-MUI_TEXT_COMPONENTS_SUBTITLE=Choose which features of $(^NameDA) you want to install.
+MUI_TEXT_COMPONENTS_SUBTITLE=Choose which features of $BrandFullNameDA 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_DIRECTORY_SUBTITLE=Choose the folder in which to install $BrandFullNameDA.
 MUI_TEXT_INSTALLING_TITLE=Installing
-MUI_TEXT_INSTALLING_SUBTITLE=Please wait while $(^NameDA) is being installed.
+MUI_TEXT_INSTALLING_SUBTITLE=Please wait while $BrandFullNameDA is being installed.
 MUI_TEXT_FINISH_TITLE=Installation Complete
 MUI_TEXT_FINISH_SUBTITLE=Setup was completed successfully.
 MUI_TEXT_ABORT_TITLE=Installation Aborted
 MUI_TEXT_ABORT_SUBTITLE=Setup was not completed successfully.
 MUI_BUTTONTEXT_FINISH=&Finish
-MUI_TEXT_FINISH_INFO_TITLE=Completing the $(^NameDA) Setup Wizard
-MUI_TEXT_FINISH_INFO_TEXT=$(^NameDA) has been installed on your computer.\n\nClick Finish to close this wizard.
-MUI_TEXT_FINISH_INFO_REBOOT=Your computer must be restarted in order to complete the installation of $(^NameDA). Do you want to reboot now?
+MUI_TEXT_FINISH_INFO_TITLE=Completing the $BrandFullNameDA Setup Wizard
+MUI_TEXT_FINISH_INFO_TEXT=$BrandFullNameDA has been installed on your computer.\n\nClick Finish to close this wizard.
+MUI_TEXT_FINISH_INFO_REBOOT=Your computer must be restarted in order to complete the installation of $BrandFullNameDA. Do you want to reboot now?
 MUI_TEXT_FINISH_REBOOTNOW=Reboot now
 MUI_TEXT_FINISH_REBOOTLATER=I want to manually reboot later
 MUI_TEXT_STARTMENU_TITLE=Choose Start Menu Folder
-MUI_TEXT_STARTMENU_SUBTITLE=Choose a Start Menu folder for the $(^NameDA) shortcuts.
+MUI_TEXT_STARTMENU_SUBTITLE=Choose a Start Menu folder for the $BrandFullNameDA shortcuts.
 MUI_INNERTEXT_STARTMENU_TOP=Select the Start Menu folder in which you would like to create the program's shortcuts. You can also enter a name to create a new folder.
-MUI_TEXT_ABORTWARNING=Are you sure you want to quit $(^Name) Setup?
-MUI_UNTEXT_WELCOME_INFO_TITLE=Welcome to the $(^NameDA) Uninstall Wizard
-MUI_UNTEXT_WELCOME_INFO_TEXT=This wizard will guide you through the uninstallation of $(^NameDA).\n\nBefore starting the uninstallation, make sure $(^NameDA) is not running.\n\n$_CLICK
-MUI_UNTEXT_CONFIRM_TITLE=Uninstall $(^NameDA)
-MUI_UNTEXT_CONFIRM_SUBTITLE=Remove $(^NameDA) from your computer.
+MUI_TEXT_ABORTWARNING=Are you sure you want to quit $BrandFullName Setup?
+MUI_UNTEXT_WELCOME_INFO_TITLE=Welcome to the $BrandFullNameDA Uninstall Wizard
+MUI_UNTEXT_WELCOME_INFO_TEXT=This wizard will guide you through the uninstallation of $BrandFullNameDA.\n\nBefore starting the uninstallation, make sure $BrandFullNameDA is not running.\n\n$_CLICK
+MUI_UNTEXT_CONFIRM_TITLE=Uninstall $BrandFullNameDA
+MUI_UNTEXT_CONFIRM_SUBTITLE=Remove $BrandFullNameDA from your computer.
 MUI_UNTEXT_UNINSTALLING_TITLE=Uninstalling
-MUI_UNTEXT_UNINSTALLING_SUBTITLE=Please wait while $(^NameDA) is being uninstalled.
+MUI_UNTEXT_UNINSTALLING_SUBTITLE=Please wait while $BrandFullNameDA is being uninstalled.
 MUI_UNTEXT_FINISH_TITLE=Uninstallation Complete
 MUI_UNTEXT_FINISH_SUBTITLE=Uninstall was completed successfully.
 MUI_UNTEXT_ABORT_TITLE=Uninstallation Aborted
 MUI_UNTEXT_ABORT_SUBTITLE=Uninstall was not completed successfully.
-MUI_UNTEXT_FINISH_INFO_TITLE=Completing the $(^NameDA) Uninstall Wizard
-MUI_UNTEXT_FINISH_INFO_TEXT=$(^NameDA) has been uninstalled from your computer.\n\nClick Finish to close this wizard.
-MUI_UNTEXT_FINISH_INFO_REBOOT=Your computer must be restarted in order to complete the uninstallation of $(^NameDA). Do you want to reboot now?
-MUI_UNTEXT_ABORTWARNING=Are you sure you want to quit $(^Name) Uninstall?
+MUI_UNTEXT_FINISH_INFO_TITLE=Completing the $BrandFullNameDA Uninstall Wizard
+MUI_UNTEXT_FINISH_INFO_TEXT=$BrandFullNameDA has been uninstalled from your computer.\n\nClick Finish to close this wizard.
+MUI_UNTEXT_FINISH_INFO_REBOOT=Your computer must be restarted in order to complete the uninstallation of $BrandFullNameDA. Do you want to reboot now?
+MUI_UNTEXT_ABORTWARNING=Are you sure you want to quit $BrandFullName Uninstall?
--- a/browser/locales/en-US/installer/override.properties
+++ b/browser/locales/en-US/installer/override.properties
@@ -36,55 +36,55 @@
 
 # LOCALIZATION NOTE:
 
 # This file must be saved as UTF8
 
 # Accesskeys are defined by prefixing the letter that is to be used for the
 # accesskey with an ampersand (e.g. &).
 
-# Do not replace $(^NameDA) or $(^Name) with a custom string.
-
-# Do not change $(^NameDA) to $(^Name) or $(^Name) to $(^NameDA). NameDA allows
-# Name to contain an ampersand (e.g. DA stands for double ampersand) and
-# prevents the letter following the ampersand being used as an accesskey.
+# Do not replace $BrandShortName, $BrandFullName, or $BrandFullNameDA with a
+# custom string and always use the same one as used by the en-US files.
+# $BrandFullNameDA allows the string to contain an ampersand (e.g. DA stands
+# for double ampersand) and prevents the letter following the ampersand from
+# being used as an accesskey.
 
 # You can use \n to create a newline in the string but only when the string
 # from en-US contains a \n.
 
 # Strings that require a space at the end should be enclosed with double
 # quotes and the double quotes will be removed. To add quotes to the beginning
 # and end of a strong enclose the add and additional double quote to the
 # beginning and end of the string (e.g. ""This will include quotes"").
 
-SetupCaption=$(^Name) Setup
-UninstallCaption=$(^Name) Uninstall
+SetupCaption=$BrandFullName Setup
+UninstallCaption=$BrandFullName Uninstall
 BackBtn=< &Back
 NextBtn=&Next >
 AcceptBtn=I &accept the terms in the License Agreement
 DontAcceptBtn=I &do not accept the terms in the License Agreement
 InstallBtn=&Install
 UninstallBtn=&Uninstall
 CancelBtn=Cancel
 CloseBtn=&Close
 BrowseBtn=B&rowse...
 ShowDetailsBtn=Show &details
 ClickNext=Click Next to continue.
 ClickInstall=Click Install to start the installation.
 ClickUninstall=Click Uninstall to start the uninstallation.
 Completed=Completed
-LicenseTextRB=Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK
+LicenseTextRB=Please review the license agreement before installing $BrandFullNameDA. If you accept all terms of the agreement, select the first option below. $_CLICK
 ComponentsText=Check the components you want to install and uncheck the components you don't want to install. $_CLICK
 ComponentsSubText2_NoInstTypes=Select components to install:
-DirText=Setup will install $(^NameDA) in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK
+DirText=Setup will install $BrandFullNameDA in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK
 DirSubText=Destination Folder
-DirBrowseText=Select the folder to install $(^NameDA) in:
+DirBrowseText=Select the folder to install $BrandFullNameDA in:
 SpaceAvailable="Space available: "
 SpaceRequired="Space required: "
-UninstallingText=$(^NameDA) will be uninstalled from the following folder. $_CLICK
+UninstallingText=$BrandFullNameDA will be uninstalled from the following folder. $_CLICK
 UninstallingSubText=Uninstalling from:
 FileError=Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Abort to stop the installation,\r\nRetry to try again, or\r\nIgnore to skip this file.
 FileError_NoIgnore=Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Retry to try again, or\r\nCancel to stop the installation.
 CantWrite="Can't write: "
 CopyFailed=Copy failed
 CopyTo="Copy to "
 Registering="Registering: "
 Unregistering="Unregistering: "
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -32,16 +32,17 @@
     locale/browser/places/editBookmarkOverlay.dtd  (%chrome/browser/places/editBookmarkOverlay.dtd)
     locale/browser/places/bookmarkProperties.dtd   (%chrome/browser/places/bookmarkProperties.dtd)
     locale/browser/places/bookmarkProperties.properties (%chrome/browser/places/bookmarkProperties.properties)
     locale/browser/preferences/selectBookmark.dtd  (%chrome/browser/preferences/selectBookmark.dtd)
     locale/browser/places/moveBookmarks.dtd        (%chrome/browser/places/moveBookmarks.dtd)
 #ifdef MOZ_SAFE_BROWSING
     locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
     locale/browser/safebrowsing/report-phishing.dtd                    (%chrome/browser/safebrowsing/report-phishing.dtd)
+    locale/browser/safebrowsing/blockedSite.properties                 (%chrome/browser/safebrowsing/blockedSite.properties)
 #endif
     locale/browser/feeds/subscribe.dtd              (%chrome/browser/feeds/subscribe.dtd)
     locale/browser/feeds/subscribe.properties       (%chrome/browser/feeds/subscribe.properties)
     locale/browser/history/history.dtd             (%chrome/browser/history/history.dtd)
     locale/browser/migration/migration.dtd         (%chrome/browser/migration/migration.dtd)
     locale/browser/migration/migration.properties  (%chrome/browser/migration/migration.properties)
     locale/browser/preferences/advanced.dtd           (%chrome/browser/preferences/advanced.dtd)
 *   locale/browser/preferences/advanced-scripts.dtd   (%chrome/browser/preferences/advanced-scripts.dtd)
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -826,51 +826,24 @@ toolbar[iconsize="small"] #paste-button:
   list-style-image: url("chrome://global/skin/icons/close.gif");
 }
 
 /* ::::: nav-bar-inner ::::: */
 
 #urlbar {
   margin-top: 5px;
   margin-bottom: 5px;
-  -moz-margin-start: 4px;
+  -moz-margin-start: 0px;
   -moz-margin-end: 0px;
   width: 7em;
   min-width: 7em;
   padding: 0px;
   font: icon !important;
 }
 
-.formatted-url {
-  -moz-box-align: center;
-  margin: 0 3px;
-  /*XXX Gecko 1.9 quirk*/
-  -moz-padding-start: 1px;
-  color: -moz-fieldtext;
-}
-
-#urlbar[level="high"] .formatted-url ,
-#urlbar[level="low"] .formatted-url {
-  color: black;
-}
-
-.formatted-url * {
-  margin: 0;
-  padding: 0;
-  cursor: text;
-}
-
-.formatted-url-ellipsis {
-  -moz-margin-start: 1px;
-}
-
-.formatted-url-prePath {
-  -moz-box-pack: center;
-}
-
 #urlbar[level="high"] > .autocomplete-textbox-container,
 #urlbar[level="low"] > .autocomplete-textbox-container
  {
   margin: -2px;
   padding: 2px;
   background: url("chrome://browser/skin/Secure-background.gif") #FFFED8 repeat-x;
   color: black !important;
 }
@@ -878,56 +851,16 @@ toolbar[iconsize="small"] #paste-button:
 #urlbar[level="high"] > .autocomplete-history-dropmarker,
 #urlbar[level="low"] > .autocomplete-history-dropmarker
  {
   margin: -2px;
   padding: 2px 6px;
   background: url("chrome://browser/skin/Secure-background.gif") #FFFED8 repeat-x;
 }
 
-#urlbar #lock-icon {
-  height: 18px;
-  margin: -1px;
-}
-
-#urlbar[level="high"] #lock-icon {
-  list-style-image: url("chrome://browser/skin/Secure.png");
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-}
-#urlbar[level="high"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-}
-#urlbar[level="high"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-}
-
-#urlbar[level="low"] #lock-icon {
-  list-style-image: url("chrome://browser/skin/Secure.png");
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-}
-#urlbar[level="low"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-}
-#urlbar[level="low"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-}
-
-#urlbar[level="broken"] #lock-icon {
-  list-style-image: url("chrome://browser/skin/Security-broken.png");
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-}
-
-#urlbar[level="broken"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-}
-
-#urlbar[level="broken"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-}
-
 #urlbar-container {
   -moz-padding-end: 5px;
 }
 
 #wrapper-urlbar-container #urlbar {
   -moz-user-input: disabled;
   cursor: -moz-grab;
 }
@@ -1702,8 +1635,121 @@ toolbarbutton.bookmark-item[dragover="tr
   border-left: 2px solid;
   border-right: 2px solid;
   border-bottom: 3px solid;
   -moz-border-right-colors: -moz-mac-menushadow ThreeDLightShadow  !important;
   -moz-border-bottom-colors: -moz-mac-menushadow -moz-mac-menushadow ThreeDShadow  !important;
   -moz-border-left-colors: ThreeDLightShadow ThreeDHighlight !important;
 }
 
+/* ::::: Identity Indicator Styling ::::: */
+/* Location bar visuals*/
+#identity-box {
+  /* Extend our margins out so that our highlight/separator bar covers the
+    location bar properly */
+  margin: -1px 0 -2px;
+  padding: 1px 2px 2px 0;
+  border-right: 1px solid #888;
+  background-color: white;
+  opacity: 0.9;
+}
+
+#identity-box:hover {
+  opacity: 1.0;
+}
+
+#identity-box.verifiedIdentity {
+  background-color: #BFA;
+}
+
+#urlbar[level="high"] > #identity-box,
+#urlbar[level="low"] > #identity-box {
+  /* urlbar adds padding when security level is set, which we need to
+  counteract here so that we still fill the background.  */
+  margin: -2px;
+  padding: 1px 2px 2px;
+}
+
+#identity-icon-label {
+    padding: 2px 2px 0;
+    margin: 0;
+    color: black;
+    vertical-align: middle;
+}
+
+.unknownIdentity > #identity-icon-label {
+    display: none;
+}
+
+/* Popup Icons */
+#identity-popup-icon {
+    height: 64px;
+    width: 64px;
+    padding: 0;
+    margin: 10px 0 0;
+    list-style-image: url("chrome://browser/skin/identity.png");
+    -moz-image-region: rect(0px, 64px, 64px, 0px);
+}
+
+.verifiedDomain > #identity-popup-container > #identity-popup-icon {
+    -moz-image-region: rect(64px, 64px, 128px, 0px);
+}
+
+.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
+    -moz-image-region: rect(128px, 64px, 192px, 0px);
+}
+
+/* Popup Title */
+#identity-popup-title {
+    font-size: 120%;
+    font-weight: bold;
+}
+
+.verifiedIdentity > #identity-popup-title {
+    color: #6A6;
+}
+
+.unknownIdentity > #identity-popup-title {
+    color: #999;
+}
+
+.verifiedDomain > #identity-popup-title {
+    color: black;
+}
+
+/* Popup Body Text */
+#identity-popup-content-box > description,
+#identity-popup-encryption-label {
+    white-space: -moz-pre-wrap;
+    color: black;
+    padding-left: 10px;
+}
+
+#identity-popup-content {
+    padding-top: 5px;
+    margin-bottom: 0;
+    max-width: 200px;
+}
+
+.verifiedIdentity > #identity-popup-content,
+.verifiedDomain > #identity-popup-content {
+   font-size: 140%;
+   font-weight: bold;
+   max-width: 300px;
+}
+
+#identity-popup-encryption {
+  margin: 10px 0;
+}
+
+.verifiedIdentity > #identity-popup-encryption > * > #identity-popup-encryption-icon,
+.verifiedDomain > #identity-popup-encryption > * >#identity-popup-encryption-icon {
+  list-style-image: url("chrome://browser/skin/Secure.png");
+  -moz-image-region: rect(0px, 18px, 18px, 0px);
+}
+
+/* Popup Bounding Box */
+#identity-popup-container {
+    background-image: none;
+    background-color: white;
+    min-width: 280px;
+    padding: 10px;
+}
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -5,16 +5,17 @@ classic.jar:
   skin/classic/browser/bookmark-open-mid.png
   skin/classic/browser/bookmark-open-right.png
 * skin/classic/browser/browser.css                          (browser.css)
   skin/classic/browser/browser.xml
 * skin/classic/browser/engineManager.css                    (engineManager.css)
   skin/classic/browser/find.png
   skin/classic/browser/find-bar-background.png
   skin/classic/browser/Go.png
+  skin/classic/browser/identity.png
   skin/classic/browser/Info.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/livemark-item.png
   skin/classic/browser/pageInfo.css
   skin/classic/browser/pageInfo.png
   skin/classic/browser/Popup-blocked.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/search-bar-background-mid.png
--- a/browser/themes/pinstripe/browser/places/places.css
+++ b/browser/themes/pinstripe/browser/places/places.css
@@ -1,8 +1,31 @@
+/* Sidebars */
+
+.sidebar-placesTree {
+  -moz-appearance: none;
+  border: 0;
+  margin: 0;
+  border-top: 1px solid ThreeDShadow;
+}
+
+.sidebar-placesTreechildren::-moz-tree-cell(leaf) ,
+.sidebar-placesTreechildren::-moz-tree-image(leaf) {
+  cursor: pointer;
+}
+
+.sidebar-placesTreechildren::-moz-tree-cell-text(leaf, hover) {
+  cursor: pointer;
+  text-decoration: underline;
+}
+
+.sidebar-placesTreechildren::-moz-tree-cell(separator) {
+  cursor: default;
+}
+
 /* Toolbar */
 #placesToolbar {
   border-bottom: none;
 }
 
 /* back button */
 
 #back-button {
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -851,55 +851,28 @@ toolbar[iconsize="small"] #paste-button:
 }
 
 /* ::::: nav-bar-inner ::::: */
 
 #urlbar {
   margin-bottom: 2px;
   margin-top: 2px;
   -moz-margin-end: 0px;
-  -moz-margin-start: 3px;
+  -moz-margin-start: 0px;
   width: 7em;
   min-width: 7em;
 
   -moz-appearance: none;
   -moz-border-top-colors: ThreeDShadow;
   -moz-border-bottom-colors: ThreeDShadow;
   -moz-border-right-colors: ThreeDShadow;
   -moz-border-left-colors: ThreeDShadow;
   border-width: 1px;
 }
 
-.formatted-url {
-  -moz-box-align: center;
-  margin: 0 3px;
-  /*XXX Gecko 1.9 quirk*/
-  -moz-padding-start: 1px;
-  color: -moz-fieldtext;
-}
-
-#urlbar[level="high"] .formatted-url ,
-#urlbar[level="low"] .formatted-url {
-  color: black;
-}
-
-.formatted-url * {
-  margin: 0;
-  padding: 0;
-  cursor: text;
-}
-
-.formatted-url-ellipsis {
-  -moz-margin-start: 1px;
-}
-
-.formatted-url-prePath {
-  -moz-box-pack: center;
-}
-
 #urlbar-container {
   -moz-box-orient: horizontal;
   -moz-box-align: stretch;
   -moz-margin-end: 5px;
 }
 
 #urlbar-icons {
   height: 18px;
@@ -1741,53 +1714,16 @@ toolbar[mode="text"] > #window-controls 
 }
 
 #urlbar[level="high"] > .autocomplete-textbox-container,
 #urlbar[level="low"] > .autocomplete-textbox-container {
   background-color: #F5F6BE; /* #F7F898; */
   color: #000000;
 }
 
-#urlbar[level="high"] #lock-icon {
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="high"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="high"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="low"] #lock-icon {
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="low"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="low"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-  list-style-image: url("chrome://browser/skin/Secure.png");
-}
-#urlbar[level="broken"] #lock-icon {
-  -moz-image-region: rect(0px, 18px, 18px, 0px);
-  list-style-image: url("chrome://browser/skin/Security-broken.png");
-}
-#urlbar[level="broken"] #lock-icon:hover {
-  -moz-image-region: rect(18px, 18px, 36px, 0px);
-  list-style-image: url("chrome://browser/skin/Security-broken.png");
-}
-#urlbar[level="broken"] #lock-icon:active {
-  -moz-image-region: rect(36px, 18px, 54px, 0px);
-  list-style-image: url("chrome://browser/skin/Security-broken.png");
-}
-
 %ifdef MOZ_WIDGET_GTK2
 #urlbar > .autocomplete-textbox-container {
   -moz-binding: url(chrome://browser/skin/browser.xml#autocomplete-security-wrapper);
 }
 
 #autocomplete-security-wrapper {
   -moz-box-align: center;
 }
@@ -1890,8 +1826,122 @@ toolbarbutton.bookmark-item[dragover="tr
 
 .bookmark-item[dragover-top="true"] {
   -moz-border-top-colors: #000000;
 }
 
 .bookmark-item[dragover-bottom="true"] {
   -moz-border-bottom-colors: #000000;
 }
+
+/* ::::: Identity Indicator Styling ::::: */
+/* Location bar visuals*/
+#identity-box {
+  cursor: help;
+  background-color: ThreeDFace;
+%ifdef MOZ_WIDGET_GTK2
+  -moz-border-end: 1px solid ThreeDShadow;
+%else
+  -moz-appearance: toolbox;
+  outline: 1px solid ThreeDShadow;
+%endif
+}
+
+#identity-box.verifiedIdentity {
+%ifdef MOZ_WIDGET_GTK2
+  border-color: highlight;
+%else
+  outline-color: highlight;
+%endif
+}
+
+#identity-box:hover {
+%ifdef MOZ_WIDGET_GTK2
+  border-color: ThreeDDarkShadow;
+%else
+  outline-color: ThreeDDarkShadow;
+%endif
+}
+
+#identity-icon-label {
+  padding: 0 2px;
+  margin: 0;
+  cursor: inherit;
+}
+
+.unknownIdentity > #identity-icon-label {
+  display: none;
+}
+
+/* Popup Icons */
+#identity-popup-icon {
+    height: 64px;
+    width: 64px;
+    padding: 0;
+    margin: 10px 0 0;
+    list-style-image: url("chrome://browser/skin/identity.png");
+    -moz-image-region: rect(0px, 64px, 64px, 0px);
+}
+
+.verifiedDomain > #identity-popup-container > #identity-popup-icon {
+    -moz-image-region: rect(64px, 64px, 128px, 0px);
+}
+
+.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
+    -moz-image-region: rect(128px, 64px, 192px, 0px);
+}
+
+/* Popup Title */
+#identity-popup-title {
+    font-size: 120%;
+    font-weight: bold;
+}
+
+.verifiedIdentity > #identity-popup-title {
+    color: #6A6;
+}
+
+.unknownIdentity > #identity-popup-title {
+    color: #999;
+}
+
+.verifiedDomain > #identity-popup-title {
+    color: black;
+}
+
+/* Popup Body Text */
+#identity-popup-content-box > description,
+#identity-popup-encryption-label {
+    white-space: -moz-pre-wrap;
+    color: black;
+    padding-left: 10px;
+}
+
+#identity-popup-content {
+    padding-top: 5px;
+    margin-bottom: 0;
+    max-width: 200px;
+}
+
+.verifiedIdentity > #identity-popup-content,
+.verifiedDomain > #identity-popup-content {
+   font-size: 140%;
+   font-weight: bold;
+   max-width: 300px;
+}
+
+#identity-popup-encryption {
+  margin: 10px 0;
+}
+
+.verifiedIdentity > #identity-popup-encryption > * > #identity-popup-encryption-icon,
+.verifiedDomain > #identity-popup-encryption > * >#identity-popup-encryption-icon {
+  list-style-image: url("chrome://browser/skin/Secure.png");
+  -moz-image-region: rect(0px, 18px, 18px, 0px);
+}
+
+/* Popup Bounding Box */
+#identity-popup-container {
+    background-image: none;
+    background-color: white;
+    min-width: 280px;
+    padding: 10px;
+}
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -1,16 +1,17 @@
 classic.jar:
 % skin browser classic/1.0 %skin/classic/browser/
 *       skin/classic/browser/browser.css                        (browser.css)
         skin/classic/browser/browser.xml
         skin/classic/browser/endcap-bkgnd.png
         skin/classic/browser/endcap-bkgnd-hover.png
 *       skin/classic/browser/engineManager.css                  (engineManager.css)
         skin/classic/browser/Info.png
+        skin/classic/browser/identity.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png
         skin/classic/browser/page-livemarks.png
         skin/classic/browser/livemark-item.png
         skin/classic/browser/livemark-item-rtl.png
         skin/classic/browser/livemark-folder.png
         skin/classic/browser/livemark-folder-rtl.png
         skin/classic/browser/Secure.png
--- a/browser/themes/winstripe/browser/places/places.css
+++ b/browser/themes/winstripe/browser/places/places.css
@@ -1,20 +1,31 @@
 /* Sidebars */
 
-page > .placesTree > treechildren::-moz-tree-cell(leaf) ,
-page > .placesTree > treechildren::-moz-tree-image(leaf) {
+.sidebar-placesTree {
+  -moz-appearance: none;
+  border: 0;
+  margin: 0;
+  border-top: 1px solid ThreeDShadow;
+}
+
+.sidebar-placesTreechildren::-moz-tree-cell(leaf) ,
+.sidebar-placesTreechildren::-moz-tree-image(leaf) {
   cursor: pointer;
 }
 
-page > .placesTree > treechildren::-moz-tree-cell-text(leaf, hover) {
+.sidebar-placesTreechildren::-moz-tree-cell-text(leaf, hover) {
   cursor: pointer;
   text-decoration: underline;
 }
 
+.sidebar-placesTreechildren::-moz-tree-cell(separator) {
+  cursor: default;
+}
+
 /* Toolbar */
 #placesToolbar {
   border: none;
 }
 
 /* back button */
 
 #back-button {
--- a/caps/idl/nsIScriptSecurityManager.idl
+++ b/caps/idl/nsIScriptSecurityManager.idl
@@ -279,19 +279,22 @@ interface nsIScriptSecurityManager : nsI
      * (scheme, host, and port).
      */
     [noscript] void checkSameOrigin(in JSContextPtr aJSContext,
                                     in nsIURI aTargetURI);
 
     /**
      * Returns OK if aSourceURI and target have the same "origin"
      * (scheme, host, and port).
+     * ReportError flag suppresses error reports for functions that
+     * don't need reporting.
      */
     void checkSameOriginURI(in nsIURI aSourceURI,
-                            in nsIURI aTargetURI);
+                            in nsIURI aTargetURI,
+                            in boolean reportError);
 
     /**
      * Returns OK if aSourcePrincipal and aTargetPrincipal
      * have the same "origin" (scheme, host, and port).
      */
     void checkSameOriginPrincipal(in nsIPrincipal aSourcePrincipal,
                                   in nsIPrincipal aTargetPrincipal);
 
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -441,23 +441,18 @@ nsScriptSecurityManager::GetChannelPrinc
         if (*aPrincipal) {
             return NS_OK;
         }
     }
 
     // OK, get the principal from the URI.  Make sure this does the same thing
     // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
     nsCOMPtr<nsIURI> uri;
-    nsLoadFlags loadFlags = 0;
-    nsresult rv = aChannel->GetLoadFlags(&loadFlags);
-    if (NS_SUCCEEDED(rv) && (loadFlags & nsIChannel::LOAD_REPLACE)) {
-      aChannel->GetURI(getter_AddRefs(uri));
-    } else {
-      aChannel->GetOriginalURI(getter_AddRefs(uri));
-    }
+    nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+    NS_ENSURE_SUCCESS(rv, rv);
 
     return GetCodebasePrincipal(uri, aPrincipal);
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
                                            PRBool* aIsSystem)
 {
@@ -676,22 +671,25 @@ nsScriptSecurityManager::CheckSameOrigin
          ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI);
          return NS_ERROR_DOM_BAD_URI;
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
-                                            nsIURI* aTargetURI)
+                                            nsIURI* aTargetURI,
+                                            PRBool reportError)
 {
     if (!SecurityCompareURIs(aSourceURI, aTargetURI))
     {
-         ReportError(nsnull, NS_LITERAL_STRING("CheckSameOriginError"), 
+         if (reportError) {
+            ReportError(nsnull, NS_LITERAL_STRING("CheckSameOriginError"),
                      aSourceURI, aTargetURI);
+         }
          return NS_ERROR_DOM_BAD_URI;
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSourcePrincipal,
                                                   nsIPrincipal* aTargetPrincipal)
--- a/client.py
+++ b/client.py
@@ -1,11 +1,11 @@
 #!/usr/bin/python
 
-NSPR_CO_TAG = 'NSPR_HEAD_20071009'
+NSPR_CO_TAG = 'NSPR_HEAD_20071016'
 NSS_CO_TAG  = 'NSS_3_12_ALPHA_2'
 
 NSPR_DIRS = ('nsprpub',)
 NSS_DIRS  = ('dbm',
              'security/nss',
              'security/coreconf',
              'security/dbm')
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1043,16 +1043,25 @@ endif # OS/2
 	rm -f $@
 	$(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS)
 	$(HOST_RANLIB) $@
 
 ifdef NO_LD_ARCHIVE_FLAGS
 SUB_SHLOBJS = $(SUB_LOBJS)
 endif
 
+ifdef HAVE_DTRACE
+ifdef DTRACE_PROBE_OBJ
+ifndef DTRACE_LIB_DEPENDENT
+$(DTRACE_PROBE_OBJ): $(OBJS)
+	dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(OBJS)
+endif
+endif
+endif
+
 # On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files,
 # so instead of deleting .o files after repacking them into a dylib, we make
 # symlinks back to the originals. The symlinks are a no-op for stabs debugging,
 # so no need to conditionalize on OS version or debugging format.
 
 $(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) Makefile Makefile.in
 ifndef INCREMENTAL_LINKER
 	rm -f $@
@@ -1073,35 +1082,35 @@ ifdef IS_COMPONENT
 endif
 endif
 ifdef NO_LD_ARCHIVE_FLAGS
 ifdef SHARED_LIBRARY_LIBS
 	@rm -f $(SUB_SHLOBJS)
 	@for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
 endif # SHARED_LIBRARY_LIBS
 endif # NO_LD_ARCHIVE_FLAGS
-ifdef NEED_DTRACE_PROBE_OBJ
+ifdef DTRACE_LIB_DEPENDENT
 	@rm -f $(PROBE_LOBJS)
 	@for lib in $(MOZILLA_PROBE_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
-	dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o  $(NEED_DTRACE_PROBE_OBJ) $(PROBE_LOBJS)
+	dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS)
 	@for lib in $(MOZILLA_PROBE_LIBS); do \
 		ofiles=`$(AR_LIST) $${lib}`; \
 		$(AR_DELETE) $${lib} $$ofiles; \
 	done
-	$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(NEED_DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
+	$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 	@rm -f $(PROBE_LOBJS)
-	@rm -f $(NEED_DTRACE_PROBE_OBJ)
+	@rm -f $(DTRACE_PROBE_OBJ)
 	@for lib in $(MOZILLA_PROBE_LIBS); do \
 		if [ -L $${lib} ]; then rm -f `readlink $${lib}`; fi; \
 	done
 	@rm -f $(MOZILLA_PROBE_LIBS)
 
 else
 	$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
-endif # NEED_DTRACE_PROBE_OBJ
+endif # DTRACE_LIB_DEPENDENT
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -552,16 +552,18 @@ public:
    */
   static PRBool CanLoadImage(nsIURI* aURI,
                              nsISupports* aContext,
                              nsIDocument* aLoadingDocument,
                              nsIPrincipal* aLoadingPrincipal,
                              PRInt16* aImageBlockingStatus = nsnull);
   /**
    * Method to start an image load.  This does not do any security checks.
+   * This method will attempt to make aURI immutable; a caller that wants to
+   * keep a mutable version around should pass in a clone.
    *
    * @param aURI uri of the image to be loaded
    * @param aLoadingDocument the document we belong to
    * @param aLoadingPrincipal the principal doing the load
    * @param aReferrer the referrer URI
    * @param aObserver the observer for the image load
    * @param aLoadFlags the load flags to use.  See nsIRequest
    * @return the imgIRequest for the image load
@@ -746,52 +748,16 @@ public:
   }
 
   /**
    * Return the content policy service
    */
   static nsIContentPolicy *GetContentPolicy();
 
   /**
-   * Make sure that whatever value *aPtr contains at any given moment is
-   * protected from JS GC until we remove the GC root.  A call to this that
-   * succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
-   */
-  static nsresult AddJSGCRoot(jsval* aPtr, const char* aName) {
-    return AddJSGCRoot((void*)aPtr, aName);
-  }
-
-  /**
-   * Make sure that whatever object *aPtr is pointing to at any given moment is
-   * protected from JS GC until we remove the GC root.  A call to this that
-   * succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
-   */
-  static nsresult AddJSGCRoot(JSObject** aPtr, const char* aName) {
-    return AddJSGCRoot((void*)aPtr, aName);
-  }
-
-  /**
-   * Make sure that whatever object *aPtr is pointing to at any given moment is
-   * protected from JS GC until we remove the GC root.  A call to this that
-   * succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
-   */
-  static nsresult AddJSGCRoot(void* aPtr, const char* aName);  
-
-  /**
-   * Remove aPtr as a JS GC root
-   */
-  static nsresult RemoveJSGCRoot(jsval* aPtr) {
-    return RemoveJSGCRoot((void*)aPtr);
-  }
-  static nsresult RemoveJSGCRoot(JSObject** aPtr) {
-    return RemoveJSGCRoot((void*)aPtr);
-  }
-  static nsresult RemoveJSGCRoot(void* aPtr);
-
-  /**
    * Quick helper to determine whether there are any mutation listeners
    * of a given type that apply to this content or any of its ancestors.
    * The method has the side effect to call document's MayDispatchMutationEvent
    * using aTargetForSubtreeModified as the parameter.
    *
    * @param aNode  The node to search for listeners
    * @param aType  The type of listener (NS_EVENT_BITS_MUTATION_*)
    * @param aTargetForSubtreeModified The node which is the target of the
@@ -945,17 +911,17 @@ public:
    * @param aTryReuse When true, the function will try to reuse an existing
    *                  textnodes rather than always creating a new one.
    */
   static nsresult SetNodeTextContent(nsIContent* aContent,
                                      const nsAString& aValue,
                                      PRBool aTryReuse);
 
   /**
-   * Get the textual contents of a node. This is a concatination of all
+   * Get the textual contents of a node. This is a concatenation of all
    * textnodes that are direct or (depending on aDeep) indirect children
    * of the node.
    *
    * NOTE! No serialization takes place and <br> elements
    * are not converted into newlines. Only textnodes and cdata nodes are
    * added to the result.
    *
    * @param aNode Node to get textual contents of.
@@ -995,50 +961,83 @@ public:
     }
   }
 
   /**
    * Unbinds the content from the tree and nulls it out if it's not null.
    */
   static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
 
-  static nsresult HoldScriptObject(PRUint32 aLangID, void *aObject);
-  static nsresult DropScriptObject(PRUint32 aLangID, void *aObject);
-
-  class ScriptObjectHolder
+  /**
+   * Keep script object aNewObject, held by aScriptObjectHolder, alive.
+   *
+   * NOTE: This currently only supports objects that hold script objects of one
+   *       scripting language.
+   *
+   * @param aLangID script language ID of aNewObject
+   * @param aScriptObjectHolder the object that holds aNewObject
+   * @param aTracer the tracer for aScriptObject
+   * @param aNewObject the script object to hold
+   * @param aWasHoldingObjects whether aScriptObjectHolder was already holding
+   *                           script objects (ie. HoldScriptObject was called
+   *                           on it before, without a corresponding call to
+   *                           DropScriptObjects)
+   */
+  static nsresult HoldScriptObject(PRUint32 aLangID, void* aScriptObjectHolder,
+                                   nsScriptObjectTracer* aTracer,
+                                   void* aNewObject, PRBool aWasHoldingObjects)
   {
-  public:
-    ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
-                                           mObject(nsnull)
-    {
-      MOZ_COUNT_CTOR(ScriptObjectHolder);
-    }
-    ~ScriptObjectHolder()
-    {
-      MOZ_COUNT_DTOR(ScriptObjectHolder);
-      if (mObject)
-        DropScriptObject(mLangID, mObject);
+    if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
+      return aWasHoldingObjects ? NS_OK :
+                                  HoldJSObjects(aScriptObjectHolder, aTracer);
     }
-    nsresult set(void *aObject)
-    {
-      NS_ASSERTION(aObject, "unexpected null object");
-      NS_ASSERTION(!mObject, "already have an object");
-      nsresult rv = HoldScriptObject(mLangID, aObject);
-      if (NS_SUCCEEDED(rv)) {
-        mObject = aObject;
-      }
-      return rv;
+
+    return HoldScriptObject(aLangID, aNewObject);
+  }
+
+  /**
+   * Drop any script objects that aScriptObjectHolder is holding.
+   *
+   * NOTE: This currently only supports objects that hold script objects of one
+   *       scripting language.
+   *
+   * @param aLangID script language ID of the objects that 
+   * @param aScriptObjectHolder the object that holds script object that we want
+   *                            to drop
+   * @param aTracer the tracer for aScriptObject
+   */
+  static nsresult DropScriptObjects(PRUint32 aLangID, void* aScriptObjectHolder,
+                                    nsScriptObjectTracer* aTracer)
+  {
+    if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
+      return DropJSObjects(aScriptObjectHolder);
     }
-    void traverse(nsCycleCollectionTraversalCallback &cb)
-    {
-      cb.NoteScriptChild(mLangID, mObject);
-    }
-    PRUint32 mLangID;
-    void *mObject;
-  };
+
+    aTracer->Trace(aScriptObjectHolder, DropScriptObject, nsnull);
+
+    return NS_OK;
+  }
+
+  /**
+   * Keep the JS objects held by aScriptObjectHolder alive.
+   *
+   * @param aScriptObjectHolder the object that holds JS objects that we want to
+   *                            keep alive
+   * @param aTracer the tracer for aScriptObject
+   */
+  static nsresult HoldJSObjects(void* aScriptObjectHolder,
+                                nsScriptObjectTracer* aTracer);
+
+  /**
+   * Drop the JS objects held by aScriptObjectHolder.
+   *
+   * @param aScriptObjectHolder the object that holds JS objects that we want to
+   *                            drop
+   */
+  static nsresult DropJSObjects(void* aScriptObjectHolder);
 
   /**
    * Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
    */
   static PRUint32 GetKBStateControlStatusFromIMEStatus(PRUint32 aState);
 
   /*
    * Notify when the first XUL menu is opened and when the all XUL menus are
@@ -1115,16 +1114,20 @@ private:
                                            JSObject *aNewGlobal,
                                            nsIDocument *aOldDocument,
                                            nsIDocument *aNewDocument);
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
+  static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
+  PR_STATIC_CALLBACK(void) DropScriptObject(PRUint32 aLangID, void *aObject,
+                                            void *aClosure);
+
   static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
 
   static nsIXPConnect *sXPConnect;
 
   static nsIScriptSecurityManager *sSecurityManager;
 
   static nsIThreadJSContextStack *sThreadJSContextStack;
 
@@ -1156,33 +1159,36 @@ private:
 
   static nsILineBreaker* sLineBreaker;
   static nsIWordBreaker* sWordBreaker;
   static nsICaseConversion* sCaseConv;
 
   // Holds pointers to nsISupports* that should be released at shutdown
   static nsVoidArray* sPtrsToPtrsToRelease;
 
-  // For now, we don't want to automatically clean this up in Shutdown(), since
-  // consumers might unfortunately end up wanting to use it after that
-  static nsIJSRuntimeService* sJSRuntimeService;
-  static JSRuntime* sJSScriptRuntime;
-  static PRInt32 sJSScriptRootCount;
-
   static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
   static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
+  static PRUint32 sJSGCThingRootCount;
 
 #ifdef IBMBIDI
   static nsIBidiKeyboard* sBidiKeyboard;
 #endif
 
   static PRBool sInitialized;
 };
 
 
+#define NS_HOLD_JS_OBJECTS(obj, clazz)                                         \
+  nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz),        \
+                                &NS_CYCLE_COLLECTION_NAME(clazz))
+
+#define NS_DROP_JS_OBJECTS(obj, clazz)                                         \
+  nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
+
+
 class nsCxPusher
 {
 public:
   nsCxPusher();
   ~nsCxPusher(); // Calls Pop();
 
   // Returns PR_FALSE if something erroneous happened.
   PRBool Push(nsISupports *aCurrentTarget);
@@ -1195,43 +1201,48 @@ private:
 };
 
 class nsAutoGCRoot {
 public:
   // aPtr should be the pointer to the jsval we want to protect
   nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
     mPtr(aPtr)
   {
-    mResult = *aResult =
-      nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
+    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
   }
 
   // aPtr should be the pointer to the JSObject* we want to protect
   nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
     mPtr(aPtr)
   {
-    mResult = *aResult =
-      nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
+    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
   }
 
   // aPtr should be the pointer to the thing we want to protect
   nsAutoGCRoot(void* aPtr, nsresult* aResult) :
     mPtr(aPtr)
   {
-    mResult = *aResult =
-      nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
+    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
   }
 
   ~nsAutoGCRoot() {
     if (NS_SUCCEEDED(mResult)) {
-      nsContentUtils::RemoveJSGCRoot(mPtr);
+      RemoveJSGCRoot(mPtr);
     }
   }
 
+  static void Shutdown();
+
 private:
+  static nsresult AddJSGCRoot(void *aPtr, const char* aName);
+  static nsresult RemoveJSGCRoot(void *aPtr);
+
+  static nsIJSRuntimeService* sJSRuntimeService;
+  static JSRuntime* sJSScriptRuntime;
+
   void* mPtr;
   nsresult mResult;
 };
 
 #define NS_AUTO_GCROOT_PASTE2(tok,line) tok##line
 #define NS_AUTO_GCROOT_PASTE(tok,line) \
   NS_AUTO_GCROOT_PASTE2(tok,line)
 #define NS_AUTO_GCROOT(ptr, result) \ \
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -95,18 +95,21 @@ enum {
   // Optimizations to quickly check whether element may have ID, class or style
   // attributes. Not all element implementations may use these!
   NODE_MAY_HAVE_ID =             0x00000200U,
   NODE_MAY_HAVE_CLASS =          0x00000400U,
   NODE_MAY_HAVE_STYLE =          0x00000800U,
 
   NODE_IS_INSERTION_PARENT =     0x00001000U,
 
+  // Keep track of whether this node is in the middle of binding teardown
+  NODE_IS_IN_BINDING_TEARDOWN =  0x00002000U,
+
   // Four bits for the script-type ID
-  NODE_SCRIPT_TYPE_OFFSET =               13,
+  NODE_SCRIPT_TYPE_OFFSET =               14,
 
   NODE_SCRIPT_TYPE_SIZE =                  4,
 
   // Remaining bits are node type specific.
   NODE_TYPE_SPECIFIC_BITS_OFFSET =
     NODE_SCRIPT_TYPE_OFFSET + NODE_SCRIPT_TYPE_SIZE
 };
 
--- a/content/base/public/nsLineBreaker.h
+++ b/content/base/public/nsLineBreaker.h
@@ -68,19 +68,19 @@ public:
  * with each text chunk, which might happen during the corresponding AppendText
  * call, or might happen during a later AppendText call or even a Reset()
  * call.
  * 
  * The linebreak results MUST NOT depend on how the text is broken up
  * into AppendText calls.
  * 
  * The current strategy is that we break the overall text into
- * whitespace-delimited "words". Then for words that contain a "complex" 
- * character (currently CJK or Thai), we break within the word using complex
- * rules (JISx4051 or Pango).
+ * whitespace-delimited "words". Then those words are passed to the nsILineBreaker
+ * service for deeper analysis if they contain a "complex" character as described
+ * below.
  */
 class nsLineBreaker {
 public:
   nsLineBreaker();
   ~nsLineBreaker();
   
   static inline PRBool IsSpace(PRUnichar u) { return NS_IsSpace(u); }
 
@@ -97,44 +97,60 @@ public:
            NS_NeedsPlatformNativeHandling(u) ||
            (0x1100 <= u && u <= 0x11ff) || // Hangul Jamo
            (0x2000 <= u && u <= 0x21ff) || // Punctuations and Symbols
            (0x2e80 <= u && u <= 0xd7ff) || // several CJK blocks
            (0xf900 <= u && u <= 0xfaff) || // CJK Compatibility Idographs
            (0xff00 <= u && u <= 0xffef);   // Halfwidth and Fullwidth Forms
   }
 
-  // Normally, break opportunities exist at the end of each run of whitespace
-  // (see IsSpace above). Break opportunities can also exist inside runs of
-  // non-whitespace, as determined by nsILineBreaker. We pass a whitespace-
+  // Break opportunities exist at the end of each run of breakable whitespace
+  // (see IsSpace above). Break opportunities can also exist between pairs of
+  // non-whitespace characters, as determined by nsILineBreaker. We pass a whitespace-
   // delimited word to nsILineBreaker if it contains at least one character
   // matching IsComplexChar.
   // We provide flags to control on a per-chunk basis where breaks are allowed.
   // At any character boundary, exactly one text chunk governs whether a
   // break is allowed at that boundary.
   //
   // We operate on text after whitespace processing has been applied, so
   // other characters (e.g. tabs and newlines) may have been converted to
   // spaces.
+
+  /**
+   * Flags passed with each chunk of text.
+   */
   enum {
-    /**
-     * Allow a break opportunity at the start of this chunk of text.
+    /*
+     * Do not introduce a break opportunity at the start of this chunk of text.
      */
-    BREAK_ALLOW_INITIAL = 0x01,
+    BREAK_SUPPRESS_INITIAL = 0x01,
+    /**
+     * Do not introduce a break opportunity in the interior of this chunk of text.
+     * Also, whitespace in this chunk is treated as non-breakable.
+     */
+    BREAK_SUPPRESS_INSIDE = 0x02,
     /**
-     * Allow a break opportunity in the interior of this chunk of text.
+     * The sink currently is already set up to have no breaks in it;
+     * if no breaks are possible, nsLineBreaker does not need to call
+     * SetBreaks on it. This is useful when handling large quantities of
+     * preformatted text; the textruns will never have any breaks set on them,
+     * and there is no need to ever actually scan the text for breaks, except
+     * at the end of textruns in case context is needed for following breakable
+     * text.
      */
-    BREAK_ALLOW_INSIDE = 0x02
+    BREAK_SKIP_SETTING_NO_BREAKS = 0x04
   };
 
   /**
    * Append "invisible whitespace". This acts like whitespace, but there is
-   * no actual text associated with it.
+   * no actual text associated with it. Only the BREAK_SUPPRESS_INSIDE flag
+   * is relevant here.
    */
-  nsresult AppendInvisibleWhitespace();
+  nsresult AppendInvisibleWhitespace(PRUint32 aFlags);
 
   /**
    * Feed Unicode text into the linebreaker for analysis. aLength must be
    * nonzero.
    * @param aSink can be null if the breaks are not actually needed (we may
    * still be setting up state for later breaks)
    */
   nsresult AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32 aLength,
@@ -179,13 +195,16 @@ private:
   // appropriate sink(s). Then we clear the current word state.
   nsresult FlushCurrentWord();
 
   nsAutoTArray<PRUnichar,100> mCurrentWord;
   // All the items that contribute to mCurrentWord
   nsAutoTArray<TextItem,2>    mTextItems;
   PRPackedBool                mCurrentWordContainsComplexChar;
 
-  // True if the previous character was whitespace
-  PRPackedBool                mAfterSpace;
+  // True if the previous character was breakable whitespace
+  PRPackedBool                mAfterBreakableSpace;
+  // True if a break must be allowed at the current position because
+  // a run of breakable whitespace ends here
+  PRPackedBool                mBreakHere;
 };
 
 #endif /*NSLINEBREAKER_H_*/
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -175,25 +175,25 @@ nsDataHashtable<nsISupportsHashKey, Even
 nsIStringBundleService *nsContentUtils::sStringBundleService;
 nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
 nsIContentPolicy *nsContentUtils::sContentPolicyService;
 PRBool nsContentUtils::sTriedToGetContentPolicy = PR_FALSE;
 nsILineBreaker *nsContentUtils::sLineBreaker;
 nsIWordBreaker *nsContentUtils::sWordBreaker;
 nsICaseConversion *nsContentUtils::sCaseConv;
 nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
-nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
-JSRuntime *nsContentUtils::sJSScriptRuntime;
-PRInt32 nsContentUtils::sJSScriptRootCount = 0;
 nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
 PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
+PRUint32 nsContentUtils::sJSGCThingRootCount;
 #ifdef IBMBIDI
 nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
 #endif
 
+nsIJSRuntimeService *nsAutoGCRoot::sJSRuntimeService;
+JSRuntime *nsAutoGCRoot::sJSScriptRuntime;
 
 PRBool nsContentUtils::sInitialized = PR_FALSE;
 
 static PLDHashTable sEventListenerManagersHash;
 
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
 public:
@@ -666,17 +666,18 @@ nsContentUtils::Shutdown()
   NS_IF_RELEASE(sContentPolicyService);
   sTriedToGetContentPolicy = PR_FALSE;
   PRInt32 i;
   for (i = 0; i < PRInt32(PropertiesFile_COUNT); ++i)
     NS_IF_RELEASE(sStringBundles[i]);
   NS_IF_RELEASE(sStringBundleService);
   NS_IF_RELEASE(sConsoleService);
   NS_IF_RELEASE(sDOMScriptObjectFactory);
-  NS_IF_RELEASE(sXPConnect);
+  if (sJSGCThingRootCount == 0 && sXPConnect)
+    NS_RELEASE(sXPConnect);
   NS_IF_RELEASE(sSecurityManager);
   NS_IF_RELEASE(sThreadJSContextStack);
   NS_IF_RELEASE(sNameSpaceManager);
   NS_IF_RELEASE(sParserService);
   NS_IF_RELEASE(sIOService);
   NS_IF_RELEASE(sLineBreaker);
   NS_IF_RELEASE(sWordBreaker);
   NS_IF_RELEASE(sCaseConv);
@@ -716,16 +717,18 @@ nsContentUtils::Shutdown()
     // it could leave dangling references in DOMClassInfo's preserved
     // wrapper table.
 
     if (sEventListenerManagersHash.entryCount == 0) {
       PL_DHashTableFinish(&sEventListenerManagersHash);
       sEventListenerManagersHash.ops = nsnull;
     }
   }
+
+  nsAutoGCRoot::Shutdown();
 }
 
 static PRBool IsCallerTrustedForCapability(const char* aCapability)
 {
   // The secman really should handle UniversalXPConnect case, since that
   // should include UniversalBrowserRead... doesn't right now, though.
   PRBool hasCap;
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
@@ -2152,16 +2155,19 @@ nsContentUtils::LoadImage(nsIURI* aURI, 
     return NS_OK;
   }
 
   nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
   NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
 
   nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
 
+  // Make the URI immutable so people won't change it under us
+  NS_TryToSetImmutable(aURI);
+
   // We don't use aLoadingPrincipal for anything here yet... but we
   // will.  See bug 377092.
 
   // XXXbz using "documentURI" for the initialDocumentURI is not quite
   // right, but the best we can do here...
   return sImgLoader->LoadImage(aURI,                 /* uri to load */
                                documentURI,          /* initialDocumentURI */
                                aReferrer,            /* referrer */
@@ -2664,17 +2670,17 @@ nsContentUtils::GetContentPolicy()
     sTriedToGetContentPolicy = PR_TRUE;
   }
 
   return sContentPolicyService;
 }
 
 // static
 nsresult
-nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
+nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName)
 {
   if (!sJSScriptRuntime) {
     nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
                                  &sJSRuntimeService);
     NS_ENSURE_TRUE(sJSRuntimeService, rv);
 
     sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
     if (!sJSScriptRuntime) {
@@ -2682,48 +2688,34 @@ nsContentUtils::AddJSGCRoot(void* aPtr, 
       NS_WARNING("Unable to get JS runtime from JS runtime service");
       return NS_ERROR_FAILURE;
     }
   }
 
   PRBool ok;
   ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
   if (!ok) {
-    if (sJSScriptRootCount == 0) {
-      // We just got the runtime... Just null things out, since no
-      // one's expecting us to have a runtime yet
-      NS_RELEASE(sJSRuntimeService);
-      sJSScriptRuntime = nsnull;
-    }
     NS_WARNING("JS_AddNamedRootRT failed");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  // We now have one more root we added to the runtime
-  ++sJSScriptRootCount;
-
   return NS_OK;
 }
 
 /* static */
 nsresult
-nsContentUtils::RemoveJSGCRoot(void* aPtr)
+nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
 {
   if (!sJSScriptRuntime) {
     NS_NOTREACHED("Trying to remove a JS GC root when none were added");
     return NS_ERROR_UNEXPECTED;
   }
 
   ::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
 
-  if (--sJSScriptRootCount == 0) {
-    NS_RELEASE(sJSRuntimeService);
-    sJSScriptRuntime = nsnull;
-  }
-
   return NS_OK;
 }
 
 // static
 PRBool
 nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
 {
   const char* name;
@@ -3517,16 +3509,18 @@ nsContentUtils::GetDOMScriptObjectFactor
   return sDOMScriptObjectFactory;
 }
 
 /* static */
 nsresult
 nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
 {
   NS_ASSERTION(aObject, "unexpected null object");
+  NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
+               "Should use HoldJSObjects.");
   nsresult rv;
 
   PRUint32 langIndex = NS_STID_INDEX(aLangID);
   nsIScriptRuntime *runtime = sScriptRuntimes[langIndex];
   if (!runtime) {
     nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
     NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
 
@@ -3543,27 +3537,57 @@ nsContentUtils::HoldScriptObject(PRUint3
   ++sScriptRootCount[langIndex];
   NS_LOG_ADDREF(sScriptRuntimes[langIndex], sScriptRootCount[langIndex],
                 "HoldScriptObject", sizeof(void*));
 
   return NS_OK;
 }
 
 /* static */
-nsresult
-nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject)
+void
+nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject,
+                                 void *aClosure)
 {
   NS_ASSERTION(aObject, "unexpected null object");
+  NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
+               "Should use DropJSObjects.");
   PRUint32 langIndex = NS_STID_INDEX(aLangID);
   NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
                  "HoldScriptObject");
-  nsresult rv = sScriptRuntimes[langIndex]->DropScriptObject(aObject);
+  sScriptRuntimes[langIndex]->DropScriptObject(aObject);
   if (--sScriptRootCount[langIndex] == 0) {
     NS_RELEASE(sScriptRuntimes[langIndex]);
   }
+}
+
+/* static */
+nsresult
+nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
+                              nsScriptObjectTracer* aTracer)
+{
+  PRBool newHolder;
+  nsresult rv = sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  ++sJSGCThingRootCount;
+  NS_LOG_ADDREF(sXPConnect, sJSGCThingRootCount, "HoldJSObjects",
+                sizeof(void*));
+
+  return NS_OK;
+}
+
+/* static */
+nsresult
+nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
+{
+  NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects");
+  nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder);
+  if (--sJSGCThingRootCount == 0 && !sInitialized) {
+    NS_RELEASE(sXPConnect);
+  }
   return rv;
 }
 
 /* static */
 PRUint32
 nsContentUtils::GetKBStateControlStatusFromIMEStatus(PRUint32 aState)
 {
   switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
@@ -3635,17 +3659,17 @@ nsContentUtils::CheckSecurityBeforeLoad(
       ((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
        SchemeIs(aURIToLoad, "chrome"))) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> loadingURI;
   rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
   NS_ENSURE_SUCCESS(rv, rv);
-  return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad);
+  return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad, PR_TRUE);
 }
 
 /* static */
 void
 nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
                             nsIURI *aLinkURI, const nsString &aTargetSpec,
                             PRBool aClick, PRBool aIsUserTriggered)
 {
@@ -3693,15 +3717,31 @@ nsContentUtils::IsNativeAnonymous(nsICon
     nsIContent* bindingParent = aContent->GetBindingParent();
     if (bindingParent == aContent) {
       NS_ASSERTION(bindingParent->IsNativeAnonymous() ||
                    bindingParent->IsNodeOfType(nsINode::eXUL),
                    "Bogus binding parent?");
       return PR_TRUE;
     }
 
-    NS_ASSERTION(!aContent->IsNativeAnonymous(),
+    // Nasty hack to work around spell-check resolving style on
+    // native-anonymous content that's already been torn down.  Don't assert
+    // !IsNativeAnonymous() if aContent->GetCurrentDoc() is null.  The caller
+    // will get "wrong" style data, but it's just asking for that sort of thing
+    // anyway.
+    NS_ASSERTION(!aContent->IsNativeAnonymous() ||
+                 !aContent->GetCurrentDoc() ||
+                 (aContent->GetParent() &&
+                  aContent->GetParent()->NodeInfo()->
+                    Equals(nsGkAtoms::use, kNameSpaceID_SVG)),
                  "Native anonymous node with wrong binding parent");
     aContent = bindingParent;
   }
 
   return PR_FALSE;
 }
+
+/* static */
+void
+nsAutoGCRoot::Shutdown()
+{
+  NS_IF_RELEASE(sJSRuntimeService);
+}
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -129,17 +129,17 @@ nsCrossSiteListenerProxy::OnStartRequest
   // Check if this was actually a cross domain request
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   if (!channel) {
     return NS_ERROR_DOM_BAD_URI;
   }
   nsCOMPtr<nsIURI> finalURI;
   channel->GetURI(getter_AddRefs(finalURI));
   rv = nsContentUtils::GetSecurityManager()->
-    CheckSameOriginURI(mRequestingURI, finalURI);
+    CheckSameOriginURI(mRequestingURI, finalURI, PR_FALSE);
   if (NS_SUCCEEDED(rv)) {
     mAcceptState = eAccept;
     return ForwardRequest(PR_FALSE);
   }
 
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel);
   if (http) {
     PRBool succeeded;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1156,23 +1156,17 @@ void
 nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
 {
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsIPrincipal> principal;
   if (aChannel) {
     // Note: this code is duplicated in nsXULDocument::StartDocumentLoad and
     // nsScriptSecurityManager::GetChannelPrincipal.    
     // Note: this should match nsDocShell::OnLoadingSite
-    nsLoadFlags loadFlags = 0;
-    nsresult rv = aChannel->GetLoadFlags(&loadFlags);
-    if (NS_SUCCEEDED(rv) && (loadFlags & nsIChannel::LOAD_REPLACE)) {
-      aChannel->GetURI(getter_AddRefs(uri));
-    } else {
-      aChannel->GetOriginalURI(getter_AddRefs(uri));
-    }
+    NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
 
     nsIScriptSecurityManager *securityManager =
       nsContentUtils::GetSecurityManager();
     if (securityManager) {
       securityManager->GetChannelPrincipal(aChannel,
                                            getter_AddRefs(principal));
     }
   }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -787,16 +787,19 @@ protected:
   nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
   nsCOMPtr<nsIHTMLCSSStyleSheet> mStyleAttrStyleSheet;
   nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
 
   nsCOMPtr<nsIScriptEventManager> mScriptEventManager;
 
   nsString mBaseTarget;
 
+  // Our update nesting level
+  PRUint32 mUpdateNestLevel;
+
 private:
   friend class nsUnblockOnloadEvent;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   /**
    * See if aDocument is a child of this.  If so, return the frame element in
@@ -828,15 +831,12 @@ private:
   
   // A map from unvisited URI hashes to content elements
   nsTHashtable<nsUint32ToContentHashEntry> mLinkMap;
   // URIs whose visitedness has changed while we were hidden
   nsCOMArray<nsIURI> mVisitednessChangedURIs;
 
   // Member to store out last-selected stylesheet set.
   nsString mLastStyleSheetSet;
-
-  // Our update nesting level
-  PRUint32 mUpdateNestLevel;
 };
 
 
 #endif /* nsDocument_h___ */
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -833,16 +833,17 @@ GK_ATOM(textarea, "textarea")
 GK_ATOM(textbox, "textbox")
 GK_ATOM(textnode, "textnode")
 GK_ATOM(tfoot, "tfoot")
 GK_ATOM(th, "th")
 GK_ATOM(thead, "thead")
 GK_ATOM(thumb, "thumb")
 GK_ATOM(title, "title")
 GK_ATOM(titlebar, "titlebar")
+GK_ATOM(titlebarcolor, "titlebarcolor")
 GK_ATOM(titletip, "titletip")
 GK_ATOM(toggled, "toggled")
 GK_ATOM(token, "token")
 GK_ATOM(tokenize, "tokenize")
 GK_ATOM(toolbar, "toolbar")
 GK_ATOM(toolbarbutton, "toolbarbutton")
 GK_ATOM(toolbaritem, "toolbaritem")
 GK_ATOM(toolbox, "toolbox")
--- a/content/base/src/nsLineBreaker.cpp
+++ b/content/base/src/nsLineBreaker.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsLineBreaker.h"
 #include "nsContentUtils.h"
 #include "nsILineBreaker.h"
 
 nsLineBreaker::nsLineBreaker()
   : mCurrentWordContainsComplexChar(PR_FALSE),
-    mAfterSpace(PR_FALSE)
+    mAfterBreakableSpace(PR_FALSE), mBreakHere(PR_FALSE)
 {
 }
 
 nsLineBreaker::~nsLineBreaker()
 {
   NS_ASSERTION(mCurrentWord.Length() == 0, "Should have Reset() before destruction!");
 }
 
@@ -67,20 +67,20 @@ nsLineBreaker::FlushCurrentWord()
   }
 
   PRUint32 i;
   PRUint32 offset = 0;
   for (i = 0; i < mTextItems.Length(); ++i) {
     TextItem* ti = &mTextItems[i];
     NS_ASSERTION(ti->mLength > 0, "Zero length word contribution?");
 
-    if (!(ti->mFlags & BREAK_ALLOW_INITIAL) && ti->mSinkOffset == 0) {
+    if ((ti->mFlags & BREAK_SUPPRESS_INITIAL) && ti->mSinkOffset == 0) {
       breakState[offset] = PR_FALSE;
     }
-    if (!(ti->mFlags & BREAK_ALLOW_INSIDE)) {
+    if (ti->mFlags & BREAK_SUPPRESS_INSIDE) {
       PRUint32 exclude = ti->mSinkOffset == 0 ? 1 : 0;
       memset(breakState.Elements() + offset + exclude, PR_FALSE, ti->mLength - exclude);
     }
 
     // Don't set the break state for the first character of the word, because
     // it was already set correctly earlier and we don't know what the true
     // value should be.
     PRUint32 skipSet = i == 0 ? 1 : 0;
@@ -102,17 +102,17 @@ nsLineBreaker::AppendText(nsIAtom* aLang
                           PRUint32 aFlags, nsILineBreakSink* aSink)
 {
   NS_ASSERTION(aLength > 0, "Appending empty text...");
 
   PRUint32 offset = 0;
 
   // Continue the current word
   if (mCurrentWord.Length() > 0) {
-    NS_ASSERTION(!mAfterSpace, "These should not be set");
+    NS_ASSERTION(!mAfterBreakableSpace && !mBreakHere, "These should not be set");
 
     while (offset < aLength && !IsSpace(aText[offset])) {
       mCurrentWord.AppendElement(aText[offset]);
       if (!mCurrentWordContainsComplexChar && IsComplexChar(aText[offset])) {
         mCurrentWordContainsComplexChar = PR_TRUE;
       }
       ++offset;
     }
@@ -132,41 +132,48 @@ nsLineBreaker::AppendText(nsIAtom* aLang
 
   nsAutoTArray<PRPackedBool,4000> breakState;
   if (aSink) {
     if (!breakState.AppendElements(aLength))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   PRUint32 start = offset;
-  if (!aSink && !aFlags) {
-    // Skip to the space before the last word, since we don't need the breaks
+  PRBool noBreaksNeeded = !aSink ||
+    ((aFlags & BREAK_SUPPRESS_INITIAL) && (aFlags & BREAK_SUPPRESS_INSIDE) &&
+     !mBreakHere && !mAfterBreakableSpace && (aFlags & BREAK_SKIP_SETTING_NO_BREAKS));
+  if (noBreaksNeeded) {
+    // Skip to the space before the last word, since either the break data
+    // here is not needed, or no breaks are set in the sink and there cannot
+    // be any breaks in this chunk; all we need is the context for the next
+    // chunk (if any)
     offset = aLength;
     while (offset > start) {
       --offset;
       if (IsSpace(aText[offset]))
         break;
     }
   }
   PRUint32 wordStart = offset;
   PRBool wordHasComplexChar = PR_FALSE;
 
   for (;;) {
     PRUnichar ch = aText[offset];
     PRBool isSpace = IsSpace(ch);
+    PRBool isBreakableSpace = isSpace && !(aFlags & BREAK_SUPPRESS_INSIDE);
 
     if (aSink) {
-      breakState[offset] = mAfterSpace && !isSpace &&
-        (aFlags & (offset == 0 ? BREAK_ALLOW_INITIAL : BREAK_ALLOW_INSIDE));
+      breakState[offset] = mBreakHere || (mAfterBreakableSpace && !isBreakableSpace);
     }
-    mAfterSpace = isSpace;
+    mBreakHere = PR_FALSE;
+    mAfterBreakableSpace = isBreakableSpace;
 
     if (isSpace) {
       if (offset > wordStart && wordHasComplexChar) {
-        if (aSink && (aFlags & BREAK_ALLOW_INSIDE)) {
+        if (aSink && !(aFlags & BREAK_SUPPRESS_INSIDE)) {
           // Save current start-of-word state because GetJISx4051Breaks will
           // set it to false
           PRPackedBool currentStart = breakState[wordStart];
           nsContentUtils::LineBreaker()->
             GetJISx4051Breaks(aText + wordStart, offset - wordStart,
                               breakState.Elements() + wordStart);
           breakState[wordStart] = currentStart;
         }
@@ -193,33 +200,33 @@ nsLineBreaker::AppendText(nsIAtom* aLang
         mTextItems.AppendElement(TextItem(aSink, wordStart, len, aFlags));
         // Ensure that the break-before for this word is written out
         offset = wordStart + 1;
         break;
       }
     }
   }
 
-  if (aSink) {
+  if (!noBreaksNeeded) {