Merge mozilla-central to services-central.
authorRichard Newman <rnewman@mozilla.com>
Mon, 22 Aug 2011 08:03:23 -0700
changeset 75730 2a9fb4f365011f1d6e3949df5ecda28ddc8bcee7
parent 75729 dfb016c497aeefbd7d810eb648586c67ce6eb0b7 (current diff)
parent 75640 b7c8af20e4009560b86cb6b84d7025b62ceaaa25 (diff)
child 75731 2a68cc330b3406aef2ccb15ccfc8fee46dbf4b40
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone9.0a1
Merge mozilla-central to services-central.
browser/base/content/tabview/modules/AllTabs.jsm
browser/base/content/test/tabview/browser_tabview_bug627239.js
browser/components/migration/src/nsNetscapeProfileMigratorBase.cpp
browser/components/migration/src/nsNetscapeProfileMigratorBase.h
browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
browser/components/migration/src/nsSeamonkeyProfileMigrator.h
config/gtscc.c
db/Makefile.in
docshell/base/nsIGlobalHistory3.idl
dom/interfaces/css/nsIDOMDocumentCSS.idl
js/src/jit-test/tests/bug666448.js
layout/reftests/svg/dynamic-filter-contents-01.svg
mobile/chrome/content/browser.xul
modules/libreg/src/mmapio.c
modules/libreg/src/mmapio.h
modules/plugin/test/unit/xpcshell.ini
nsprpub/lib/msgc/.cvsignore
nsprpub/lib/msgc/Makefile.in
nsprpub/lib/msgc/include/.cvsignore
nsprpub/lib/msgc/include/Makefile.in
nsprpub/lib/msgc/include/gcint.h
nsprpub/lib/msgc/include/prgc.h
nsprpub/lib/msgc/src/.cvsignore
nsprpub/lib/msgc/src/Makefile.in
nsprpub/lib/msgc/src/os2gc.c
nsprpub/lib/msgc/src/prgcapi.c
nsprpub/lib/msgc/src/prmsgc.c
nsprpub/lib/msgc/src/unixgc.c
nsprpub/lib/msgc/src/win32gc.c
nsprpub/lib/msgc/tests/.cvsignore
nsprpub/lib/msgc/tests/Makefile.in
nsprpub/lib/msgc/tests/gc1.c
nsprpub/lib/msgc/tests/thrashgc.c
security/nss/cmd/lib/NSPRerrs.h
security/nss/cmd/lib/SECerrs.h
security/nss/cmd/lib/SSLerrs.h
security/nss/lib/zlib/gzio.c
toolkit/components/places/History.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -198,14 +198,29 @@ ifdef MOZ_CRASHREPORTER
 endif
 
 codesighs:
 	$(MAKE) -C $(MOZ_BUILD_APP)/installer codesighs
 
 # defined in package-name.mk
 export MOZ_SOURCE_STAMP
 
+#XXX: this is a hack, since we don't want to clobber for MSVC
+# PGO support, but we can't do this test in client.mk
+ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
+# No point in clobbering if PGO has been explicitly disabled.
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+maybe_clobber_profiledbuild: clean
+else
+maybe_clobber_profiledbuild:
+endif
+else
+maybe_clobber_profiledbuild:
+endif
+
+.PHONY: maybe_clobber_profiledbuild
+
 # Look for R_386_PC32 relocations in shared libs, these
 # break x86_64 builds and SELinux users.
 ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
 scheck::
 	@relcount=`find $(DIST)/bin -name "*.so" | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo "FAILED: R_386_PC32 relocations detected in a shared library.  Did you use a system header without adding it to config/system-headers?"; exit 1; else echo "PASSED"; fi
 endif
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -876,17 +876,17 @@ pref("browser.privatebrowsing.autostart"
 // Whether we should skip prompting before starting the private browsing mode
 pref("browser.privatebrowsing.dont_prompt_on_enter", false);
 
 // Don't try to alter this pref, it'll be reset the next time you use the
 // bookmarking dialog
 pref("browser.bookmarks.editDialog.firstEditField", "namePicker");
 
 // base url for the wifi geolocation network provider
-pref("geo.wifi.uri", "https://www.google.com/loc/json");
+pref("geo.wifi.uri", "https://maps.googleapis.com/maps/api/browserlocation/json");
 pref("geo.wifi.protocol", 0);
 
 // Whether to use a panel that looks like an OS X sheet for customization
 #ifdef XP_MACOSX
 pref("toolbar.customization.usesheet", true);
 #else
 pref("toolbar.customization.usesheet", false);
 #endif
--- a/browser/base/content/domplate.jsm
+++ b/browser/base/content/domplate.jsm
@@ -1626,17 +1626,17 @@ BaseTemplates.Element = domplate(BaseTem
 ///////////////////////////////////////////////////////////////////////////
 //// HTMLTemplates.tags
 
 BaseTemplates.AttrTag =
   domplate.SPAN({"class": "nodeAttr editGroup"},
     "&nbsp;",
     domplate.SPAN({"class": "nodeName editable"}, "$attr.nodeName"),
     "=&quot;",
-    domplate.SPAN({"class": "nodeValue editable"}, "$attr.nodeValue"),
+    domplate.SPAN({"class": "nodeValue editable", "data-attributeName": "$attr.nodeName"}, "$attr.nodeValue"),
     "&quot;");
 
 BaseTemplates.TextTag =
   domplate.SPAN({"class": "nodeText editable"},
     domplate.FOR("chr", "$object|getNodeTextGroups",
       domplate.SPAN({"class": "$chr.class $chr.extra"},
         "$chr.str")));
 
--- a/browser/base/content/inspector.html
+++ b/browser/base/content/inspector.html
@@ -2,10 +2,13 @@
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <link rel="stylesheet" href="chrome://browser/skin/inspector.css" type="text/css"/>
 </head>
 <body role="application">
+  <div id="attribute-editor">
+    <input id="attribute-editor-input" />
+  </div>
 </body>
 </html>
--- a/browser/base/content/inspector.js
+++ b/browser/base/content/inspector.js
@@ -21,16 +21,17 @@
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Rob Campbell <rcampbell@mozilla.com> (original author)
  *   Mihai Șucan <mihai.sucan@gmail.com>
  *   Julian Viereck <jviereck@mozilla.com>
  *   Paul Rouget <paul@mozilla.com>
+ *   Kyle Simpson <ksimpson@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
@@ -65,16 +66,21 @@ const INSPECTOR_NOTIFICATIONS = {
   UNHIGHLIGHTING: "inspector-unhighlighting",
 
   // Fires once the Inspector completes the initialization and opens up on
   // screen.
   OPENED: "inspector-opened",
 
   // Fires once the Inspector is closed.
   CLOSED: "inspector-closed",
+
+  // Event notifications for the attribute-value editor
+  EDITOR_OPENED: "inspector-editor-opened",
+  EDITOR_CLOSED: "inspector-editor-closed",
+  EDITOR_SAVED: "inspector-editor-saved",
 };
 
 ///////////////////////////////////////////////////////////////////////////
 //// Highlighter
 
 /**
  * A highlighter mechanism.
  *
@@ -586,16 +592,18 @@ var InspectorUI = {
   {
     this.treeBrowserDocument = this.treeIFrame.contentDocument;
     this.treePanelDiv = this.treeBrowserDocument.createElement("div");
     this.treeBrowserDocument.body.appendChild(this.treePanelDiv);
     this.treePanelDiv.ownerPanel = this;
     this.ioBox = new InsideOutBox(this, this.treePanelDiv);
     this.ioBox.createObjectBox(this.win.document.documentElement);
     this.treeLoaded = true;
+    this.editingContext = null;
+    this.editingEvents = {};
 
     // initialize the highlighter
     this.initializeHighlighter();
   },
 
   /**
    * Open the inspector's tree panel and initialize it.
    */
@@ -609,16 +617,17 @@ var InspectorUI = {
     this.treeIFrame = document.getElementById("inspector-tree-iframe");
     if (!this.treeIFrame) {
       let resizerBox = document.getElementById("tree-panel-resizer-box");
       this.treeIFrame = document.createElement("iframe");
       this.treeIFrame.setAttribute("id", "inspector-tree-iframe");
       this.treeIFrame.setAttribute("flex", "1");
       this.treeIFrame.setAttribute("type", "content");
       this.treeIFrame.setAttribute("onclick", "InspectorUI.onTreeClick(event)");
+      this.treeIFrame.setAttribute("ondblclick", "InspectorUI.onTreeDblClick(event);");
       this.treeIFrame = this.treePanel.insertBefore(this.treeIFrame, resizerBox);
     }
 
     this.treePanel.addEventListener("popupshown", function treePanelShown() {
       InspectorUI.treePanel.removeEventListener("popupshown",
         treePanelShown, false);
 
         InspectorUI.treeIFrame.addEventListener("load",
@@ -812,16 +821,21 @@ var InspectorUI = {
    *
    * @param boolean aKeepStore
    *        Tells if you want the store associated to the current tab/window to
    *        be cleared or not. Set this to true to not clear the store, or false
    *        otherwise.
    */
   closeInspectorUI: function IUI_closeInspectorUI(aKeepStore)
   {
+    // if currently editing an attribute value, closing the
+    // highlighter/HTML panel dismisses the editor
+    if (this.editingContext)
+      this.closeEditor();
+
     if (this.closing || !this.win || !this.browser) {
       return;
     }
 
     this.closing = true;
     this.toolbar.hidden = true;
 
     if (!aKeepStore) {
@@ -849,18 +863,21 @@ var InspectorUI = {
     if (this.treePanelDiv) {
       this.treePanelDiv.ownerPanel = null;
       let parent = this.treePanelDiv.parentNode;
       parent.removeChild(this.treePanelDiv);
       delete this.treePanelDiv;
       delete this.treeBrowserDocument;
     }
 
-    if (this.treeIFrame)
+    if (this.treeIFrame) {
+      let parent = this.treeIFrame.parentNode;
+      parent.removeChild(this.treeIFrame);
       delete this.treeIFrame;
+    }
     delete this.ioBox;
 
     if (this.domplate) {
       this.domplateUtils.setDOM(null);
       delete this.domplate;
       delete this.HTMLTemplates;
       delete this.domplateUtils;
     }
@@ -874,30 +891,37 @@ var InspectorUI = {
 
     this.inspectCmd.setAttribute("checked", false);
     this.browser = this.win = null; // null out references to browser and window
     this.winID = null;
     this.selection = null;
     this.treeLoaded = false;
 
     this.treePanel.addEventListener("popuphidden", function treePanelHidden() {
+      this.removeEventListener("popuphidden", treePanelHidden, false);
+
       InspectorUI.closing = false;
       Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
     }, false);
 
     this.treePanel.hidePopup();
     delete this.treePanel;
   },
 
   /**
    * Begin inspecting webpage, attach page event listeners, activate
    * highlighter event listeners.
    */
   startInspecting: function IUI_startInspecting()
   {
+    // if currently editing an attribute value, starting
+    // "live inspection" mode closes the editor
+    if (this.editingContext)
+      this.closeEditor();
+
     document.getElementById("inspector-inspect-toolbutton").checked = true;
     this.attachPageListeners();
     this.inspecting = true;
     this.highlighter.veilTransparentBox.removeAttribute("locked");
   },
 
   /**
    * Stop inspecting webpage, detach page listeners, disable highlighter
@@ -928,16 +952,21 @@ var InspectorUI = {
    *        node to inspect
    * @param forceUpdate
    *        force an update?
    * @param aScroll
    *        force scroll?
    */
   select: function IUI_select(aNode, forceUpdate, aScroll)
   {
+    // if currently editing an attribute value, using the
+    // highlighter dismisses the editor
+    if (this.editingContext)
+      this.closeEditor();
+
     if (!aNode)
       aNode = this.defaultSelection;
 
     if (forceUpdate || aNode != this.selection) {
       this.selection = aNode;
       if (!this.inspecting) {
         this.highlighter.highlightNode(this.selection);
       }
@@ -1039,16 +1068,27 @@ var InspectorUI = {
 
   /**
    * Handle click events in the html tree panel.
    * @param aEvent
    *        The mouse event.
    */
   onTreeClick: function IUI_onTreeClick(aEvent)
   {
+    // if currently editing an attribute value, clicking outside
+    // the editor dismisses the editor
+    if (this.editingContext) {
+      this.closeEditor();
+
+      // clicking outside the editor ONLY closes the editor
+      // so, cancel the rest of the processing of this event
+      aEvent.preventDefault();
+      return;
+    }
+
     let node;
     let target = aEvent.target;
     let hitTwisty = false;
     if (this.hasClass(target, "twisty")) {
       node = this.getRepObject(aEvent.target.nextSibling);
       hitTwisty = true;
     } else {
       node = this.getRepObject(aEvent.target);
@@ -1064,16 +1104,230 @@ var InspectorUI = {
           this.select(node, true, false);
           this.highlighter.highlightNode(node);
         }
       }
     }
   },
 
   /**
+   * Handle double-click events in the html tree panel.
+   * (double-clicking an attribute value allows it to be edited)
+   * @param aEvent
+   *        The mouse event.
+   */
+  onTreeDblClick: function IUI_onTreeDblClick(aEvent)
+  {
+    // if already editing an attribute value, double-clicking elsewhere
+    // in the tree is the same as a click, which dismisses the editor
+    if (this.editingContext)
+      this.closeEditor();
+
+    let target = aEvent.target;
+
+    if (this.hasClass(target, "nodeValue")) {
+      let repObj = this.getRepObject(target);
+      let attrName = target.getAttribute("data-attributeName");
+      let attrVal = target.innerHTML;
+
+      this.editAttributeValue(target, repObj, attrName, attrVal);
+    }
+  },
+
+  /**
+   * Starts the editor for an attribute value.
+   * @param aAttrObj
+   *        The DOM object representing the attribute value in the HTML Tree
+   * @param aRepObj
+   *        The original DOM (target) object being inspected/edited
+   * @param aAttrName
+   *        The name of the attribute being edited
+   * @param aAttrVal
+   *        The current value of the attribute being edited
+   */
+  editAttributeValue: 
+  function IUI_editAttributeValue(aAttrObj, aRepObj, aAttrName, aAttrVal)
+  {
+    let editor = this.treeBrowserDocument.getElementById("attribute-editor");
+    let editorInput = 
+      this.treeBrowserDocument.getElementById("attribute-editor-input");
+    let attrDims = aAttrObj.getBoundingClientRect();
+    // figure out actual viewable viewport dimensions (sans scrollbars)
+    let viewportWidth = this.treeBrowserDocument.documentElement.clientWidth;
+    let viewportHeight = this.treeBrowserDocument.documentElement.clientHeight;
+
+    // saves the editing context for use when the editor is saved/closed
+    this.editingContext = {
+      attrObj: aAttrObj,
+      repObj: aRepObj,
+      attrName: aAttrName
+    };
+
+    // highlight attribute-value node in tree while editing
+    this.addClass(aAttrObj, "editingAttributeValue");
+
+    // show the editor
+    this.addClass(editor, "editing");
+
+    // offset the editor below the attribute-value node being edited
+    let editorVeritcalOffset = 2;
+
+    // keep the editor comfortably within the bounds of the viewport
+    let editorViewportBoundary = 5;
+
+    // outer editor is sized based on the <input> box inside it
+    editorInput.style.width = Math.min(attrDims.width, viewportWidth - 
+                                editorViewportBoundary) + "px";
+    editorInput.style.height = Math.min(attrDims.height, viewportHeight - 
+                                editorViewportBoundary) + "px";
+    let editorDims = editor.getBoundingClientRect();
+
+    // calculate position for the editor according to the attribute node
+    let editorLeft = attrDims.left + this.treeIFrame.contentWindow.scrollX -
+                    // center the editor against the attribute value    
+                    ((editorDims.width - attrDims.width) / 2); 
+    let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY + 
+                    attrDims.height + editorVeritcalOffset;
+
+    // but, make sure the editor stays within the visible viewport
+    editorLeft = Math.max(0, Math.min(
+                                      (this.treeIFrame.contentWindow.scrollX + 
+                                          viewportWidth - editorDims.width),
+                                      editorLeft)
+                          );
+    editorTop = Math.max(0, Math.min(
+                                      (this.treeIFrame.contentWindow.scrollY + 
+                                          viewportHeight - editorDims.height),
+                                      editorTop)
+                          );
+
+    // position the editor
+    editor.style.left = editorLeft + "px";
+    editor.style.top = editorTop + "px";
+
+    // set and select the text
+    editorInput.value = aAttrVal;
+    editorInput.select();
+
+    // listen for editor specific events
+    this.bindEditorEvent(editor, "click", function(aEvent) {
+      aEvent.stopPropagation();
+    });
+    this.bindEditorEvent(editor, "dblclick", function(aEvent) {
+      aEvent.stopPropagation();
+    });
+    this.bindEditorEvent(editor, "keypress", 
+                          this.handleEditorKeypress.bind(this));
+
+    // event notification    
+    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, 
+                                  null);
+  },
+
+  /**
+   * Handle binding an event handler for the editor.
+   * (saves the callback for easier unbinding later)   
+   * @param aEditor
+   *        The DOM object for the editor
+   * @param aEventName
+   *        The name of the event to listen for
+   * @param aEventCallback
+   *        The callback to bind to the event (and also to save for later 
+   *          unbinding)
+   */
+  bindEditorEvent: 
+  function IUI_bindEditorEvent(aEditor, aEventName, aEventCallback)
+  {
+    this.editingEvents[aEventName] = aEventCallback;
+    aEditor.addEventListener(aEventName, aEventCallback, false);
+  },
+
+  /**
+   * Handle unbinding an event handler from the editor.
+   * (unbinds the previously bound and saved callback)   
+   * @param aEditor
+   *        The DOM object for the editor
+   * @param aEventName
+   *        The name of the event being listened for
+   */
+  unbindEditorEvent: function IUI_unbindEditorEvent(aEditor, aEventName)
+  {
+    aEditor.removeEventListener(aEventName, this.editingEvents[aEventName], 
+                                  false);
+    this.editingEvents[aEventName] = null;
+  },
+
+  /**
+   * Handle keypress events in the editor.
+   * @param aEvent
+   *        The keyboard event.
+   */
+  handleEditorKeypress: function IUI_handleEditorKeypress(aEvent)
+  {
+    if (aEvent.which == KeyEvent.DOM_VK_RETURN) {
+      this.saveEditor();
+    } else if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) {
+      this.closeEditor();
+    }
+  },
+
+  /**
+   * Close the editor and cleanup.
+   */
+  closeEditor: function IUI_closeEditor()
+  {
+    let editor = this.treeBrowserDocument.getElementById("attribute-editor");
+    let editorInput = 
+      this.treeBrowserDocument.getElementById("attribute-editor-input");
+
+    // remove highlight from attribute-value node in tree
+    this.removeClass(this.editingContext.attrObj, "editingAttributeValue");
+
+    // hide editor
+    this.removeClass(editor, "editing");
+
+    // stop listening for editor specific events
+    this.unbindEditorEvent(editor, "click");
+    this.unbindEditorEvent(editor, "dblclick");
+    this.unbindEditorEvent(editor, "keypress");
+
+    // clean up after the editor
+    editorInput.value = "";
+    editorInput.blur();
+    this.editingContext = null;
+    this.editingEvents = {};
+
+    // event notification    
+    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, 
+                                  null);
+  },
+
+  /**
+   * Commit the edits made in the editor, then close it.
+   */
+  saveEditor: function IUI_saveEditor()
+  {
+    let editorInput = 
+      this.treeBrowserDocument.getElementById("attribute-editor-input");
+
+    // set the new attribute value on the original target DOM element
+    this.editingContext.repObj.setAttribute(this.editingContext.attrName, 
+                                              editorInput.value);
+
+    // update the HTML tree attribute value
+    this.editingContext.attrObj.innerHTML = editorInput.value;
+
+    // event notification    
+    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, 
+                                  null);
+    
+    this.closeEditor();
+  },
+
+  /**
    * Attach event listeners to content window and child windows to enable
    * highlighting and click to stop inspection.
    */
   attachPageListeners: function IUI_attachPageListeners()
   {
     this.browser.addEventListener("keypress", this, true);
     this.highlighter.attachInspectListeners();
   },
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -74,17 +74,18 @@ nsContextMenu.prototype = {
                    document.popupRangeOffset);
     if (!this.shouldDisplay)
       return;
 
     this.browser = aBrowser;
 
     this.hasPageMenu = false;
     if (!aIsShift) {
-      this.hasPageMenu = PageMenu.init(this.target, aXulMenu);
+      this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target,
+                                                          aXulMenu);
     }
 
     this.isFrameImage = document.getElementById("isFrameImage");
     this.ellipsis = "\u2026";
     try {
       this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/tabview/content.js
@@ -0,0 +1,46 @@
+/* ***** 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 content.js.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Tim Taubert <ttaubert@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 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 ***** */
+
+addEventListener("DOMWillOpenModalDialog", function (event) {
+  // (event.isTrusted == true) when the event is generated by a user action
+  // and does not originate from a script.
+  if (event.isTrusted) {
+    // we're intentionally sending a synchronous message to handle this event
+    // as quick as possible, switch the selected tab and hide the tabview
+    // before the modal dialog is shown
+    sendSyncMessage("Panorama:DOMWillOpenModalDialog");
+  }
+}, true);
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -226,17 +226,17 @@ function GroupItem(listOfEls, options) {
   let appTabTrayContainer = iQ("<div/>")
     .addClass("appTabTrayContainer")
     .appendTo($container);
   this.$appTabTray = iQ("<div/>")
     .addClass("appTabTray")
     .appendTo(appTabTrayContainer);
 
   AllTabs.tabs.forEach(function(xulTab) {
-    if (xulTab.pinned && xulTab.ownerDocument.defaultView == gWindow)
+    if (xulTab.pinned)
       self.addAppTab(xulTab, {dontAdjustTray: true});
   });
 
   // ___ Undo Close
   this.$undoContainer = null;
   this._undoButtonTimeoutId = null;
 
   // ___ Superclass initialization
@@ -739,40 +739,55 @@ GroupItem.prototype = Utils.extend(new I
       return true;
     }
     return false;
   },
 
   // ----------
   // Function: _unhide
   // Shows the hidden group.
-  _unhide: function GroupItem__unhide() {
-    let self = this;
-
+  //
+  // Parameters:
+  //   options - various options (see below)
+  //
+  // Possible options:
+  //   immediately - true when no animations should be used
+  _unhide: function GroupItem__unhide(options) {
     this._cancelFadeAwayUndoButtonTimer();
     this.hidden = false;
     this.$undoContainer.remove();
     this.$undoContainer = null;
     this.droppable(true);
     this.setTrenches(this.bounds);
 
-    iQ(this.container).show().animate({
-      "-moz-transform": "scale(1)",
-      "opacity": 1
-    }, {
-      duration: 170,
-      complete: function() {
-        self._children.forEach(function(child) {
-          iQ(child.container).show();
-        });
+    let self = this;
+
+    let finalize = function () {
+      self._children.forEach(function(child) {
+        iQ(child.container).show();
+      });
+
+      UI.setActive(self);
+      self._sendToSubscribers("groupShown", { groupItemId: self.id });
+    };
+
+    let $container = iQ(this.container).show();
 
-        UI.setActive(self);
-        self._sendToSubscribers("groupShown", { groupItemId: self.id });
-      }
-    });
+    if (!options || !options.immediately) {
+      $container.animate({
+        "-moz-transform": "scale(1)",
+        "opacity": 1
+      }, {
+        duration: 170,
+        complete: finalize
+      });
+    } else {
+      $container.css({"-moz-transform": "none", opacity: 1});
+      finalize();
+    }
 
     GroupItems.updateGroupCloseButtons();
   },
 
   // ----------
   // Function: closeHidden
   // Removes the group item, its children and its container.
   closeHidden: function GroupItem_closeHidden() {
@@ -780,69 +795,83 @@ GroupItem.prototype = Utils.extend(new I
 
     this._cancelFadeAwayUndoButtonTimer();
 
     // When the last non-empty groupItem is closed and there are no
     // pinned tabs then create a new group with a blank tab.
     let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
       return (groupItem != self && groupItem.getChildren().length);
     });
+
+    let tab = null;
+
     if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
       let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
         return (groupItem != self && !groupItem.getChildren().length);
       });
       let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
-      group.newTab(null, { closedLastTab: true });
+      tab = group.newTab(null, {dontZoomIn: true});
     }
 
-    this.destroy();
+    let closed = this.destroy();
+
+    if (!tab)
+      return;
+
+    if (closed) {
+      // Let's make the new tab the selected tab.
+      UI.goToTab(tab);
+    } else {
+      // Remove the new tab and group, if this group is no longer closed.
+      tab._tabViewTabItem.parent.destroy({immediately: true});
+    }
   },
 
   // ----------
   // Function: destroy
   // Close all tabs linked to children (tabItems), removes all children and 
   // close the groupItem.
   //
   // Parameters:
   //   options - An object with optional settings for this call.
   //
   // Options:
   //   immediately - (bool) if true, no animation will be used
+  //
+  // Returns true if the groupItem has been closed, or false otherwise. A group
+  // could not have been closed due to a tab with an onUnload handler (that
+  // waits for user interaction).
   destroy: function GroupItem_destroy(options) {
     let self = this;
 
     // when "TabClose" event is fired, the browser tab is about to close and our 
     // item "close" event is fired.  And then, the browser tab gets closed. 
     // In other words, the group "close" event is fired before all browser
     // tabs in the group are closed.  The below code would fire the group "close"
     // event only after all browser tabs in that group are closed.
-    let shouldRemoveTabItems = [];
-    let toClose = this._children.concat();
-    toClose.forEach(function(child) {
+    this._children.concat().forEach(function(child) {
       child.removeSubscriber("close", self._onChildClose);
 
-      let removed = child.close(true);
-      if (removed) {
-        shouldRemoveTabItems.push(child);
+      if (child.close(true)) {
+        self.remove(child, { dontArrange: true });
       } else {
         // child.removeSubscriber() must be called before child.close(), 
         // therefore we call child.addSubscriber() if the tab is not removed.
         child.addSubscriber("close", self._onChildClose);
       }
     });
 
-    if (shouldRemoveTabItems.length != toClose.length) {
-      // remove children without the assiciated tab and show the group item
-      shouldRemoveTabItems.forEach(function(child) {
-        self.remove(child, { dontArrange: true });
-      });
+    if (this._children.length) {
+      if (this.hidden)
+        this.$undoContainer.fadeOut(function() { self._unhide() });
 
-      this.$undoContainer.fadeOut(function() { self._unhide() });
+      return false;
     } else {
       this.close(options);
+      return true;
     }
   },
 
   // ----------
   // Function: _fadeAwayUndoButton
   // Fades away the undo button
   _fadeAwayUndoButton: function GroupItem__fadeAwayUdoButton() {
     let self = this;
@@ -1813,23 +1842,26 @@ GroupItem.prototype = Utils.extend(new I
   },
 
   // ----------
   // Function: newTab
   // Creates a new tab within this groupItem.
   // Parameters:
   //  url - the new tab should open this url as well
   //  options - the options object
+  //    dontZoomIn - set to true to not zoom into the newly created tab
   //    closedLastTab - boolean indicates the last tab has just been closed
   newTab: function GroupItem_newTab(url, options) {
     if (options && options.closedLastTab)
       UI.closedLastTabInTabView = true;
 
     UI.setActive(this, { dontSetActiveTabInGroup: true });
-    gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
+
+    let dontZoomIn = !!(options && options.dontZoomIn);
+    return gBrowser.loadOneTab(url || "about:blank", { inBackground: dontZoomIn });
   },
 
   // ----------
   // Function: reorderTabItemsBasedOnTabOrder
   // Reorders the tabs in a groupItem based on the arrangment of the tabs
   // shown in the tab bar. It does it by sorting the children
   // of the groupItem by the positions of their respective tabs in the
   // tab bar.
@@ -1921,23 +1953,23 @@ let GroupItems = {
   },
 
   // ----------
   // Function: init
   init: function GroupItems_init() {
     let self = this;
 
     // setup attr modified handler, and prepare for its uninit
-    function handleAttrModified(xulTab) {
-      self._handleAttrModified(xulTab);
+    function handleAttrModified(event) {
+      self._handleAttrModified(event.target);
     }
 
     // make sure any closed tabs are removed from the delay update list
-    function handleClose(xulTab) {
-      let idx = self._delayedModUpdates.indexOf(xulTab);
+    function handleClose(event) {
+      let idx = self._delayedModUpdates.indexOf(event.target);
       if (idx != -1)
         self._delayedModUpdates.splice(idx, 1);
     }
 
     AllTabs.register("attrModified", handleAttrModified);
     AllTabs.register("close", handleClose);
     this._cleanupFunctions.push(function() {
       AllTabs.unregister("attrModified", handleAttrModified);
@@ -2035,17 +2067,17 @@ let GroupItems = {
     });
     this._delayedModUpdates = [];
   },
 
   // ----------
   // Function: _updateAppTabIcons
   // Update images of any apptab icons that point to passed in xultab 
   _updateAppTabIcons: function GroupItems__updateAppTabIcons(xulTab) {
-    if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
+    if (!xulTab.pinned)
       return;
 
     let iconUrl = this.getAppTabFavIconUrl(xulTab);
     this.groupItems.forEach(function(groupItem) {
       iQ(".appTabIcon", groupItem.$appTabTray).each(function(icon) {
         let $icon = iQ(icon);
         if ($icon.data("xulTab") != xulTab)
           return true;
deleted file mode 100644
--- a/browser/base/content/tabview/modules/AllTabs.jsm
+++ /dev/null
@@ -1,183 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is TabView AllTabs.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Edward Lee <edilee@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 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 ***** */
-
-"use strict";
-
-const Cu = Components.utils;
-Cu.import("resource://gre/modules/Services.jsm");
-
-let EXPORTED_SYMBOLS = ["AllTabs"];
-
-let AllTabs = {
-  // ----------
-  // Function: toString
-  // Prints [AllTabs] for debug use
-  toString: function AllTabs_toString() {
-    return "[AllTabs]";
-  },
-
-  /**
-   * Get an array of all tabs from all tabbrowser windows.
-   *
-   * @usage let numAllTabs = AllTabs.tabs.length;
-   *        AllTabs.tabs.forEach(handleAllTabs);
-   */
-  get tabs() {
-    // Get tabs from each browser window and flatten them into one array
-    return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
-      return Array.filter(browserWindow.gBrowser.tabs, function (tab) !tab.closing);
-    }));
-  },
-
-  /**
-   * Attach a callback for a given tab event.
-   *
-   * @param eventName
-   *        Name of the corresponding Tab* Event; one of "attrModified",
-   *        "close", "move", "open", "select", "pinned", "unpinned".
-   * @param callback
-   *        Callback that gets called with the tab as the first argument and
-   *        the event as the second argument.
-   * @usage AllTabs.register("change", function handleChange(tab, event) {});
-   */
-  register: function register(eventName, callback) {
-    // Either add additional callbacks or create the first entry
-    let listeners = eventListeners[events[eventName]];
-    if (listeners)
-      listeners.push(callback);
-    else
-      eventListeners[events[eventName]] = [callback];
-  },
-
-  /**
-   * Remove a callback for a given tab event.
-   *
-   * @param eventName
-   *        Name of the corresponding Tab* Event; one of "attrModified",
-   *        "close", "move", "open", "select", "pinned", "unpinned".
-   * @param callback
-   *        The callback given for the original AllTabs.register call.
-   * @usage AllTabs.unregister("close", handleClose);
-   */
-  unregister: function unregister(eventName, callback) {
-    // Nothing to remove for this event
-    let listeners = eventListeners[events[eventName]];
-    if (!listeners)
-      return;
-
-    // Can only remove a callback if we have it
-    let index = listeners.indexOf(callback);
-    if (index == -1)
-      return;
-
-    listeners.splice(index, 1);
-  }
-};
-
-__defineGetter__("browserWindows", function browserWindows() {
-  let browserWindows = [];
-  let windows = Services.wm.getEnumerator("navigator:browser");
-  while (windows.hasMoreElements())
-    browserWindows.push(windows.getNext());
-  return browserWindows;
-});
-
-let events = {
-  attrModified: "TabAttrModified",
-  close:        "TabClose",
-  move:         "TabMove",
-  open:         "TabOpen",
-  select:       "TabSelect",
-  pinned:       "TabPinned",
-  unpinned:     "TabUnpinned"
-};
-let eventListeners = {};
-
-function registerBrowserWindow(browserWindow) {
-  for each (let event in events)
-    browserWindow.addEventListener(event, tabEventListener, true);
-
-  browserWindow.addEventListener("unload", unregisterBrowserWindow, false);
-}
-
-function unregisterBrowserWindow(unloadEvent) {
-  let browserWindow = unloadEvent.currentTarget;
-
-  for each (let event in events)
-    browserWindow.removeEventListener(event, tabEventListener, true);
-
-  browserWindow.removeEventListener("unload", unregisterBrowserWindow, false);
-}
-
-function tabEventListener(event) {
-  // Make sure we've gotten listeners before trying to call
-  let listeners = eventListeners[event.type];
-  if (!listeners)
-    return;
-
-  let tab = event.target;
-
-  // Make a copy of the listeners, so it can't change as we call back
-  listeners.slice().forEach(function (callback) {
-    try {
-      callback(tab, event);
-    }
-    // Don't let failing callbacks stop us but report the failure
-    catch (ex) {
-      Cu.reportError(ex);
-    }
-  });
-}
-
-function observer(subject, topic, data) {
-  switch (topic) {
-    case "domwindowopened":
-      subject.addEventListener("load", function onLoad() {
-        subject.removeEventListener("load", onLoad, false);
-
-        // Now that the window has loaded, only register on browser windows
-        let doc = subject.document.documentElement;
-        if (doc.getAttribute("windowtype") == "navigator:browser")
-          registerBrowserWindow(subject);
-      }, false);
-      break;
-  }
-}
-
-// Register listeners on all browser windows and future ones
-browserWindows.forEach(registerBrowserWindow);
-Services.obs.addObserver(observer, "domwindowopened", false);
--- a/browser/base/content/tabview/search.js
+++ b/browser/base/content/tabview/search.js
@@ -515,16 +515,19 @@ var TabHandlers = {
   _mouseDownLocation: null
 };
 
 function createSearchTabMacher() {
   return new TabMatcher(iQ("#searchbox").val());
 }
 
 function hideSearch(event) {
+  if (!isSearchEnabled())
+    return;
+
   iQ("#searchbox").val("");
   iQ("#searchshade").hide();
   iQ("#search").hide();
 
   iQ("#searchbutton").css({ opacity:.8 });
 
 #ifdef XP_MACOSX
   UI.setTitlebarColors(true);
--- a/browser/base/content/tabview/storage.js
+++ b/browser/base/content/tabview/storage.js
@@ -74,19 +74,16 @@ let Storage = {
   // Function: wipe
   // Cleans out all the stored data, leaving empty objects.
   wipe: function Storage_wipe() {
     try {
       var self = this;
 
       // ___ Tabs
       AllTabs.tabs.forEach(function(tab) {
-        if (tab.ownerDocument.defaultView != gWindow)
-          return;
-
         self.saveTab(tab, null);
       });
 
       // ___ Other
       this.saveGroupItemsData(gWindow, {});
       this.saveUIData(gWindow, {});
 
       this._sessionStore.setWindowValue(gWindow, this.GROUP_DATA_IDENTIFIER,
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -473,39 +473,32 @@ TabItem.prototype = Utils.extend(new Ite
   // Parameters:
   //   groupClose - true if this method is called by group close action.
   // Returns true if this tab is removed.
   close: function TabItem_close(groupClose) {
     // When the last tab is closed, put a new tab into closing tab's group. If
     // closing tab doesn't belong to a group and no empty group, create a new 
     // one for the new tab.
     if (!groupClose && gBrowser.tabs.length == 1) {
-      let group;
-      if (this.tab._tabViewTabItem.parent) {
-        group = this.tab._tabViewTabItem.parent;
-      } else {
-        let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
-          return (!groupItem.getChildren().length);
-        });
-        group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
-      }
+      let group = this.tab._tabViewTabItem.parent;
       group.newTab(null, { closedLastTab: true });
     }
+
     // when "TabClose" event is fired, the browser tab is about to close and our 
     // item "close" is fired before the browser tab actually get closed. 
     // Therefore, we need "tabRemoved" event below.
     gBrowser.removeTab(this.tab);
-    let tabNotClosed = 
-      Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
-    if (!tabNotClosed)
+    let tabClosed = !this.tab;
+
+    if (tabClosed)
       this._sendToSubscribers("tabRemoved");
 
     // No need to explicitly delete the tab data, becasue sessionstore data
     // associated with the tab will automatically go away
-    return !tabNotClosed;
+    return tabClosed;
   },
 
   // ----------
   // Function: addClass
   // Adds the specified CSS class to this item's container DOM element.
   addClass: function TabItem_addClass(className) {
     this.$container.addClass(className);
   },
@@ -741,46 +734,45 @@ let TabItems = {
     $canvas.hide();
     this.tempCanvas = $canvas[0];
     // 150 pixels is an empirical size, below which FF's drawWindow()
     // algorithm breaks down
     this.tempCanvas.width = 150;
     this.tempCanvas.height = 112;
 
     // When a tab is opened, create the TabItem
-    this._eventListeners["open"] = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
-        return;
+    this._eventListeners.open = function (event) {
+      let tab = event.target;
 
-      self.link(tab);
+      if (!tab.pinned)
+        self.link(tab);
     }
     // When a tab's content is loaded, show the canvas and hide the cached data
     // if necessary.
-    this._eventListeners["attrModified"] = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
-        return;
+    this._eventListeners.attrModified = function (event) {
+      let tab = event.target;
 
-      self.update(tab);
+      if (!tab.pinned)
+        self.update(tab);
     }
     // When a tab is closed, unlink.
-    this._eventListeners["close"] = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
-        return;
+    this._eventListeners.close = function (event) {
+      let tab = event.target;
 
       // XXX bug #635975 - don't unlink the tab if the dom window is closing.
-      if (!UI.isDOMWindowClosing)
+      if (!tab.pinned && !UI.isDOMWindowClosing)
         self.unlink(tab);
     }
     for (let name in this._eventListeners) {
       AllTabs.register(name, this._eventListeners[name]);
     }
 
     // For each tab, create the link.
-    AllTabs.tabs.forEach(function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
+    AllTabs.tabs.forEach(function (tab) {
+      if (tab.pinned)
         return;
 
       self.link(tab, {immediately: true});
       self.update(tab);
     });
   },
 
   // ----------
--- a/browser/base/content/tabview/tabview.js
+++ b/browser/base/content/tabview/tabview.js
@@ -1,16 +1,15 @@
 "use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-Cu.import("resource:///modules/tabview/AllTabs.jsm");
 Cu.import("resource:///modules/tabview/utils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "tabviewBundle", function() {
   return Services.strings.
     createBundle("chrome://browser/locale/tabview.properties");
 });
@@ -39,16 +38,40 @@ XPCOMUtils.defineLazyGetter(this, "gNetU
 
 var gWindow = window.parent;
 var gBrowser = gWindow.gBrowser;
 var gTabView = gWindow.TabView;
 var gTabViewDeck = gWindow.document.getElementById("tab-view-deck");
 var gBrowserPanel = gWindow.document.getElementById("browser-panel");
 var gTabViewFrame = gWindow.document.getElementById("tab-view");
 
+let AllTabs = {
+  _events: {
+    attrModified: "TabAttrModified",
+    close:        "TabClose",
+    move:         "TabMove",
+    open:         "TabOpen",
+    select:       "TabSelect",
+    pinned:       "TabPinned",
+    unpinned:     "TabUnpinned"
+  },
+
+  get tabs() {
+    return Array.filter(gBrowser.tabs, function (tab) !tab.closing);
+  },
+
+  register: function AllTabs_register(eventName, callback) {
+    gBrowser.tabContainer.addEventListener(this._events[eventName], callback, false);
+  },
+
+  unregister: function AllTabs_unregister(eventName, callback) {
+    gBrowser.tabContainer.removeEventListener(this._events[eventName], callback, false);
+  }
+};
+
 # NB: Certain files need to evaluate before others
 
 #include iq.js
 #include storage.js
 #include items.js
 #include groupitems.js
 #include tabitems.js
 #include drag.js
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -21,16 +21,17 @@
  * Contributor(s):
  * Ian Gilman <ian@iangilman.com>
  * Aza Raskin <aza@mozilla.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  * Ehsan Akhgari <ehsan@mozilla.com>
  * Raymond Lee <raymond@appcoast.com>
  * Sean Dunn <seanedunn@yahoo.com>
  * Tim Taubert <tim.taubert@gmx.de>
+ * Mihai Sucan <mihai.sucan@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -75,16 +76,20 @@ let UI = {
   // Variable: _closedSelectedTabInTabView
   // If true, a select tab has just been closed in TabView.
   _closedSelectedTabInTabView: false,
 
   // Variable: restoredClosedTab
   // If true, a closed tab has just been restored.
   restoredClosedTab: false,
 
+  // Variable: _isChangingVisibility
+  // Tracks whether we're currently in the process of showing/hiding the tabview.
+  _isChangingVisibility: false,
+
   // Variable: _reorderTabItemsOnShow
   // Keeps track of the <GroupItem>s which their tab items' tabs have been moved
   // and re-orders the tab items when switching to TabView.
   _reorderTabItemsOnShow: [],
 
   // Variable: _reorderTabsOnHide
   // Keeps track of the <GroupItem>s which their tab items have been moved in
   // TabView UI and re-orders the tabs when switcing back to main browser.
@@ -229,16 +234,25 @@ let UI = {
           }
         }
       });
 
       iQ(window).bind("unload", function() {
         self.uninit();
       });
 
+      // ___ setup DOMWillOpenModalDialog message handler
+      let mm = gWindow.messageManager;
+      let callback = this._onDOMWillOpenModalDialog.bind(this);
+      mm.addMessageListener("Panorama:DOMWillOpenModalDialog", callback);
+
+      this._cleanupFunctions.push(function () {
+        mm.removeMessageListener("Panorama:DOMWillOpenModalDialog", callback);
+      });
+
       // ___ setup key handlers
       this._setTabViewFrameKeyHandlers();
 
       // ___ add tab action handlers
       this._addTabActionHandlers();
 
       // ___ groups
       GroupItems.init();
@@ -271,16 +285,20 @@ let UI = {
         if (self.isTabViewVisible())
           GroupItems.removeHiddenGroups();
 
         Storage.saveActiveGroupName(gWindow);
         TabItems.saveAll(true);
         self._save();
       }, false);
 
+      // ___ load frame script
+      let frameScript = "chrome://browser/content/tabview-content.js";
+      gWindow.messageManager.loadFrameScript(frameScript, true);
+
       // ___ Done
       this._frameInitialized = true;
       this._save();
 
       // fire an iframe initialized event so everyone knows tab view is 
       // initialized.
       let event = document.createEvent("Events");
       event.initEvent("tabviewframeinitialized", true, false);
@@ -476,19 +494,21 @@ let UI = {
   },
 
   // ----------
   // Function: showTabView
   // Shows TabView and hides the main browser UI.
   // Parameters:
   //   zoomOut - true for zoom out animation, false for nothing.
   showTabView: function UI_showTabView(zoomOut) {
-    if (this.isTabViewVisible())
+    if (this.isTabViewVisible() || this._isChangingVisibility)
       return;
 
+    this._isChangingVisibility = true;
+
     // initialize the direction of the page
     this._initPageDirection();
 
     var self = this;
     var currentTab = this._currentTab;
 
     this._reorderTabItemsOnShow.forEach(function(groupItem) {
       groupItem.reorderTabItemsBasedOnTabOrder();
@@ -521,44 +541,48 @@ let UI = {
       // Zoom out!
       item.zoomOut(function() {
         if (!currentTab._tabViewTabItem) // if the tab's been destroyed
           item = null;
 
         self.setActive(item);
 
         self._resize(true);
+        self._isChangingVisibility = false;
         dispatchEvent(event);
 
         // Flush pending updates
         GroupItems.flushAppTabUpdates();
 
         TabItems.resumePainting();
       });
     } else {
       self.clearActiveTab();
+      self._isChangingVisibility = false;
       dispatchEvent(event);
 
       // Flush pending updates
       GroupItems.flushAppTabUpdates();
 
       TabItems.resumePainting();
     }
 
     if (gTabView.firstUseExperienced)
       gTabView.enableSessionRestore();
   },
 
   // ----------
   // Function: hideTabView
   // Hides TabView and shows the main browser UI.
   hideTabView: function UI_hideTabView() {
-    if (!this.isTabViewVisible())
+    if (!this.isTabViewVisible() || this._isChangingVisibility)
       return;
 
+    this._isChangingVisibility = true;
+
     // another tab might be select if user decides to stay on a page when
     // a onclose confirmation prompts.
     GroupItems.removeHiddenGroups();
     TabItems.pausePainting();
 
     this._reorderTabsOnHide.forEach(function(groupItem) {
       groupItem.reorderTabsBasedOnTabItemOrder();
     });
@@ -575,16 +599,18 @@ let UI = {
     gBrowser.contentWindow.focus();
 
     gBrowser.updateTitlebar();
 #ifdef XP_MACOSX
     this.setTitlebarColors(false);
 #endif
     Storage.saveVisibilityData(gWindow, "false");
 
+    this._isChangingVisibility = false;
+
     let event = document.createEvent("Events");
     event.initEvent("tabviewhidden", true, false);
     dispatchEvent(event);
   },
 
 #ifdef XP_MACOSX
   // ----------
   // Function: setTitlebarColors
@@ -680,16 +706,17 @@ let UI = {
         if (data == "enter") {
           // If we are in Tab View, exit. 
           self._privateBrowsing.wasInTabView = self.isTabViewVisible();
           if (self.isTabViewVisible())
             self.goToTab(gBrowser.selectedTab);
         }
       } else if (topic == "private-browsing-change-granted") {
         if (data == "enter" || data == "exit") {
+          hideSearch();
           self._privateBrowsing.transitionMode = data;
           self.storageBusy();
         }
       } else if (topic == "private-browsing-transition-complete") {
         // We use .transitionMode here, as aData is empty.
         if (self._privateBrowsing.transitionMode == "exit" &&
             self._privateBrowsing.wasInTabView)
           self.showTabView(false);
@@ -705,31 +732,29 @@ let UI = {
 
     this._cleanupFunctions.push(function() {
       Services.obs.removeObserver(pbObserver, "private-browsing");
       Services.obs.removeObserver(pbObserver, "private-browsing-change-granted");
       Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
     });
 
     // TabOpen
-    this._eventListeners.open = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
+    this._eventListeners.open = function (event) {
+      let tab = event.target;
 
       // if it's an app tab, add it to all the group items
       if (tab.pinned)
         GroupItems.addAppTab(tab);
       else if (self.isTabViewVisible() && !self._storageBusyCount)
         self._lastOpenedTab = tab;
     };
     
     // TabClose
-    this._eventListeners.close = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
+    this._eventListeners.close = function (event) {
+      let tab = event.target;
 
       // if it's an app tab, remove it from all the group items
       if (tab.pinned)
         GroupItems.removeAppTab(tab);
         
       if (self.isTabViewVisible()) {
         // just closed the selected tab in the TabView interface.
         if (self._currentTab == tab)
@@ -751,77 +776,64 @@ let UI = {
           var groupItem = GroupItems.getActiveGroupItem();
 
           // 1) Only go back to the TabView tab when there you close the last
           // tab of a groupItem.
           let closingLastOfGroup = (groupItem && 
               groupItem._children.length == 1 && 
               groupItem._children[0].tab == tab);
 
-          // 2) Take care of the case where you've closed the last tab in
-          // an un-named groupItem, which means that the groupItem is gone (null) and
-          // there are no visible tabs. 
-          let closingUnnamedGroup = (groupItem == null &&
-              gBrowser.visibleTabs.length <= 1); 
-
-          // 3) When a blank tab is active while restoring a closed tab the
+          // 2) When a blank tab is active while restoring a closed tab the
           // blank tab gets removed. The active group is not closed as this is
           // where the restored tab goes. So do not show the TabView.
           let tabItem = tab && tab._tabViewTabItem;
           let closingBlankTabAfterRestore =
             (tabItem && tabItem.isRemovedAfterRestore);
 
-          if ((closingLastOfGroup || closingUnnamedGroup) &&
-              !closingBlankTabAfterRestore) {
+          if (closingLastOfGroup && !closingBlankTabAfterRestore) {
             // for the tab focus event to pick up.
             self._closedLastVisibleTab = true;
             self.showTabView();
           }
         }
       }
     };
 
     // TabMove
-    this._eventListeners.move = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
+    this._eventListeners.move = function (event) {
+      let tab = event.target;
 
       if (GroupItems.groupItems.length > 0) {
         if (tab.pinned) {
           if (gBrowser._numPinnedTabs > 1)
             GroupItems.arrangeAppTab(tab);
         } else {
           let activeGroupItem = GroupItems.getActiveGroupItem();
           if (activeGroupItem)
             self.setReorderTabItemsOnShow(activeGroupItem);
         }
       }
     };
 
     // TabSelect
-    this._eventListeners.select = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
-
-      self.onTabSelect(tab);
+    this._eventListeners.select = function (event) {
+      self.onTabSelect(event.target);
     };
 
     // TabPinned
-    this._eventListeners.pinned = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
+    this._eventListeners.pinned = function (event) {
+      let tab = event.target;
 
       TabItems.handleTabPin(tab);
       GroupItems.addAppTab(tab);
     };
 
     // TabUnpinned
-    this._eventListeners.unpinned = function(tab) {
-      if (tab.ownerDocument.defaultView != gWindow)
-        return;
+    this._eventListeners.unpinned = function (event) {
+      let tab = event.target;
 
       TabItems.handleTabUnpin(tab);
       GroupItems.removeAppTab(tab);
 
       let groupItem = tab._tabViewTabItem.parent;
       if (groupItem)
         self.setReorderTabItemsOnShow(groupItem);
     };
@@ -885,18 +897,24 @@ let UI = {
     this._closedLastVisibleTab = false;
     this._closedSelectedTabInTabView = false;
     this.closedLastTabInTabView = false;
     this.restoredClosedTab = false;
     this._lastOpenedTab = null;
 
     // if TabView is visible but we didn't just close the last tab or
     // selected tab, show chrome.
-    if (this.isTabViewVisible())
+    if (this.isTabViewVisible()) {
+      // Unhide the group of the tab the user is activating.
+      if (tab && tab._tabViewTabItem && tab._tabViewTabItem.parent &&
+          tab._tabViewTabItem.parent.hidden)
+        tab._tabViewTabItem.parent._unhide({immediately: true});
+
       this.hideTabView();
+    }
 
     // another tab might be selected when hideTabView() is invoked so a
     // validation is needed.
     if (this._currentTab != tab)
       return;
 
     let newItem = null;
     // update the tab bar for the new tab's group
@@ -921,16 +939,37 @@ let UI = {
       }
 
       if (GroupItems.getActiveGroupItem())
         GroupItems._updateTabBar();
     }
   },
 
   // ----------
+  // Function: _onDOMWillOpenModalDialog
+  // Called when a web page is about to show a modal dialog.
+  _onDOMWillOpenModalDialog: function UI__onDOMWillOpenModalDialog(cx) {
+    if (!this.isTabViewVisible())
+      return;
+
+    let index = gBrowser.browsers.indexOf(cx.target);
+    if (index == -1)
+      return;
+
+    let tab = gBrowser.tabs[index];
+
+    // When TabView is visible, we need to call onTabSelect to make sure that
+    // TabView is hidden and that the correct group is activated. When a modal
+    // dialog is shown for currently selected tab the onTabSelect event handler
+    // is not called, so we need to do it.
+    if (gBrowser.selectedTab == tab && this._currentTab == tab)
+      this.onTabSelect(tab);
+  },
+
+  // ----------
   // Function: setReorderTabsOnHide
   // Sets the groupItem which the tab items' tabs should be re-ordered when
   // switching to the main browser UI.
   // Parameters:
   //   groupItem - the groupItem which would be used for re-ordering tabs.
   setReorderTabsOnHide: function UI_setReorderTabsOnHide(groupItem) {
     if (this.isTabViewVisible()) {
       var index = this._reorderTabsOnHide.indexOf(groupItem);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -172,16 +172,17 @@ endif
                  browser_bug599325.js \
                  browser_bug609700.js \
                  browser_bug616836.js \
                  browser_bug623893.js \
                  browser_bug624734.js \
                  browser_bug647886.js \
                  browser_bug655584.js \
                  browser_bug664672.js \
+                 browser_canonizeURL.js \
                  browser_findbarClose.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
                  browser_disablechrome.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_canonizeURL.js
@@ -0,0 +1,54 @@
+function test() {
+  waitForExplicitFinish();
+  testNext();
+}
+
+var pairs = [
+  ["example", "http://www.example.net/"],
+  ["ex-ample", "http://www.ex-ample.net/"],
+  ["  example ", "http://www.example.net/"],
+  [" example/foo ", "http://www.example.net/foo"],
+  [" example/foo bar ", "http://www.example.net/foo%20bar"],
+  ["example.net", "http://example.net/"],
+  ["http://example", "http://example/"],
+  ["example:8080", "http://example:8080/"],
+  ["ex-ample.foo", "http://ex-ample.foo/"],
+  ["example.foo/bar ", "http://example.foo/bar"],
+  ["1.1.1.1", "http://1.1.1.1/"],
+  ["ftp://example", "ftp://example/"],
+  ["ftp.example.bar", "ftp://ftp.example.bar/"],
+  ["ex ample", Services.search.originalDefaultEngine.getSubmission("ex ample").uri.spec],
+];
+
+function testNext() {
+  if (!pairs.length) {
+    finish();
+    return;
+  }
+
+  let [inputValue, expectedURL] = pairs.shift();
+
+  gBrowser.addProgressListener({
+    onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
+      if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
+          aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
+        is(aRequest.originalURI.spec, expectedURL,
+           "entering '" + inputValue + "' loads expected URL");
+
+        gBrowser.removeProgressListener(this);
+        gBrowser.stop();
+
+        executeSoon(testNext);
+      }
+    }
+  });
+
+  gURLBar.addEventListener("focus", function onFocus() {
+    gURLBar.removeEventListener("focus", onFocus);
+    EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
+  });
+
+  gBrowser.selectedBrowser.focus();
+  gURLBar.inputField.value = inputValue;
+  gURLBar.focus();
+}
--- a/browser/base/content/test/inspector/Makefile.in
+++ b/browser/base/content/test/inspector/Makefile.in
@@ -51,12 +51,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_scrolling.js \
 		browser_inspector_store.js \
 		browser_inspector_tab_switch.js \
 		browser_inspector_treePanel_output.js \
 		browser_inspector_treePanel_input.html \
 		browser_inspector_treePanel_result.html \
 		browser_inspector_registertools.js \
 		browser_inspector_bug_665880.js \
+		browser_inspector_editor.js \
 		$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/inspector/browser_inspector_editor.js
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * 
+ * Contributor(s):
+ *   Rob Campbell <rcampbell@mozilla.com>
+ *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Kyle Simpson <ksimpson@mozilla.com> 
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let doc;
+let div;
+let editorTestSteps;
+
+function doNextStep() {
+  editorTestSteps.next();
+}
+
+function setupEditorTests()
+{
+  div = doc.createElement("div");
+  div.setAttribute("id", "foobar");
+  div.setAttribute("class", "barbaz");
+  doc.body.appendChild(div);
+  
+  Services.obs.addObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false);
+  InspectorUI.toggleInspectorUI();
+}
+
+function runEditorTests()
+{
+  Services.obs.removeObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false);
+  InspectorUI.stopInspecting();
+  
+  // setup generator for async test steps
+  editorTestSteps = doEditorTestSteps();
+  
+  // add step listeners
+  Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
+  Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
+  Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
+
+  // start the tests
+  doNextStep();
+}
+
+function doEditorTestSteps()
+{
+  let editor = InspectorUI.treeBrowserDocument.getElementById("attribute-editor");
+  let editorInput = InspectorUI.treeBrowserDocument.getElementById("attribute-editor-input");
+
+  // Step 1: grab and test the attribute-value nodes in the HTML panel, then open editor
+  let attrValNode_id = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='id']")[0];
+  let attrValNode_class = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='class']")[0];
+
+  is(attrValNode_id.innerHTML, "foobar", "Step 1: we have the correct `id` attribute-value node in the HTML panel");
+  is(attrValNode_class.innerHTML, "barbaz", "we have the correct `class` attribute-value node in the HTML panel");
+  
+  // double-click the `id` attribute-value node to open the editor
+  executeSoon(function() {
+    // firing 2 clicks right in a row to simulate a double-click
+    EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView);
+  });
+
+  yield; // End of Step 1
+
+
+  // Step 2: validate editing session, enter new attribute value into editor, and save input
+  ok(InspectorUI.editingContext, "Step 2: editor session started");
+
+  let editorVisible = editor.classList.contains("editing");
+  ok(editorVisible, "editor popup visible");
+
+  // check if the editor popup is "near" the correct position
+  let editorDims = editor.getBoundingClientRect();
+  let attrValNodeDims = attrValNode_id.getBoundingClientRect();
+  let editorPositionOK = (editorDims.left >= (attrValNodeDims.left - editorDims.width - 5)) &&
+                          (editorDims.right <= (attrValNodeDims.right + editorDims.width + 5)) &&
+                          (editorDims.top >= (attrValNodeDims.top - editorDims.height - 5)) &&
+                          (editorDims.bottom <= (attrValNodeDims.bottom + editorDims.height + 5));
+
+  ok(editorPositionOK, "editor position acceptable");
+
+  // check to make sure the attribute-value node being edited is properly highlighted
+  let attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue");
+  ok(attrValNodeHighlighted, "`id` attribute-value node is editor-highlighted");
+
+  is(InspectorUI.editingContext.repObj, div, "editor session has correct reference to div");
+  is(InspectorUI.editingContext.attrObj, attrValNode_id, "editor session has correct reference to `id` attribute-value node in HTML panel");
+  is(InspectorUI.editingContext.attrName, "id", "editor session knows correct attribute-name");
+
+  editorInput.value = "Hello World";
+  editorInput.focus();
+  
+  // hit <enter> to save the inputted value
+  executeSoon(function() {
+    EventUtils.synthesizeKey("VK_RETURN", {}, attrValNode_id.ownerDocument.defaultView);
+  });
+
+  // two `yield` statements, to trap both the "SAVED" and "CLOSED" events that will be triggered
+  yield;
+  yield; // End of Step 2
+
+
+  // Step 3: validate that the previous editing session saved correctly, then open editor on `class` attribute value
+  ok(!InspectorUI.editingContext, "Step 3: editor session ended");
+  editorVisible = editor.classList.contains("editing");
+  ok(!editorVisible, "editor popup hidden");
+  attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue");
+  ok(!attrValNodeHighlighted, "`id` attribute-value node is no longer editor-highlighted");
+  is(div.getAttribute("id"), "Hello World", "`id` attribute-value successfully updated");
+  is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel successfully updated");
+
+  // double-click the `class` attribute-value node to open the editor
+  executeSoon(function() {
+    // firing 2 clicks right in a row to simulate a double-click
+    EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {clickCount: 2}, attrValNode_class.ownerDocument.defaultView);
+  });
+
+  yield; // End of Step 3
+
+
+  // Step 4: enter value into editor, then hit <escape> to discard it
+  ok(InspectorUI.editingContext, "Step 4: editor session started");
+  editorVisible = editor.classList.contains("editing");
+  ok(editorVisible, "editor popup visible");
+  
+  is(InspectorUI.editingContext.attrObj, attrValNode_class, "editor session has correct reference to `class` attribute-value node in HTML panel");
+  is(InspectorUI.editingContext.attrName, "class", "editor session knows correct attribute-name");
+
+  editorInput.value = "Hello World";
+  editorInput.focus();
+  
+  // hit <escape> to discard the inputted value
+  executeSoon(function() {
+    EventUtils.synthesizeKey("VK_ESCAPE", {}, attrValNode_class.ownerDocument.defaultView);
+  });
+
+  yield; // End of Step 4
+
+
+  // Step 5: validate that the previous editing session discarded correctly, then open editor on `id` attribute value again
+  ok(!InspectorUI.editingContext, "Step 5: editor session ended");
+  editorVisible = editor.classList.contains("editing");
+  ok(!editorVisible, "editor popup hidden");
+  is(div.getAttribute("class"), "barbaz", "`class` attribute-value *not* updated");
+  is(attrValNode_class.innerHTML, "barbaz", "attribute-value node in HTML panel *not* updated");
+
+  // double-click the `id` attribute-value node to open the editor
+  executeSoon(function() {
+    // firing 2 clicks right in a row to simulate a double-click
+    EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView);
+  });
+
+  yield; // End of Step 5
+
+
+  // Step 6: validate that editor opened again, then test double-click inside of editor (should do nothing)
+  ok(InspectorUI.editingContext, "Step 6: editor session started");
+  editorVisible = editor.classList.contains("editing");
+  ok(editorVisible, "editor popup visible");
+  
+  // double-click on the editor input box
+  executeSoon(function() {
+    // firing 2 clicks right in a row to simulate a double-click
+    EventUtils.synthesizeMouse(editorInput, 2, 2, {clickCount: 2}, editorInput.ownerDocument.defaultView);
+    
+    // since the previous double-click is supposed to do nothing,
+    // wait a brief moment, then move on to the next step
+    executeSoon(function() {
+      doNextStep();
+    });
+  });
+
+  yield; // End of Step 6
+
+
+  // Step 7: validate that editing session is still correct, then enter a value and try a click 
+  //         outside of editor (should cancel the editing session)
+  ok(InspectorUI.editingContext, "Step 7: editor session still going");
+  editorVisible = editor.classList.contains("editing");
+  ok(editorVisible, "editor popup still visible");
+  
+  editorInput.value = "all your base are belong to us";
+
+  // single-click the `class` attribute-value node
+  executeSoon(function() {
+    EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {}, attrValNode_class.ownerDocument.defaultView);
+  });
+
+  yield; // End of Step 7
+
+
+  // Step 8: validate that the editor was closed and that the editing was not saved
+  ok(!InspectorUI.editingContext, "Step 8: editor session ended");
+  editorVisible = editor.classList.contains("editing");
+  ok(!editorVisible, "editor popup hidden");
+  is(div.getAttribute("id"), "Hello World", "`id` attribute-value *not* updated");
+  is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel *not* updated");
+  
+  // End of Step 8
+
+  // end of all steps, so clean up
+  Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
+  Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
+  Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
+
+  executeSoon(finishUp);
+}
+
+function finishUp() {
+  doc = div = null;
+  InspectorUI.closeInspectorUI();
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+function test()
+{
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    doc = content.document;
+    waitForFocus(setupEditorTests, content);
+  }, true);
+
+  content.location = "data:text/html,basic tests for html panel attribute-value editor";
+}
+
--- a/browser/base/content/test/inspector/browser_inspector_treePanel_result.html
+++ b/browser/base/content/test/inspector/browser_inspector_treePanel_result.html
@@ -1,8 +1,8 @@
-<div role="presentation" class="nodeBox htmlNodeBox containerNodeBox  repIgnore open"><div class="docType ">&lt;!DOCTYPE html&gt;</div><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">html</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">xml:lang</span>="<span class="nodeValue editable ">en</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">head</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox emptyNodeBox  repIgnore"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">meta</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">charset</span>="<span class="nodeValue editable ">utf-8</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div></div><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">title</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">Inspector tree panel test</span></span>&lt;/<span class="nodeTag ">title</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">style</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">type</span>="<span class="nodeValue editable ">text/css</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox "><span class="nodeText editable "><span class="  ">&lt;!--
+<div role="presentation" class="nodeBox htmlNodeBox containerNodeBox  repIgnore open"><div class="docType ">&lt;!DOCTYPE html&gt;</div><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">html</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">xml:lang</span>="<span data-attributename="xml:lang" class="nodeValue editable ">en</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">head</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox emptyNodeBox  repIgnore"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">meta</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">charset</span>="<span data-attributename="charset" class="nodeValue editable ">utf-8</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div></div><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">title</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">Inspector tree panel test</span></span>&lt;/<span class="nodeTag ">title</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">style</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">type</span>="<span data-attributename="type" class="nodeValue editable ">text/css</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox "><span class="nodeText editable "><span class="  ">&lt;!--
 #duplicate { color: green }
---&gt;</span></span></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">style</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">script</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">type</span>="<span class="nodeValue editable ">text/javascript</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox "><span class="nodeText editable "><span class="  ">&lt;!--
+--&gt;</span></span></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">style</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">script</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">type</span>="<span data-attributename="type" class="nodeValue editable ">text/javascript</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox "><span class="nodeText editable "><span class="  ">&lt;!--
 function fooBarBaz(arg1) {
 return true; // do nothing
 }
-// --&gt;</span></span></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">script</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">head</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">body</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">arbitrary:attribute</span>="<span class="nodeValue editable ">value</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">p</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">Inspector tree panel test.</span></span>&lt;/<span class="nodeTag ">p</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">id</span>="<span class="nodeValue editable ">foo</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">class</span>="<span class="nodeValue editable ">foo bar baz</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">style</span>="<span class="nodeValue editable ">border:1px solid red;
-unknownProperty: unknownValue; color: withUnkownValue</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">unknowntag</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">unknownattribute</span>="<span class="nodeValue editable ">fooBar</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">p</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">data-test1</span>="<span class="nodeValue editable ">value</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">unknownattribute</span>="<span class="nodeValue editable ">fooBar</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">hello world!</span></span>&lt;/<span class="nodeTag ">p</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">unknowntag</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">id</span>="<span class="nodeValue editable ">duplicate</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">class</span>="<span class="nodeValue editable ">test</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">foobar</span>="<span class="nodeValue editable ">baz</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">test</span></span>&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">iframe</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">src</span>="<span class="nodeValue editable ">data:text/html,&lt;div&gt;hello from an iframe!&lt;/div&gt;</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">html</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">head</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  "></span></span>&lt;/<span class="nodeTag ">head</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">body</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore selected"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">hello from an iframe!</span></span>&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">body</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">html</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">iframe</span>&gt;</span></div></div><div role="presentation" class="nodeBox nodeComment ">&lt;!--<span class="nodeComment editable "> hello world from a comment! </span>--&gt;</div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">body</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">html</span>&gt;</span></div></div>
+// --&gt;</span></span></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">script</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">head</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">body</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">arbitrary:attribute</span>="<span data-attributename="arbitrary:attribute" class="nodeValue editable ">value</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">p</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">Inspector tree panel test.</span></span>&lt;/<span class="nodeTag ">p</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">id</span>="<span data-attributename="id" class="nodeValue editable ">foo</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">class</span>="<span data-attributename="class" class="nodeValue editable ">foo bar baz</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">style</span>="<span data-attributename="style" class="nodeValue editable ">border:1px solid red;
+unknownProperty: unknownValue; color: withUnkownValue</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">unknowntag</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">unknownattribute</span>="<span data-attributename="unknownattribute" class="nodeValue editable ">fooBar</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">p</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">data-test1</span>="<span data-attributename="data-test1" class="nodeValue editable ">value</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">unknownattribute</span>="<span data-attributename="unknownattribute" class="nodeValue editable ">fooBar</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">hello world!</span></span>&lt;/<span class="nodeTag ">p</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">unknowntag</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">id</span>="<span data-attributename="id" class="nodeValue editable ">duplicate</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">class</span>="<span data-attributename="class" class="nodeValue editable ">test</span>"</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">foobar</span>="<span data-attributename="foobar" class="nodeValue editable ">baz</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">test</span></span>&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">iframe</span><span class="nodeAttr editGroup ">&nbsp;<span class="nodeName editable ">src</span>="<span data-attributename="src" class="nodeValue editable ">data:text/html,&lt;div&gt;hello from an iframe!&lt;/div&gt;</span>"</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">html</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore "><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">head</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  "></span></span>&lt;/<span class="nodeTag ">head</span>&gt;</span></div></div><div role="presentation" class="nodeBox containerNodeBox  repIgnore open"><div role="presentation" class="nodeLabel "><img role="presentation" class="twisty "><span role="treeitem" aria-expanded="true" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">body</span><span class="nodeBracket editable insertBefore ">&gt;</span></span></div><div role="group" class="nodeChildBox "><div role="presentation" class="nodeBox textNodeBox  repIgnore selected"><div role="presentation" class="nodeLabel "><span role="treeitem" class="nodeLabelBox repTarget ">&lt;<span class="nodeTag ">div</span><span class="nodeBracket editable insertBefore ">&gt;</span><span class="nodeText editable "><span class="  ">hello from an iframe!</span></span>&lt;/<span class="nodeTag ">div</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">body</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">html</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">iframe</span>&gt;</span></div></div><div role="presentation" class="nodeBox nodeComment ">&lt;!--<span class="nodeComment editable "> hello world from a comment! </span>--&gt;</div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">body</span>&gt;</span></div></div></div><div role="presentation" class="nodeCloseLabel "><span class="nodeCloseLabelBox repTarget ">&lt;/<span class="nodeTag ">html</span>&gt;</span></div></div>
\ No newline at end of file
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -106,16 +106,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug624727.js \
                  browser_tabview_bug624847.js \
                  browser_tabview_bug624931.js \
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625195.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_bug625424.js \
                  browser_tabview_bug626368.js \
+                 browser_tabview_bug626455.js \
                  browser_tabview_bug626525.js \
                  browser_tabview_bug626791.js \
                  browser_tabview_bug627239.js \
                  browser_tabview_bug627288.js \
                  browser_tabview_bug627736.js \
                  browser_tabview_bug628061.js \
                  browser_tabview_bug628165.js \
                  browser_tabview_bug628270.js \
@@ -134,16 +135,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug641802.js \
                  browser_tabview_bug642793.js \
                  browser_tabview_bug643392.js \
                  browser_tabview_bug644097.js \
                  browser_tabview_bug648882.js \
                  browser_tabview_bug649006.js \
                  browser_tabview_bug649307.js \
                  browser_tabview_bug649319.js \
+                 browser_tabview_bug650280.js \
                  browser_tabview_bug650573.js \
                  browser_tabview_bug651311.js \
                  browser_tabview_bug654721.js \
                  browser_tabview_bug654941.js \
                  browser_tabview_bug655269.js \
                  browser_tabview_bug656778.js \
                  browser_tabview_bug656913.js \
                  browser_tabview_bug662266.js \
--- a/browser/base/content/test/tabview/browser_tabview_alltabs.js
+++ b/browser/base/content/test/tabview/browser_tabview_alltabs.js
@@ -1,38 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-Cu.import("resource:///modules/tabview/AllTabs.jsm");
-
 function test() {
   waitForExplicitFinish();
 
+  let AllTabs;
   let newTab = gBrowser.addTab();
 
   // TabPinned
-  let pinned = function(tab) {
+  let pinned = function (event) {
+    let tab = event.target;
+
     is(tab, newTab, "The tabs are the same after the tab is pinned");
     ok(tab.pinned, "The tab gets pinned");
 
     gBrowser.unpinTab(tab);
   };
 
   // TabUnpinned
-  let unpinned = function(tab) {
+  let unpinned = function (event) {
+    let tab = event.target;
+
     AllTabs.unregister("pinned", pinned);
     AllTabs.unregister("unpinned", unpinned);
 
     is(tab, newTab, "The tabs are the same after the tab is unpinned");
     ok(!tab.pinned, "The tab gets unpinned");
 
     // clean up and finish
     gBrowser.removeTab(tab);
-    finish();
+    hideTabView(finish);
   };
 
-  AllTabs.register("pinned", pinned);
-  AllTabs.register("unpinned", unpinned);
+  showTabView(function () {
+    AllTabs = TabView.getContentWindow().AllTabs;
 
-  ok(!newTab.pinned, "The tab is not pinned");
-  gBrowser.pinTab(newTab);
+    AllTabs.register("pinned", pinned);
+    AllTabs.register("unpinned", unpinned);
+
+    ok(!newTab.pinned, "The tab is not pinned");
+    gBrowser.pinTab(newTab);
+  });
 }
 
--- a/browser/base/content/test/tabview/browser_tabview_bug597248.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug597248.js
@@ -17,17 +17,17 @@ function setupOne(win) {
   win.TabView.firstUseExperienced = true;
 
   win.gBrowser.addTab("http://mochi.test:8888/browser/browser/base/content/test/tabview/search1.html");
   win.gBrowser.addTab("http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html");
 
   afterAllTabsLoaded(function () setupTwo(win), win);
 }
 
-let restoreWin;
+let restoredWin;
 
 function setupTwo(win) {
   let contentWindow = win.TabView.getContentWindow();
 
   let tabItems = contentWindow.TabItems.getItems();
   is(tabItems.length, 3, "There should be 3 tab items before closing");
 
   let numTabsToSave = tabItems.length;
--- a/browser/base/content/test/tabview/browser_tabview_bug597980.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug597980.js
@@ -5,17 +5,17 @@ function test() {
   waitForExplicitFinish();
 
   newWindowWithTabView(part1);
 }
 
 function part1(win) {
   registerCleanupFunction(function() win.close());
 
-  let contentWindow = win.document.getElementById("tab-view").contentWindow;
+  let contentWindow = win.TabView.getContentWindow();
   is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
 
   let originalTab = win.gBrowser.selectedTab;
   let originalGroup = contentWindow.GroupItems.groupItems[0];
   let newTab = win.gBrowser.loadOneTab("about:blank", {inBackground: true});
   
   is(originalGroup.getChildren().length, 2, "The original group now has two tabs");
   
@@ -66,20 +66,17 @@ function part2(win) {
   let newTab = win.gBrowser.loadOneTab("about:blank", {inBackground: true});
   hideTabView(function() {
     let selectedTab = win.gBrowser.selectedTab;
     isnot(selectedTab, newTab, "They are different tabs");
 
     // switch the selected tab to new tab
     win.gBrowser.selectedTab = newTab;
 
-    whenTabViewIsHidden(function () {
-      is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
-       win.close();
-       finish();
-    });
-
-    // show tabview
-    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
-    // hide tabview
-    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
-  })
+    showTabView(function () {
+      hideTabView(function () {
+        is(win.gBrowser.selectedTab, newTab,
+           "The selected tab should be the same as before (new tab)");
+        waitForFocus(finish);
+      }, win);
+    }, win);
+  }, win);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug599626.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug599626.js
@@ -16,19 +16,17 @@ function onTabViewShown() {
 
   afterAllTabsLoaded(function () {
     testStayOnPage(contentWindow, groupItemOne, groupItemTwo);
   });
 }
 
 function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
   whenDialogOpened(function (dialog) {
-    groupItemTwo.addSubscriber("groupShown", function onShown() {
-      groupItemTwo.removeSubscriber("groupShown", onShown);
-
+    executeSoon(function () {
       is(gBrowser.tabs.length, 2, 
          "The total number of tab is 2 when staying on the page");
       is(contentWindow.TabItems.getItems().length, 2, 
          "The total number of tab items is 2 when staying on the page");
 
       showTabView(function () {
         // start the next test
         testLeavePage(contentWindow, groupItemOne, groupItemTwo);
--- a/browser/base/content/test/tabview/browser_tabview_bug604098.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug604098.js
@@ -20,16 +20,17 @@ function test() {
   });
 }
 
 function test1() {
   let groupItems = contentWindow.GroupItems.groupItems;
   is(groupItems.length, 1, "there is one groupItem");
 
   whenTabViewIsHidden(function() {
+    gBrowser.selectedTab = gBrowser.tabs[0];
     is(groupItems.length, 2, "there are two groupItems");
     closeGroupItem(groupItems[1], finish);
   });
 
   // first click
   mouseClick(contentElement, 0);
   // second click
   mouseClick(contentElement, 0);
--- a/browser/base/content/test/tabview/browser_tabview_bug624953.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624953.js
@@ -13,11 +13,11 @@ function test() {
 
     groupItem.setSize(100, 100, true);
     groupItem.setUserSize();
     ok(!groupItem.isStacked(), 'groupItem is still not stacked');
 
     cw.GroupItems.resumeArrange();
     ok(groupItem.isStacked(), 'groupItem is now stacked');
 
-    closeGroupItem(groupItem, finish);
+    closeGroupItem(groupItem, function () hideTabView(finish));
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug625195.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug625195.js
@@ -29,17 +29,17 @@ function test() {
 
     whenTabViewIsHidden(function() {
       popup(gBrowser.tabs[0]);
 
       ok(!document.getElementById("context_closeTab").disabled, "The 'Close tab' menu item is enabled");
       ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
 
       let newTabTwo = gBrowser.selectedTab;
-      gBrowser.selected = originalTab;
+      gBrowser.selectedTab = originalTab;
 
       gBrowser.removeTab(newTabOne);
       gBrowser.removeTab(newTabTwo);
 
       finish();
     });
     let newGroup = contentWindow.GroupItems.newGroup();
     newGroup.newTab();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug626455.js
@@ -0,0 +1,127 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Raymond Lee <raymond@appcoast.com>
+ */
+
+const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
+                 'function(e){e.returnValue="?"}</script><body ' +
+                 'onunload="alert(\'onunload\')" onpagehide="' +
+                 'alert(\'onpagehide\')"></body>';
+
+let contentWindow;
+let activeGroup;
+
+function test() {
+  waitForExplicitFinish();
+
+  showTabView(function () {
+    contentWindow = TabView.getContentWindow();
+    activeGroup = contentWindow.GroupItems.getActiveGroupItem();
+
+    gBrowser.browsers[0].contentWindow.location =
+      "data:text/html,<p>test for bug 626455, tab1";
+    gBrowser.addTab(TEST_URL);
+
+    afterAllTabsLoaded(testStayOnPage);
+  });
+}
+
+function testStayOnPage() {
+  whenDialogOpened(function (dialog) {
+    // stay on page
+    dialog.cancelDialog();
+
+    executeSoon(function () {
+      showTabView(function () {
+        is(gBrowser.tabs.length, 1,
+           "The total number of tab is 1 when staying on the page");
+
+        let location = gBrowser.browsers[0].contentWindow.location.toString();
+        isnot(location.indexOf("onbeforeunload"), -1,
+              "The open tab is the expected one");
+
+        is(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
+           "Active group is still the same");
+
+        is(contentWindow.GroupItems.groupItems.length, 1,
+           "Only one group is open");
+
+        // start the next test
+        testLeavePage();
+      });
+    });
+  });
+
+  closeGroupItem(activeGroup);
+}
+
+function testLeavePage() {
+  let dialogsAccepted = 0;
+
+  whenDialogOpened(function onDialogOpened(dialog) {
+    if (++dialogsAccepted < 3)
+      whenDialogOpened(onDialogOpened);
+
+    // Leave page
+    dialog.acceptDialog();
+  });
+
+  whenGroupClosed(activeGroup, finishTest);
+  closeGroupItem(activeGroup);
+}
+
+function finishTest() {
+  is(gBrowser.tabs.length, 1,
+     "The total number of tab is 1 after leaving the page");
+  is(contentWindow.TabItems.getItems().length, 1,
+     "The total number of tab items is 1 after leaving the page");
+
+  let location = gBrowser.browsers[0].contentWindow.location.toString();
+  is(location, "about:blank", "The open tab is the expected one");
+
+  isnot(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
+     "Active group is no longer the same");
+
+  is(contentWindow.GroupItems.groupItems.length, 1,
+     "Only one group is open");
+
+  finish();
+}
+
+// ----------
+function whenGroupClosed(group, callback) {
+  group.addSubscriber("close", function onClose() {
+    group.removeSubscriber("close", onClose);
+    callback();
+  });
+}
+
+// ----------
+function whenDialogOpened(callback) {
+  let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
+           .getService(Ci.nsIWindowMediator);
+
+  let listener = {
+    onCloseWindow: function () {},
+    onWindowTitleChange: function () {},
+
+    onOpenWindow: function (xulWin) {
+      let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
+                   .getInterface(Ci.nsIDOMWindow);
+
+      whenWindowLoaded(domWin, function () {
+        let dialog = domWin.document.querySelector("dialog");
+        if (dialog) {
+          wm.removeListener(listener);
+          callback(dialog);
+        }
+      });
+    }
+  };
+
+  wm.addListener(listener);
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug642793.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug642793.js
@@ -10,17 +10,17 @@ function loadTabs (win) {
   for (let i = 0; i < 4; i++)
     win.gBrowser.loadOneTab('about:blank', {inBackground: false});
   win.gBrowser.selectedTab = win.gBrowser.tabs[2];
 }
 
 function testTopOfStack(win) {
   registerCleanupFunction(function () { win.close(); });
   let cw = win.TabView.getContentWindow();
-  groupItem = cw.GroupItems.getActiveGroupItem();
+  let groupItem = cw.GroupItems.getActiveGroupItem();
   ok(!groupItem.isStacked(), 'groupItem is not stacked');
   groupItem.setSize(150, 150);
   groupItem.setUserSize();
   ok(groupItem.isStacked(), 'groupItem is now stacked');
   ok(groupItem.isTopOfStack(groupItem.getChild(2)),
     'the third tab is on top of stack');
   finish();
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug650280.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let pb = Cc["@mozilla.org/privatebrowsing;1"].
+         getService(Ci.nsIPrivateBrowsingService);
+
+function test() {
+  let cw;
+
+  registerCleanupFunction(function() {
+    if (cw)
+      cw.hideSearch();
+
+    TabView.hide();
+    pb.privateBrowsingEnabled = false;
+  });
+
+  let enableSearch = function (callback) {
+    if (cw.isSearchEnabled()) {
+      callback();
+      return;
+    }
+
+    cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
+      cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
+      executeSoon(callback);
+    }, false);
+
+    cw.ensureSearchShown();
+  };
+
+  let getSearchboxValue = function () {
+    return cw.iQ("#searchbox").val();
+  };
+
+  let prepareSearchbox = function (callback) {
+    ok(!cw.isSearchEnabled(), "search is disabled");
+
+    enableSearch(function () {
+      cw.iQ("#searchbox").val("moz");
+      callback();
+    });
+  };
+
+  let searchAndSwitchPBMode = function (callback) {
+    prepareSearchbox(function () {
+      togglePrivateBrowsing(function () {
+        showTabView(function () {
+          ok(!cw.isSearchEnabled(), "search is disabled");
+          is(getSearchboxValue(), "", "search box is empty");
+          callback();
+        });
+      });
+    });
+  };
+
+  waitForExplicitFinish();
+
+  showTabView(function () {
+    cw = TabView.getContentWindow();
+    searchAndSwitchPBMode(function () {
+      searchAndSwitchPBMode(function () {
+        hideTabView(finish);
+      });
+    });
+  });
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug663421.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug663421.js
@@ -62,17 +62,17 @@ function test() {
     let target = tab._tabViewTabItem.container;
 
     waitForFocus(function () {
       EventUtils.synthesizeMouseAtCenter(target, {type: "mousedown"}, cw);
       EventUtils.synthesizeMouse(target, 600, 5, {type: "mousemove"}, cw);
       EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
 
       checkNumberOfGroupItems(2);
-      next();
+      closeGroupItem(cw.GroupItems.groupItems[1], next);
     }, win);
   }
 
   let tests = [test1, test2, test3, test4];
 
   waitForExplicitFinish();
 
   newWindowWithTabView(function (aWin) {
--- a/browser/base/content/test/tabview/browser_tabview_dragdrop.js
+++ b/browser/base/content/test/tabview/browser_tabview_dragdrop.js
@@ -1,56 +1,39 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
-
-  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
-  TabView.toggle();
+  showTabView(onTabViewShown);
 }
 
-function onTabViewWindowLoaded() {
-  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
-
+function onTabViewShown() {
   ok(TabView.isVisible(), "Tab View is visible");
 
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+  let contentWindow = TabView.getContentWindow();
   let [originalTab] = gBrowser.visibleTabs;
 
+  let createGroupItem = function (left, top, width, height) {
+    let box = new contentWindow.Rect(left, top, width, height);
+    let groupItem = new contentWindow.GroupItem([], {bounds: box, immediately: true});
+
+    contentWindow.UI.setActive(groupItem);
+    gBrowser.loadOneTab("about:blank", {inBackground: true});
+
+    return groupItem;
+  };
+
   // create group one and two
-  let boxOne = new contentWindow.Rect(20, 20, 300, 300);
-  let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
-  ok(groupOne.isEmpty(), "This group is empty");
-
-  let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
-  let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
-
-  groupOne.addSubscriber("childAdded", function onChildAdded() {
-    groupOne.removeSubscriber("childAdded", onChildAdded);
-    groupTwo.newTab();
-  });
+  let groupOne = createGroupItem(20, 20, 300, 300);
+  let groupTwo = createGroupItem(20, 400, 300, 300);
 
-  let count = 0;
-  let onTabViewShown = function() {
-    if (count == 2) {
-      window.removeEventListener("tabviewshown", onTabViewShown, false);
-      addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
-    }
-  };
-  let onTabViewHidden = function() {
-    TabView.toggle();
-    if (++count == 2)
-      window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-  };
-  window.addEventListener("tabviewshown", onTabViewShown, false);
-  window.addEventListener("tabviewhidden", onTabViewHidden, false);
-
-  // open tab in group
-  groupOne.newTab();
+  waitForFocus(function () {
+    addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
+  });
 }
 
 function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
   let groupOne = contentWindow.GroupItems.groupItem(groupOneId);
   let groupTwo = contentWindow.GroupItems.groupItem(groupTwoId);
   let groupOneTabItemCount = groupOne.getChildren().length;
   let groupTwoTabItemCount = groupTwo.getChildren().length;
   is(groupOneTabItemCount, 1, "GroupItem one has one tab");
@@ -69,34 +52,23 @@ function addTest(contentWindow, groupOne
 
   function endGame() {
     groupTwo.removeSubscriber("childAdded", endGame);
 
     is(groupOne.getChildren().length, --groupOneTabItemCount,
        "The number of children in group one is decreased by 1");
     is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
        "The number of children in group two is increased by 1");
-  
-    let onTabViewHidden = function() {
-      window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-      groupTwo.closeAll();
-      // close undo group
-      let closeButton = groupTwo.$undoContainer.find(".close");
-      EventUtils.sendMouseEvent(
-        { type: "click" }, closeButton[0], contentWindow);
-    };
-    groupTwo.addSubscriber("close", function onClose() {
-      groupTwo.removeSubscriber("close", onClose);
-      finish(); 
+
+    closeGroupItem(groupOne, function () {
+      closeGroupItem(groupTwo, function () hideTabView(finish));
     });
-    window.addEventListener("tabviewhidden", onTabViewHidden, false);
-    gBrowser.selectedTab = originalTab;
   }
+
   groupTwo.addSubscriber("childAdded", endGame);
-  
   simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
 }
 
 function simulateDragDrop(element, offsetX, offsetY, contentWindow) {
   let rect = element.getBoundingClientRect();
   let startX = (rect.right - rect.left)/2;
   let startY = (rect.bottom - rect.top)/2;
   let incrementX = offsetX / 2;
--- a/browser/base/content/test/tabview/browser_tabview_launch.js
+++ b/browser/base/content/test/tabview/browser_tabview_launch.js
@@ -1,52 +1,54 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let timerId;
 let newWin;
 
 // ----------
 function test() {
   waitForExplicitFinish();
 
-  // launch tab view for the first time
-  newWindowWithTabView(function() {}, function(win) {
+  let panelSelected = false;
+  registerCleanupFunction(function () ok(panelSelected, "panel is selected"));
+
+  let onLoad = function (win) {
+    registerCleanupFunction(function () win.close());
+
     newWin = win;
 
     let onSelect = function(event) {
       if (deck != event.target)
         return;
 
       let iframe = win.document.getElementById("tab-view");
       if (deck.selectedPanel != iframe)
         return;
 
       deck.removeEventListener("select", onSelect, true);
-
-      whenTabViewIsShown(function() {
-        executeSoon(function() {
-          testMethodToHideAndShowTabView(function() {
-            newWin.document.getElementById("menu_tabview").doCommand();
-          }, function() {
-            testMethodToHideAndShowTabView(function() {
-              EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
-            }, finish);
-          });
-        });
-      }, win);
+      panelSelected = true;
     };
 
     let deck = win.document.getElementById("tab-view-deck");
     deck.addEventListener("select", onSelect, true);
-  });
+  };
 
-  registerCleanupFunction(function () {
-    newWin.close();
-  });
+  let onShow = function (win) {
+    executeSoon(function() {
+      testMethodToHideAndShowTabView(function() {
+        newWin.document.getElementById("menu_tabview").doCommand();
+      }, function() {
+        testMethodToHideAndShowTabView(function() {
+          EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
+        }, finish);
+      });
+    });
+  };
+
+  newWindowWithTabView(onShow, onLoad);
 }
 
 function testMethodToHideAndShowTabView(executeFunc, callback) {
   whenTabViewIsHidden(function() {
     ok(!newWin.TabView.isVisible(), "Tab View is not visible after executing the function");
     whenTabViewIsShown(function() {
       ok(newWin.TabView.isVisible(), "Tab View is visible after executing the function again");
       callback();
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -44,19 +44,20 @@ function executeCopyCommand(command, exp
   // The easiest way to check the clipboard is to paste the contents into a
   // textbox
   input.focus();
   input.value = "";
   input.controllers.getControllerForCommand("cmd_paste").doCommand("cmd_paste");
   is(input.value, expectedValue, "paste for command " + command);
 }
 
-function invokeItemAction(ident)
+function invokeItemAction(generatedItemId)
 {
-  var item = contextMenu.getElementsByAttribute("ident", ident)[0];
+  var item = contextMenu.getElementsByAttribute("generateditemid",
+                                                generatedItemId)[0];
   ok(item, "Got generated XUL menu item");
   item.doCommand();
   is(pagemenu.hasAttribute("hopeless"), false, "attribute got removed");
 }
 
 function getVisibleMenuItems(aMenu, aData) {
     var items = [];
     var accessKeys = {};
@@ -64,17 +65,17 @@ function getVisibleMenuItems(aMenu, aDat
         var item = aMenu.childNodes[i];
         if (item.hidden)
             continue;
 
         var key = item.accessKey;
         if (key)
             key = key.toLowerCase();
 
-        var isGenerated = item.hasAttribute("generated");
+        var isGenerated = item.hasAttribute("generateditemid");
 
         if (item.nodeName == "menuitem") {
             var isSpellSuggestion = item.className == "spell-suggestion";
             if (isSpellSuggestion) {
               is(item.id, "", "child menuitem #" + i + " is a spelling suggestion");
             } else if (isGenerated) {
               is(item.id, "", "child menuitem #" + i + " is a generated item");
             } else {
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -362,17 +362,17 @@
         <parameter name="aTriggeringEvent"/>
         <body><![CDATA[
           var url = this.value;
           if (!url)
             return ["", null, false];
 
           // Only add the suffix when the URL bar value isn't already "URL-like",
           // and only if we get a keyboard event, to match user expectations.
-          if (!/^\s*(www|https?)\b|\/\s*$/i.test(url) &&
+          if (/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(url) &&
               (aTriggeringEvent instanceof KeyEvent)) {
 #ifdef XP_MACOSX
             let accel = aTriggeringEvent.metaKey;
 #else
             let accel = aTriggeringEvent.ctrlKey;
 #endif
             let shift = aTriggeringEvent.shiftKey;
 
@@ -397,34 +397,25 @@
             }
 
             if (suffix) {
               // trim leading/trailing spaces (bug 233205)
               url = url.trim();
 
               // Tack www. and suffix on.  If user has appended directories, insert
               // suffix before them (bug 279035).  Be careful not to get two slashes.
-              // Also, don't add the suffix if it's in the original url (bug 233853).
 
               let firstSlash = url.indexOf("/");
-              let existingSuffix = url.indexOf(suffix.substring(0, suffix.length - 1));
-
-              // * Logic for slash and existing suffix (example)
-              // No slash, no suffix: Add suffix (mozilla)
-              // No slash, yes suffix: Add slash (mozilla.com)
-              // Yes slash, no suffix: Insert suffix (mozilla/stuff)
-              // Yes slash, suffix before slash: Do nothing (mozilla.com/stuff)
-              // Yes slash, suffix after slash: Insert suffix (mozilla/?stuff=.com)
 
               if (firstSlash >= 0) {
-                if (existingSuffix == -1 || existingSuffix > firstSlash)
-                  url = url.substring(0, firstSlash) + suffix +
-                        url.substring(firstSlash + 1);
-              } else
-                url = url + (existingSuffix == -1 ? suffix : "/");
+                url = url.substring(0, firstSlash) + suffix +
+                      url.substring(firstSlash + 1);
+              } else {
+                url = url + suffix;
+              }
 
               url = "http://www." + url;
             }
           }
 
           var postData = {};
           var mayInheritPrincipal = { value: false };
           url = getShortcutOrURI(url, postData, mayInheritPrincipal);
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -48,16 +48,17 @@ browser.jar:
 *       content/browser/sanitize.xul                  (content/sanitize.xul)
 *       content/browser/sanitizeDialog.js             (content/sanitizeDialog.js)
         content/browser/sanitizeDialog.css            (content/sanitizeDialog.css)
 *       content/browser/tabbrowser.css                (content/tabbrowser.css)
 *       content/browser/tabbrowser.xml                (content/tabbrowser.xml)
         content/browser/tabview.css                   (content/tabview/tabview.css)
 *       content/browser/tabview.js                    (content/tabview/tabview.js)
         content/browser/tabview.html                  (content/tabview/tabview.html)
+        content/browser/tabview-content.js            (content/tabview/content.js)
 *       content/browser/urlbarBindings.xml            (content/urlbarBindings.xml)
 *       content/browser/utilityOverlay.js             (content/utilityOverlay.js)
 *       content/browser/web-panels.js                 (content/web-panels.js)
 *       content/browser/web-panels.xul                (content/web-panels.xul)
 *       content/browser/baseMenuOverlay.xul           (content/baseMenuOverlay.xul)
 *       content/browser/nsContextMenu.js              (content/nsContextMenu.js)
 #ifdef MOZ_SERVICES_SYNC
 *       content/browser/aboutSyncTabs.xul             (content/aboutSyncTabs.xul)
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -48,17 +48,16 @@
 #elif defined(MOZ_WIDGET_GTK2)
 #include "nsGNOMEShellService.h"
 #endif
 
 #include "nsProfileMigrator.h"
 #if !defined(XP_OS2)
 #include "nsOperaProfileMigrator.h"
 #endif
-#include "nsSeamonkeyProfileMigrator.h"
 #if defined(XP_WIN) && !defined(__MINGW32__)
 #include "nsIEProfileMigrator.h"
 #elif defined(XP_MACOSX)
 #include "nsSafariProfileMigrator.h"
 #endif
 
 #include "rdf.h"
 #include "nsFeedSniffer.h"
@@ -80,17 +79,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShel
 #elif defined(MOZ_WIDGET_GTK2)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
 #endif
 
 #if !defined(XP_OS2)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsOperaProfileMigrator)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileMigrator)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsSeamonkeyProfileMigrator)
 #if defined(XP_WIN) && !defined(__MINGW32__)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
 
@@ -109,17 +107,16 @@ NS_DEFINE_NAMED_CID(NS_FIREFOX_PROFILEMI
 NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID);
 #elif defined(XP_MACOSX)
 NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID);
 #endif
 #if !defined(XP_OS2)
 NS_DEFINE_NAMED_CID(NS_OPERAPROFILEMIGRATOR_CID);
 #endif
-NS_DEFINE_NAMED_CID(NS_SEAMONKEYPROFILEMIGRATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
 
 static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
     { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor },
 #if defined(XP_WIN)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor },
 #elif defined(MOZ_WIDGET_GTK2)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor },
@@ -131,17 +128,16 @@ static const mozilla::Module::CIDEntry k
     { &kNS_WINIEPROFILEMIGRATOR_CID, false, NULL, nsIEProfileMigratorConstructor },
 #elif defined(XP_MACOSX)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
     { &kNS_SAFARIPROFILEMIGRATOR_CID, false, NULL, nsSafariProfileMigratorConstructor },
 #endif
 #if !defined(XP_OS2)
     { &kNS_OPERAPROFILEMIGRATOR_CID, false, NULL, nsOperaProfileMigratorConstructor },
 #endif
-    { &kNS_SEAMONKEYPROFILEMIGRATOR_CID, false, NULL, nsSeamonkeyProfileMigratorConstructor },
     { &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
     { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
     { NS_BROWSERDIRECTORYPROVIDER_CONTRACTID, &kNS_BROWSERDIRECTORYPROVIDER_CID },
 #if defined(XP_WIN)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
@@ -168,17 +164,16 @@ static const mozilla::Module::ContractID
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "safari", &kNS_SAFARIPROFILEMIGRATOR_CID },
 #endif
 #if !defined(XP_OS2)
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "opera", &kNS_OPERAPROFILEMIGRATOR_CID },
 #endif
-    { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey", &kNS_SEAMONKEYPROFILEMIGRATOR_CID },
     { NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
     { NULL }
 };
 
 static const mozilla::Module::CategoryEntry kBrowserCategories[] = {
     { XPCOM_DIRECTORY_PROVIDER_CATEGORY, "browser-directory-provider", NS_BROWSERDIRECTORYPROVIDER_CONTRACTID },
     { NS_CONTENT_SNIFFER_CATEGORY, "Feed Sniffer", NS_FEEDSNIFFER_CONTRACTID },
     { NULL }
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -251,17 +251,18 @@ FeedWriter.prototype = {
 
   /**
    * Use this sandbox to run any dom manipulation code on nodes which
    * are already inserted into the content document.
    */
   __contentSandbox: null,
   get _contentSandbox() {
     if (!this.__contentSandbox)
-      this.__contentSandbox = new Cu.Sandbox(this._window);
+      this.__contentSandbox = new Cu.Sandbox(this._window, 
+                                             {sandboxName: 'FeedWriter'});
 
     return this.__contentSandbox;
   },
 
   /**
    * Calls doCommand for a given XUL element within the context of the
    * content document.
    *
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -335,19 +335,16 @@ var MigrationWizard = {
         source = "sourceNameIE";
         break;
       case "opera":
         source = "sourceNameOpera";
         break;
       case "safari":
         source = "sourceNameSafari";
         break;
-      case "seamonkey":
-        source = "sourceNameSeamonkey";
-        break;
     }
 
     // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
     this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
 
     var oldHomePageURL = this._migrator.sourceHomePageURL;
 
     if (oldHomePageURL && source) {
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -65,29 +65,24 @@
     <description id="importBookmarks" control="importSourceGroup" hidden="true">&importFromBookmarks.label;</description>
 
     <radiogroup id="importSourceGroup" align="start">
       <!-- If you are adding a migrator, please add the appropriate
            hooks to GetDefaultBrowserMigratorKey in
            browser/components/migration/src/nsProfileMigrator.cpp -->
 #ifdef XP_MACOSX
       <radio id="safari"    label="&importFromSafari.label;"    accesskey="&importFromSafari.accesskey;"/>
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #elifdef XP_UNIX
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #elifdef XP_WIN
 #ifndef NO_IE_MIGRATOR
       <radio id="ie"        label="&importFromIE.label;"        accesskey="&importFromIE.accesskey;"/>
 #endif
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
-#else
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
 #endif
       <radio id="fromfile"  label="&importFromHTMLFile.label;"  accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
       <radio id="nothing"   label="&importFromNothing.label;"   accesskey="&importFromNothing.accesskey;" hidden="true"/>
     </radiogroup>
     <label id="noSources" hidden="true">&noMigrationSources.label;</label>
   </wizardpage>
 
   <wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -47,18 +47,16 @@ FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
 ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
 endif
 
 
 CPPSRCS  = nsProfileMigrator.cpp \
            nsBrowserProfileMigratorUtils.cpp \
-           nsNetscapeProfileMigratorBase.cpp \
-           nsSeamonkeyProfileMigrator.cpp \
            $(NULL)
 
 ifneq ($(OS_ARCH),OS2)
 CPPSRCS += nsOperaProfileMigrator.cpp
 endif
 
 ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
 CPPSRCS += nsIEProfileMigrator.cpp \
deleted file mode 100644
--- a/browser/components/migration/src/nsNetscapeProfileMigratorBase.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsBrowserProfileMigratorUtils.h"
-#include "nsICookieManager2.h"
-#include "nsIFile.h"
-#include "nsILineInputStream.h"
-#include "nsIOutputStream.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefLocalizedString.h"
-#include "nsIPrefService.h"
-#include "NSReg.h"
-#include "nsIServiceManager.h"
-#include "nsISupportsPrimitives.h"
-#include "nsIURL.h"
-#include "nsNetscapeProfileMigratorBase.h"
-#include "nsNetUtil.h"
-#include "prtime.h"
-#include "prprf.h"
-
-#ifdef XP_MACOSX
-#define NEED_TO_FIX_4X_COOKIES 1
-#define SECONDS_BETWEEN_1900_AND_1970 2208988800UL
-#endif /* XP_MACOSX */
-
-#define FILE_NAME_PREFS_5X NS_LITERAL_STRING("prefs.js")
-
-///////////////////////////////////////////////////////////////////////////////
-// nsNetscapeProfileMigratorBase
-nsNetscapeProfileMigratorBase::nsNetscapeProfileMigratorBase()
-{
-}
-
-static nsresult
-regerr2nsresult(REGERR errCode)
-{
-  switch (errCode) {
-    case REGERR_PARAM:
-    case REGERR_BADTYPE:
-    case REGERR_BADNAME:
-      return NS_ERROR_INVALID_ARG;
-
-    case REGERR_MEMORY:
-      return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_ERROR_FAILURE;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
-                                                          nsISupportsArray* aProfileNames,
-                                                          nsISupportsArray* aProfileLocations)
-{
-  nsresult rv;
-  REGERR errCode;
-
-  // Ensure aRegistryFile exists before open it
-  PRBool regFileExists = PR_FALSE;
-  rv = aRegistryFile->Exists(&regFileExists);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!regFileExists)
-    return NS_ERROR_FILE_NOT_FOUND;
-
-  // Open It
-  nsCAutoString regPath;
-  rv = aRegistryFile->GetNativePath(regPath);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if ((errCode = NR_StartupRegistry()))
-    return regerr2nsresult(errCode);
-
-  HREG reg;
-  if ((errCode = NR_RegOpen(regPath.get(), &reg))) {
-    NR_ShutdownRegistry();
-
-    return regerr2nsresult(errCode);
-  }
-
-  RKEY profilesTree;
-  if ((errCode = NR_RegGetKey(reg, ROOTKEY_COMMON, "Profiles", &profilesTree))) {
-    NR_RegClose(reg);
-    NR_ShutdownRegistry();
-
-    return regerr2nsresult(errCode);
-  }
-
-  char profileStr[MAXREGPATHLEN];
-  REGENUM enumState = nsnull;
-
-  while (!NR_RegEnumSubkeys(reg, profilesTree, &enumState, profileStr,
-                            sizeof(profileStr), REGENUM_CHILDREN))
-  {
-    RKEY profileKey;
-    if (NR_RegGetKey(reg, profilesTree, profileStr, &profileKey))
-      continue;
-
-    // "migrated" is "yes" for all valid Seamonkey profiles. It is only "no"
-    // for 4.x profiles. 
-    char migratedStr[3];
-    errCode = NR_RegGetEntryString(reg, profileKey, (char *)"migrated",
-                                   migratedStr, sizeof(migratedStr));
-    if ((errCode != REGERR_OK && errCode != REGERR_BUFTOOSMALL) ||
-        strcmp(migratedStr, "no") == 0)
-      continue;
-
-    // Get the profile location and add it to the locations array
-    REGINFO regInfo;
-    regInfo.size = sizeof(REGINFO);
-
-    if (NR_RegGetEntryInfo(reg, profileKey, (char *)"directory", &regInfo))
-      continue;
-
-    nsCAutoString dirStr;
-    dirStr.SetLength(regInfo.entryLength);
-
-    errCode = NR_RegGetEntryString(reg, profileKey, (char *)"directory",
-                                   dirStr.BeginWriting(), regInfo.entryLength);
-    // Remove trailing \0
-    dirStr.SetLength(regInfo.entryLength-1);
-
-    nsCOMPtr<nsILocalFile> dir;
-#ifdef XP_MACOSX
-    rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(dir));
-    if (NS_FAILED(rv)) break;
-    dir->SetPersistentDescriptor(dirStr);
-#else
-    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirStr), PR_TRUE,
-                         getter_AddRefs(dir));
-    if (NS_FAILED(rv)) break;
-#endif
-
-    PRBool exists;
-    dir->Exists(&exists);
-
-    if (exists) {
-      aProfileLocations->AppendElement(dir);
-
-      // Get the profile name and add it to the names array
-      nsString profileName;
-      CopyUTF8toUTF16(nsDependentCString(profileStr), profileName);
-
-      nsCOMPtr<nsISupportsString> profileNameString(
-        do_CreateInstance("@mozilla.org/supports-string;1"));
-
-      profileNameString->SetData(profileName);
-      aProfileNames->AppendElement(profileNameString);
-    }
-  }
-  NR_RegClose(reg);
-  NR_ShutdownRegistry();
-
-  return rv;
-}
-
-#define GETPREF(xform, method, value) \
-  nsresult rv = aBranch->method(xform->sourcePrefName, value); \
-  if (NS_SUCCEEDED(rv)) \
-    xform->prefHasValue = PR_TRUE; \
-  return rv;
-
-#define SETPREF(xform, method, value) \
-  if (xform->prefHasValue) { \
-    return aBranch->method(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, value); \
-  } \
-  return NS_OK;
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetCharPref, &xform->stringValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetCharPref, xform->stringValue);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetWString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsCOMPtr<nsIPrefLocalizedString> prefValue;
-  nsresult rv = aBranch->GetComplexValue(xform->sourcePrefName, 
-                                         NS_GET_IID(nsIPrefLocalizedString),
-                                         getter_AddRefs(prefValue));
-
-  if (NS_SUCCEEDED(rv) && prefValue) {
-    nsString data;
-    prefValue->ToString(getter_Copies(data));
-
-    xform->stringValue = ToNewCString(NS_ConvertUTF16toUTF8(data));
-    xform->prefHasValue = PR_TRUE;
-  }
-  return rv;
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  if (xform->prefHasValue) {
-    nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-    NS_ConvertUTF8toUTF16 data(xform->stringValue);
-    pls->SetData(data.get());
-    return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::SetWString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  if (xform->prefHasValue) {
-    nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-    nsAutoString data = NS_ConvertUTF8toUTF16(xform->stringValue);
-    pls->SetData(data.get());
-    return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
-  }
-  return NS_OK;
-}
-
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetBool(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetBoolPref, &xform->boolValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetBool(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetBoolPref, xform->boolValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetInt(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetIntPref, &xform->intValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetInt(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetIntPref, xform->intValue);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName)
-{
-  nsCOMPtr<nsIFile> sourceFile;
-  mSourceProfile->Clone(getter_AddRefs(sourceFile));
-
-  sourceFile->Append(aSourceFileName);
-  PRBool exists = PR_FALSE;
-  sourceFile->Exists(&exists);
-  if (!exists)
-    return NS_OK;
-
-  nsCOMPtr<nsIFile> targetFile;
-  mTargetProfile->Clone(getter_AddRefs(targetFile));
-  
-  targetFile->Append(aTargetFileName);
-  targetFile->Exists(&exists);
-  if (exists)
-    targetFile->Remove(PR_FALSE);
-
-  return sourceFile->CopyTo(mTargetProfile, aTargetFileName);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
-                                                       const PRUnichar* aImportSourceNameKey)
-{
-  nsCOMPtr<nsIFile> bookmarksFile;
-  mSourceProfile->Clone(getter_AddRefs(bookmarksFile));
-  bookmarksFile->Append(aBookmarksFileName);
-  
-  return ImportBookmarksHTML(bookmarksFile, PR_FALSE, PR_FALSE, aImportSourceNameKey);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::ImportNetscapeCookies(nsIFile* aCookiesFile)
-{
-  nsresult rv;
-  nsCOMPtr<nsIInputStream> cookiesStream;
-  rv = NS_NewLocalFileInputStream(getter_AddRefs(cookiesStream), aCookiesFile);
-  if (NS_FAILED(rv)) return rv;
-
-  nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(cookiesStream));
-
-  // This code is copied from mozilla/netwerk/cookie/src/nsCookieManager.cpp
-  static NS_NAMED_LITERAL_CSTRING(kTrue, "TRUE");
-
-  nsCAutoString buffer;
-  PRBool isMore = PR_TRUE;
-  PRInt32 hostIndex = 0, isDomainIndex, pathIndex, secureIndex, expiresIndex, nameIndex, cookieIndex;
-  PRInt32 numInts;
-  PRInt64 expires;
-  PRBool isDomain;
-  PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
-
-  nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv));
-  if (NS_FAILED(rv)) return rv;
-
-  /* file format is:
-   *
-   * host \t isDomain \t path \t secure \t expires \t name \t cookie
-   *
-   * if this format isn't respected we move onto the next line in the file.
-   * isDomain is "TRUE" or "FALSE" (default to "FALSE")
-   * isSecure is "TRUE" or "FALSE" (default to "TRUE")
-   * expires is a PRInt64 integer
-   * note 1: cookie can contain tabs.
-   * note 2: cookies are written in order of lastAccessed time:
-   *         most-recently used come first; least-recently-used come last.
-   */
-
-  while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
-    if (buffer.IsEmpty() || buffer.First() == '#')
-      continue;
-
-    // this is a cheap, cheesy way of parsing a tab-delimited line into
-    // string indexes, which can be lopped off into substrings. just for
-    // purposes of obfuscation, it also checks that each token was found.
-    // todo: use iterators?
-    if ((isDomainIndex = buffer.FindChar('\t', hostIndex)     + 1) == 0 ||
-        (pathIndex     = buffer.FindChar('\t', isDomainIndex) + 1) == 0 ||
-        (secureIndex   = buffer.FindChar('\t', pathIndex)     + 1) == 0 ||
-        (expiresIndex  = buffer.FindChar('\t', secureIndex)   + 1) == 0 ||
-        (nameIndex     = buffer.FindChar('\t', expiresIndex)  + 1) == 0 ||
-        (cookieIndex   = buffer.FindChar('\t', nameIndex)     + 1) == 0)
-      continue;
-
-    // check the expirytime first - if it's expired, ignore
-    // nullstomp the trailing tab, to avoid copying the string
-    char *iter = buffer.BeginWriting();
-    *(iter += nameIndex - 1) = char(0);
-    numInts = PR_sscanf(buffer.get() + expiresIndex, "%lld", &expires);
-    if (numInts != 1 || expires < currentTime)
-      continue;
-
-    isDomain = Substring(buffer, isDomainIndex, pathIndex - isDomainIndex - 1).Equals(kTrue);
-    const nsDependentCSubstring host =
-      Substring(buffer, hostIndex, isDomainIndex - hostIndex - 1);
-    // check for bad legacy cookies (domain not starting with a dot, or containing a port),
-    // and discard
-    if (isDomain && !host.IsEmpty() && host.First() != '.' ||
-        host.FindChar(':') != -1)
-      continue;
-
-    // create a new nsCookie and assign the data.
-    rv = cookieManager->Add(host,
-                            Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
-                            Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
-                            Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
-                            Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).Equals(kTrue),
-                            PR_FALSE, // isHttpOnly
-                            PR_FALSE, // isSession
-                            expires);
-  }
-
-  return rv;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetSignonFileName(PRBool aReplace, char** aFileName)
-{
-  nsresult rv;
-  if (aReplace) {
-    // Find out what the signons file was called, this is stored in a pref
-    // in Seamonkey.
-    nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-    psvc->ResetPrefs();
-
-    nsCOMPtr<nsIFile> sourcePrefsName;
-    mSourceProfile->Clone(getter_AddRefs(sourcePrefsName));
-    sourcePrefsName->Append(FILE_NAME_PREFS_5X);
-    psvc->ReadUserPrefs(sourcePrefsName);
-
-    nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-    rv = branch->GetCharPref("signon.SignonFileName", aFileName);
-  }
-  else 
-    rv = LocateSignonsFile(aFileName);
-  return rv;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::LocateSignonsFile(char** aResult)
-{
-  nsCOMPtr<nsISimpleEnumerator> entries;
-  nsresult rv = mSourceProfile->GetDirectoryEntries(getter_AddRefs(entries));
-  if (NS_FAILED(rv)) return rv;
-
-  nsCAutoString fileName;
-  do {
-    PRBool hasMore = PR_FALSE;
-    rv = entries->HasMoreElements(&hasMore);
-    if (NS_FAILED(rv) || !hasMore) break;
-
-    nsCOMPtr<nsISupports> supp;
-    rv = entries->GetNext(getter_AddRefs(supp));
-    if (NS_FAILED(rv)) break;
-
-    nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
-
-    nsCOMPtr<nsIURI> uri;
-    rv = NS_NewFileURI(getter_AddRefs(uri), currFile);
-    if (NS_FAILED(rv)) break;
-    nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
-
-    nsCAutoString extn;
-    url->GetFileExtension(extn);
-
-    if (extn.Equals("s", CaseInsensitiveCompare)) {
-      url->GetFileName(fileName);
-      break;
-    }
-  }
-  while (1);
-
-  *aResult = ToNewCString(fileName);
-
-  return NS_OK;
-}
-
deleted file mode 100644
--- a/browser/components/migration/src/nsNetscapeProfileMigratorBase.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef netscapeprofilemigratorbase___h___
-#define netscapeprofilemigratorbase___h___
-
-#include "nsILocalFile.h"
-#include "nsIStringBundle.h"
-#include "nsISupportsArray.h"
-#include "nsStringAPI.h"
-
-class nsIFile;
-class nsIPrefBranch;
-
-class nsNetscapeProfileMigratorBase
-{
-public:
-  nsNetscapeProfileMigratorBase();
-  virtual ~nsNetscapeProfileMigratorBase() { }
-
-public:
-  typedef nsresult(*prefConverter)(void*, nsIPrefBranch*);
-
-  struct PrefTransform {
-    const char*   sourcePrefName;
-    const char*   targetPrefName;
-    prefConverter prefGetterFunc;
-    prefConverter prefSetterFunc;
-    PRBool        prefHasValue;
-    union {
-      PRInt32     intValue;
-      PRBool      boolValue;
-      char*       stringValue;
-    };
-  };
-
-  static nsresult GetString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetWString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetWString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetBool(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetBool(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetInt(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetInt(void* aTransform, nsIPrefBranch* aBranch);
-
-protected:
-  nsresult GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
-                                      nsISupportsArray* aProfileNames,
-                                      nsISupportsArray* aProfileLocations);
-
-  nsresult CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName);
-
-  nsresult ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
-                                   const PRUnichar* aImportSourceNameKey);
-
-  nsresult ImportNetscapeCookies(nsIFile* aCookiesFile);
-
-  nsresult GetSignonFileName(PRBool aReplace, char** aFileName);
-  nsresult LocateSignonsFile(char** aResult);
-
-protected:
-  nsCOMPtr<nsILocalFile> mSourceProfile;
-  nsCOMPtr<nsIFile> mTargetProfile;
-};
- 
-#endif
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -157,17 +157,16 @@ nsProfileMigrator::Import()
 // nsProfileMigrator
 
 NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
 
 #ifdef XP_WIN
 
 #define INTERNAL_NAME_IEXPLORE        "iexplore"
 #define INTERNAL_NAME_MOZILLA_SUITE   "apprunner"
-#define INTERNAL_NAME_SEAMONKEY       "seamonkey"
 #define INTERNAL_NAME_OPERA           "opera"
 #endif
 
 nsresult
 nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
                                                 nsCOMPtr<nsIBrowserProfileMigrator>& bpm)
 {
 #if XP_WIN
@@ -238,22 +237,17 @@ nsProfileMigrator::GetDefaultBrowserMigr
   nsAutoString internalName;
   if (NS_FAILED(lfw->GetVersionInfoField("InternalName", internalName)))
     return NS_ERROR_FAILURE;
 
   if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_IEXPLORE)) {
     aKey = "ie";
     return NS_OK;
   }
-  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_MOZILLA_SUITE) ||
-      internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_SEAMONKEY)) {
-    aKey = "seamonkey";
-    return NS_OK;
-  }
-  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
+  else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
     aKey = "opera";
     return NS_OK;
   }
 
 #else
   PRBool exists = PR_FALSE;
 #define CHECK_MIGRATOR(browser) do {\
   bpm = do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX browser);\
@@ -262,17 +256,16 @@ nsProfileMigrator::GetDefaultBrowserMigr
   if (exists) {\
     aKey = browser;\
     return NS_OK;\
   }} while(0)
 
 #if defined(XP_MACOSX)
   CHECK_MIGRATOR("safari");
 #endif
-  CHECK_MIGRATOR("seamonkey");
   CHECK_MIGRATOR("opera");
 
 #undef CHECK_MIGRATOR
 #endif
   return NS_ERROR_FAILURE;
 }
 
 PRBool
deleted file mode 100644
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
+++ /dev/null
@@ -1,721 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsBrowserProfileMigratorUtils.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsIObserverService.h"
-#include "nsILoginInfo.h"
-#include "nsILoginManager.h"
-#include "nsILoginManagerStorage.h"
-#include "nsIPrefLocalizedString.h"
-#include "nsIPrefService.h"
-#include "nsIServiceManager.h"
-#include "nsISupportsArray.h"
-#include "nsISupportsPrimitives.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsSeamonkeyProfileMigrator.h"
-#include "nsIProfileMigrator.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// nsSeamonkeyProfileMigrator
-
-#define FILE_NAME_BOOKMARKS       NS_LITERAL_STRING("bookmarks.html")
-#define FILE_NAME_COOKIES         NS_LITERAL_STRING("cookies.txt")
-#define FILE_NAME_SITEPERM_OLD    NS_LITERAL_STRING("cookperm.txt")
-#define FILE_NAME_SITEPERM_NEW    NS_LITERAL_STRING("hostperm.1")
-#define FILE_NAME_CERT8DB         NS_LITERAL_STRING("cert8.db")
-#define FILE_NAME_KEY3DB          NS_LITERAL_STRING("key3.db")
-#define FILE_NAME_SECMODDB        NS_LITERAL_STRING("secmod.db")
-#define FILE_NAME_MIMETYPES       NS_LITERAL_STRING("mimeTypes.rdf")
-#define FILE_NAME_DOWNLOADS       NS_LITERAL_STRING("downloads.rdf")
-#define FILE_NAME_PREFS           NS_LITERAL_STRING("prefs.js")
-#define FILE_NAME_USER_PREFS      NS_LITERAL_STRING("user.js")
-#define FILE_NAME_USERCONTENT     NS_LITERAL_STRING("userContent.css")
-#define DIR_NAME_CHROME           NS_LITERAL_STRING("chrome")
-
-NS_IMPL_ISUPPORTS1(nsSeamonkeyProfileMigrator, nsIBrowserProfileMigrator)
-
-nsSeamonkeyProfileMigrator::nsSeamonkeyProfileMigrator()
-{
-  mObserverService = do_GetService("@mozilla.org/observer-service;1");
-}
-
-nsSeamonkeyProfileMigrator::~nsSeamonkeyProfileMigrator()
-{
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// nsIBrowserProfileMigrator
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
-{
-  nsresult rv = NS_OK;
-  PRBool aReplace = aStartup ? PR_TRUE : PR_FALSE;
-
-  if (!mTargetProfile) {
-    GetProfilePath(aStartup, mTargetProfile);
-    if (!mTargetProfile) return NS_ERROR_FAILURE;
-  }
-  if (!mSourceProfile)
-    GetSourceProfile(aProfile);
-
-  NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
-
-  COPY_DATA(CopyPreferences,  aReplace, nsIBrowserProfileMigrator::SETTINGS);
-  COPY_DATA(CopyCookies,      aReplace, nsIBrowserProfileMigrator::COOKIES);
-  COPY_DATA(CopyPasswords,    aReplace, nsIBrowserProfileMigrator::PASSWORDS);
-  COPY_DATA(CopyOtherData,    aReplace, nsIBrowserProfileMigrator::OTHERDATA);
-
-  // Need to do startup before trying to copy bookmarks, since bookmarks
-  // import requires a profile. Can't do it earlier because services might
-  // end up creating the files we try to copy above.
-  if (aStartup) {
-    rv = aStartup->DoStartup();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  COPY_DATA(CopyBookmarks,    aReplace, nsIBrowserProfileMigrator::BOOKMARKS);
-
-  if (aReplace && 
-      (aItems & nsIBrowserProfileMigrator::SETTINGS || 
-       aItems & nsIBrowserProfileMigrator::COOKIES || 
-       aItems & nsIBrowserProfileMigrator::PASSWORDS ||
-       !aItems)) {
-    // Permissions (Images, Cookies, Popups)
-    rv |= CopyFile(FILE_NAME_SITEPERM_NEW, FILE_NAME_SITEPERM_NEW);
-    rv |= CopyFile(FILE_NAME_SITEPERM_OLD, FILE_NAME_SITEPERM_OLD);
-  }
-
-  NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetMigrateData(const PRUnichar* aProfile, 
-                                           PRBool aReplace, 
-                                           PRUint16* aResult)
-{
-  *aResult = 0;
-
-  if (!mSourceProfile) {
-    GetSourceProfile(aProfile);
-    if (!mSourceProfile)
-      return NS_ERROR_FILE_NOT_FOUND;
-  }
-
-  MigrationData data[] = { { ToNewUnicode(FILE_NAME_PREFS),
-                             nsIBrowserProfileMigrator::SETTINGS,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_USER_PREFS),
-                             nsIBrowserProfileMigrator::SETTINGS,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_COOKIES),
-                             nsIBrowserProfileMigrator::COOKIES,
-                             PR_FALSE },
-                           { ToNewUnicode(FILE_NAME_BOOKMARKS),
-                             nsIBrowserProfileMigrator::BOOKMARKS,
-                             PR_FALSE },
-                           { ToNewUnicode(FILE_NAME_DOWNLOADS),
-                             nsIBrowserProfileMigrator::OTHERDATA,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_MIMETYPES),
-                             nsIBrowserProfileMigrator::OTHERDATA,
-                             PR_TRUE } };
-                                                                  
-  // Frees file name strings allocated above.
-  GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData), 
-                          aReplace, mSourceProfile, aResult);
-
-  // Now locate passwords
-  nsCString signonsFileName;
-  GetSignonFileName(aReplace, getter_Copies(signonsFileName));
-
-  if (!signonsFileName.IsEmpty()) {
-    NS_ConvertASCIItoUTF16 fileName(signonsFileName);
-    nsCOMPtr<nsIFile> sourcePasswordsFile;
-    mSourceProfile->Clone(getter_AddRefs(sourcePasswordsFile));
-    sourcePasswordsFile->Append(fileName);
-    
-    PRBool exists;
-    sourcePasswordsFile->Exists(&exists);
-    if (exists)
-      *aResult |= nsIBrowserProfileMigrator::PASSWORDS;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceExists(PRBool* aResult)
-{
-  nsCOMPtr<nsISupportsArray> profiles;
-  GetSourceProfiles(getter_AddRefs(profiles));
-
-  if (profiles) { 
-    PRUint32 count;
-    profiles->Count(&count);
-    *aResult = count > 0;
-  }
-  else
-    *aResult = PR_FALSE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
-{
-  nsCOMPtr<nsISupportsArray> profiles;
-  GetSourceProfiles(getter_AddRefs(profiles));
-
-  if (profiles) {
-    PRUint32 count;
-    profiles->Count(&count);
-    *aResult = count > 1;
-  }
-  else
-    *aResult = PR_FALSE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
-{
-  if (!mProfileNames && !mProfileLocations) {
-    mProfileNames = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
-    mProfileLocations = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
-    NS_ENSURE_TRUE(mProfileNames && mProfileLocations, NS_ERROR_UNEXPECTED);
-
-    // Fills mProfileNames and mProfileLocations
-    FillProfileDataFromSeamonkeyRegistry();
-  }
-  
-  NS_IF_ADDREF(*aResult = mProfileNames);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
-{
-  // Load the source pref file
-  nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  psvc->ResetPrefs();
-
-  nsCOMPtr<nsIFile> sourcePrefsFile;
-  
-  mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
-  sourcePrefsFile->Append(FILE_NAME_PREFS);
-
-  psvc->ReadUserPrefs(sourcePrefsFile);
-
-  nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-
-  PRBool hasUserValue;
-  nsCOMPtr<nsIPrefLocalizedString> prefValue;
-  nsresult rv = branch->PrefHasUserValue("browser.startup.homepage", &hasUserValue);
-  if (NS_SUCCEEDED(rv) && hasUserValue) {
-    rv = branch->GetComplexValue("browser.startup.homepage", 
-                                 NS_GET_IID(nsIPrefLocalizedString),
-                                 getter_AddRefs(prefValue));
-    if (NS_SUCCEEDED(rv) && prefValue) {
-      nsString data;
-      prefValue->ToString(getter_Copies(data));
-
-      nsCAutoString val;
-      val = ToNewCString(NS_ConvertUTF16toUTF8(data));
-
-      aResult.Assign(val);
-    }
-  }
-
-  psvc->ResetPrefs();
-  psvc->ReadUserPrefs(nsnull);
-
-  return NS_OK;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// nsSeamonkeyProfileMigrator
-
-nsresult
-nsSeamonkeyProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
-{
-  PRUint32 count;
-  mProfileNames->Count(&count);
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsCOMPtr<nsISupportsString> str;
-    mProfileNames->QueryElementAt(i, NS_GET_IID(nsISupportsString),
-                                  getter_AddRefs(str));
-    nsString profileName;
-    str->GetData(profileName);
-    if (profileName.Equals(aProfile)) {
-      mProfileLocations->QueryElementAt(i, NS_GET_IID(nsILocalFile),
-                                        getter_AddRefs(mSourceProfile));
-      break;
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::FillProfileDataFromSeamonkeyRegistry()
-{
-  // Find the Seamonkey Registry
-  nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
-  nsCOMPtr<nsILocalFile> seamonkeyRegistry;
-#ifdef XP_WIN
-  fileLocator->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
-#elif defined(XP_MACOSX)
-  fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Application Registry"));
-#elif defined(XP_UNIX)
-  fileLocator->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING(".mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("appreg"));
-#elif defined(XP_OS2)
-  fileLocator->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
-#endif
-
-  return GetProfileDataFromRegistry(seamonkeyRegistry, mProfileNames, mProfileLocations);
-}
-
-#define F(a) nsSeamonkeyProfileMigrator::a
-
-#define MAKEPREFTRANSFORM(pref, newpref, getmethod, setmethod) \
-  { pref, newpref, F(Get##getmethod), F(Set##setmethod), PR_FALSE, { -1 } }
-
-#define MAKESAMETYPEPREFTRANSFORM(pref, method) \
-  { pref, 0, F(Get##method), F(Set##method), PR_FALSE, { -1 } }
-
-
-static 
-nsSeamonkeyProfileMigrator::PrefTransform gTransforms[] = {
-  MAKESAMETYPEPREFTRANSFORM("signon.SignonFileName",                    String),
-  MAKESAMETYPEPREFTRANSFORM("browser.tabs.autoHide",                    Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.tabs.loadInBackground",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.enable_automatic_image_resizing",  Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.warnAboutCookies",          Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.enabled",          Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.behavior",         Int),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_open_during_load",             Bool),
-  MAKESAMETYPEPREFTRANSFORM("signon.rememberSignons",                   Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.enable_ssl3",                     Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.enable_tls",                      Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_entering_secure",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_entering_weak",              Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_leaving_secure",             Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_submit_insecure",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_viewing_mixed",              Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.default_personal_cert",           String),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.enabled",                    Int),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.signingCA",                  String),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.URL",                        String),
-  MAKESAMETYPEPREFTRANSFORM("javascript.enabled",                       Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_move_resize",           Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_flip",                  Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_open_feature.status",   Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_status_change",         Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_image_src_set",                Bool),
-  MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.autostart",    Bool),
-  MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.linksonly",    Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.type",                       Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.http",                       String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.http_port",                  Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp",                        String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp_port",                   Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl",                        String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl_port",                   Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.socks",                      String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.socks_port",                 Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.no_proxies_on",              String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.autoconfig_url",             String),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.foreground_color",         String),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.background_color",         String),
-  MAKESAMETYPEPREFTRANSFORM("browser.anchor_color",                     String),
-  MAKESAMETYPEPREFTRANSFORM("browser.visited_color",                    String),
-  MAKESAMETYPEPREFTRANSFORM("browser.underline_anchors",                Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_system_colors",        Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_colors",      Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_fonts",       Bool),
-  MAKESAMETYPEPREFTRANSFORM("intl.charset.default",                     String),
-  MAKESAMETYPEPREFTRANSFORM("intl.accept_languages",                    String),
-
-  MAKEPREFTRANSFORM("network.image.imageBehavior",      0, Int, Image),
-  MAKEPREFTRANSFORM("network.cookie.cookieBehavior",    0, Int, Cookie),
-  MAKEPREFTRANSFORM("browser.downloadmanager.behavior", 0, Int, DownloadManager),
-
-  MAKEPREFTRANSFORM("wallet.captureForms", "formfill.enabled", Bool, Bool)
-};
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetImage(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-
-  if (xform->prefHasValue)
-    rv = aBranch->SetIntPref("network.image.imageBehavior", xform->intValue == 1 ? 0 : xform->intValue);
-
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetCookie(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-
-  if (xform->prefHasValue)
-    rv = aBranch->SetIntPref("network.cookie.cookieBehavior", xform->intValue == 3 ? 0 : xform->intValue);
-
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-  
-  if (xform->prefHasValue) {
-    // Seamonkey's download manager uses a single pref to control behavior:
-    // 0 - show download manager window
-    // 1 - show individual progress dialogs
-    // 2 - show nothing
-    //
-    // Firefox has only a download manager window, but it can behave like a progress dialog, thus:
-    // 0 || 1  -> show downloads window when a download starts
-    // 2       -> don't show anything when a download starts
-    // 1       -> close the downloads window as if it were a progress window when downloads complete.
-    //
-    rv |= aBranch->SetBoolPref("browser.download.manager.showWhenStarting", xform->intValue != 2);
-    rv |= aBranch->SetBoolPref("browser.download.manager.closeWhenDone", xform->intValue == 1);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::TransformPreferences(const nsAString& aSourcePrefFileName,
-                                                 const nsAString& aTargetPrefFileName)
-{
-  PrefTransform* transform;
-  PrefTransform* end = gTransforms + sizeof(gTransforms)/sizeof(PrefTransform);
-
-  // Load the source pref file
-  nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  psvc->ResetPrefs();
-
-  nsCOMPtr<nsIFile> sourcePrefsFile;
-  mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
-  sourcePrefsFile->Append(aSourcePrefFileName);
-  psvc->ReadUserPrefs(sourcePrefsFile);
-
-  nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-  for (transform = gTransforms; transform < end; ++transform)
-    transform->prefGetterFunc(transform, branch);
-
-  nsTArray<FontPref> fontPrefs;
-  ReadFontsBranch(psvc, &fontPrefs);
-
-  // Now that we have all the pref data in memory, load the target pref file,
-  // and write it back out
-  psvc->ResetPrefs();
-  for (transform = gTransforms; transform < end; ++transform)
-    transform->prefSetterFunc(transform, branch);
-
-  WriteFontsBranch(psvc, &fontPrefs);
-
-  nsCOMPtr<nsIFile> targetPrefsFile;
-  mTargetProfile->Clone(getter_AddRefs(targetPrefsFile));
-  targetPrefsFile->Append(aTargetPrefFileName);
-  psvc->SavePrefFile(targetPrefsFile);
-
-  psvc->ResetPrefs();
-  psvc->ReadUserPrefs(nsnull);
-
-  return NS_OK;
-}
-
-void
-nsSeamonkeyProfileMigrator::ReadFontsBranch(nsIPrefService* aPrefService, 
-                                            nsTArray<FontPref>* aPrefs)
-{
-  // Enumerate the branch
-  nsCOMPtr<nsIPrefBranch> branch;
-  aPrefService->GetBranch("font.", getter_AddRefs(branch));
-
-  PRUint32 count;
-  char** prefs = nsnull;
-  nsresult rv = branch->GetChildList("", &count, &prefs);
-  if (NS_FAILED(rv)) return;
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    // Save each pref's value into an array
-    char* currPref = prefs[i];
-    PRInt32 type;
-    branch->GetPrefType(currPref, &type);
-    FontPref* pref = aPrefs->AppendElement();
-    pref->prefName = currPref;
-    pref->type = type;
-    switch (type) {
-    case nsIPrefBranch::PREF_STRING:
-      rv = branch->GetCharPref(currPref, &pref->stringValue);
-      break;
-    case nsIPrefBranch::PREF_BOOL:
-      rv = branch->GetBoolPref(currPref, &pref->boolValue);
-      break;
-    case nsIPrefBranch::PREF_INT:
-      rv = branch->GetIntPref(currPref, &pref->intValue);
-      break;
-    case nsIPrefBranch::PREF_INVALID:
-      {
-        nsCOMPtr<nsIPrefLocalizedString> str;
-        rv = branch->GetComplexValue(currPref, 
-                                    NS_GET_IID(nsIPrefLocalizedString), 
-                                    getter_AddRefs(str));
-        if (NS_SUCCEEDED(rv) && str)
-          str->ToString(&pref->wstringValue);
-      }
-      break;
-    }
-
-    if (NS_FAILED(rv))
-      aPrefs->RemoveElementAt(aPrefs->Length()-1);
-  }
-}
-
-void
-nsSeamonkeyProfileMigrator::WriteFontsBranch(nsIPrefService* aPrefService,
-                                             nsTArray<FontPref>* aPrefs)
-{
-  nsresult rv;
-
-  // Enumerate the branch
-  nsCOMPtr<nsIPrefBranch> branch;
-  aPrefService->GetBranch("font.", getter_AddRefs(branch));
-
-  PRUint32 count = aPrefs->Length();
-  for (PRUint32 i = 0; i < count; ++i) {
-    FontPref &pref = aPrefs->ElementAt(i);
-    switch (pref.type) {
-    case nsIPrefBranch::PREF_STRING:
-      rv = branch->SetCharPref(pref.prefName, pref.stringValue);
-      NS_Free(pref.stringValue);
-      pref.stringValue = nsnull;
-      break;
-    case nsIPrefBranch::PREF_BOOL:
-      rv = branch->SetBoolPref(pref.prefName, pref.boolValue);
-      break;
-    case nsIPrefBranch::PREF_INT:
-      rv = branch->SetIntPref(pref.prefName, pref.intValue);
-      break;
-    case nsIPrefBranch::PREF_INVALID:
-      nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-      pls->SetData(pref.wstringValue);
-      rv = branch->SetComplexValue(pref.prefName, 
-                                   NS_GET_IID(nsIPrefLocalizedString),
-                                   pls);
-      NS_Free(pref.wstringValue);
-      pref.wstringValue = nsnull;
-      break;
-    }
-    NS_Free(pref.prefName);
-  }
-  aPrefs->Clear();
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyPreferences(PRBool aReplace)
-{
-  nsresult rv = NS_OK;
-  if (!aReplace)
-    return rv;
-
-  rv |= TransformPreferences(FILE_NAME_PREFS, FILE_NAME_PREFS);
-  rv |= CopyFile(FILE_NAME_USER_PREFS, FILE_NAME_USER_PREFS);
-
-  // Security Stuff
-  rv |= CopyFile(FILE_NAME_CERT8DB, FILE_NAME_CERT8DB);
-  rv |= CopyFile(FILE_NAME_KEY3DB, FILE_NAME_KEY3DB);
-  rv |= CopyFile(FILE_NAME_SECMODDB, FILE_NAME_SECMODDB);
-
-  // User MIME Type overrides
-  rv |= CopyFile(FILE_NAME_MIMETYPES, FILE_NAME_MIMETYPES);
-
-  rv |= CopyUserContentSheet();
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::CopyUserContentSheet()
-{
-  nsCOMPtr<nsIFile> sourceUserContent;
-  mSourceProfile->Clone(getter_AddRefs(sourceUserContent));
-  sourceUserContent->Append(DIR_NAME_CHROME);
-  sourceUserContent->Append(FILE_NAME_USERCONTENT);
-
-  PRBool exists = PR_FALSE;
-  sourceUserContent->Exists(&exists);
-  if (!exists)
-    return NS_OK;
-
-  nsCOMPtr<nsIFile> targetUserContent;
-  mTargetProfile->Clone(getter_AddRefs(targetUserContent));
-  targetUserContent->Append(DIR_NAME_CHROME);
-  nsCOMPtr<nsIFile> targetChromeDir;
-  targetUserContent->Clone(getter_AddRefs(targetChromeDir));
-  targetUserContent->Append(FILE_NAME_USERCONTENT);
-
-  targetUserContent->Exists(&exists);
-  if (exists)
-    targetUserContent->Remove(PR_FALSE);
-
-  return sourceUserContent->CopyTo(targetChromeDir, FILE_NAME_USERCONTENT);
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyCookies(PRBool aReplace)
-{
-  nsresult rv;
-  if (aReplace)
-    rv = CopyFile(FILE_NAME_COOKIES, FILE_NAME_COOKIES);
-  else {
-    nsCOMPtr<nsIFile> seamonkeyCookiesFile;
-    mSourceProfile->Clone(getter_AddRefs(seamonkeyCookiesFile));
-    seamonkeyCookiesFile->Append(FILE_NAME_COOKIES);
-
-    rv = ImportNetscapeCookies(seamonkeyCookiesFile);
-  }
-  return rv;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyPasswords(PRBool aReplace)
-{
-  nsresult rv;
-
-  nsCString signonsFileName;
-  GetSignonFileName(aReplace, getter_Copies(signonsFileName));
-
-  if (signonsFileName.IsEmpty())
-    return NS_ERROR_FILE_NOT_FOUND;
-
-  NS_ConvertASCIItoUTF16 fileName(signonsFileName);
-  if (aReplace)
-    rv = CopyFile(fileName, fileName);
-  else {
-    // Get the password manager, which is the destination for the passwords
-    // being migrated. Also create a new instance of the legacy password
-    // storage component, which we'll use to slurp in the signons from
-    // Seamonkey's signons.txt.
-    nsCOMPtr<nsILoginManager> pwmgr(
-        do_GetService("@mozilla.org/login-manager;1"));
-    nsCOMPtr<nsILoginManagerStorage> importer(
-        do_CreateInstance("@mozilla.org/login-manager/storage/legacy;1"));
-
-    nsCOMPtr<nsIFile> signonsFile;
-    mSourceProfile->Clone(getter_AddRefs(signonsFile));
-    signonsFile->Append(fileName);
-
-    importer->InitWithFile(signonsFile, nsnull);
-
-    PRUint32 count;
-    nsILoginInfo **logins;
-
-    rv = importer->GetAllLogins(&count, &logins);
-    NS_ENSURE_SUCCESS(rv, rv);
-    for (PRUint32 i = 0; i < count; i++) {
-        pwmgr->AddLogin(logins[i]);
-    }
-    NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
-
-    PRUnichar **hostnames;
-    rv = importer->GetAllDisabledHosts(&count, &hostnames);
-    NS_ENSURE_SUCCESS(rv, rv);
-    for (PRUint32 i = 0; i < count; i++) {
-        pwmgr->SetLoginSavingEnabled(nsDependentString(hostnames[i]),
-                                     PR_FALSE);
-    }
-    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, hostnames);
-  }
-  return rv;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyBookmarks(PRBool aReplace)
-{
-  nsresult rv;
-  if (aReplace) {
-    // Initialize the default bookmarks
-    rv = InitializeBookmarks(mTargetProfile);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Merge in the bookmarks from the source profile
-    nsCOMPtr<nsIFile> sourceFile;
-    mSourceProfile->Clone(getter_AddRefs(sourceFile));
-    sourceFile->Append(FILE_NAME_BOOKMARKS);
-    rv = ImportBookmarksHTML(sourceFile, PR_TRUE, PR_FALSE, EmptyString().get());
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  else {
-    rv = ImportNetscapeBookmarks(FILE_NAME_BOOKMARKS, 
-                                 NS_LITERAL_STRING("sourceNameSeamonkey").get());
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyOtherData(PRBool aReplace)
-{
-  return aReplace ? CopyFile(FILE_NAME_DOWNLOADS, FILE_NAME_DOWNLOADS) : NS_OK;
-}
-
deleted file mode 100644
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef seamonkeyprofilemigrator___h___
-#define seamonkeyprofilemigrator___h___
-
-#include "nsIBrowserProfileMigrator.h"
-#include "nsILocalFile.h"
-#include "nsIObserverService.h"
-#include "nsISupportsArray.h"
-#include "nsNetscapeProfileMigratorBase.h"
-#include "nsStringAPI.h"
-#include "nsTArray.h"
-
-class nsIFile;
-class nsIPrefBranch;
-class nsIPrefService;
-
-struct FontPref {
-  char*         prefName;
-  PRInt32       type;
-  union {
-    char*       stringValue;
-    PRInt32     intValue;
-    PRBool      boolValue;
-    PRUnichar*  wstringValue;
-  };
-};
-
-class nsSeamonkeyProfileMigrator : public nsNetscapeProfileMigratorBase, 
-                                   public nsIBrowserProfileMigrator
-{
-public:
-  NS_DECL_NSIBROWSERPROFILEMIGRATOR
-  NS_DECL_ISUPPORTS
-
-  nsSeamonkeyProfileMigrator();
-  virtual ~nsSeamonkeyProfileMigrator();
-
-public:
-  static nsresult SetImage(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetCookie(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch);
-
-protected:
-  nsresult FillProfileDataFromSeamonkeyRegistry();
-  nsresult GetSourceProfile(const PRUnichar* aProfile);
-
-  nsresult CopyPreferences(PRBool aReplace);
-  nsresult TransformPreferences(const nsAString& aSourcePrefFileName,
-                                const nsAString& aTargetPrefFileName);
-  void     ReadFontsBranch(nsIPrefService* aPrefService,
-                           nsTArray<FontPref>* aPrefs);
-  void     WriteFontsBranch(nsIPrefService* aPrefService,
-                            nsTArray<FontPref>* aPrefs);
-
-  nsresult CopyUserContentSheet();
-
-  nsresult CopyCookies(PRBool aReplace);
-  nsresult CopyPasswords(PRBool aReplace);
-  nsresult LocateSignonsFile(char** aResult);
-  nsresult CopyBookmarks(PRBool aReplace);
-  nsresult CopyOtherData(PRBool aReplace);
-
-private:
-  nsCOMPtr<nsISupportsArray> mProfileNames;
-  nsCOMPtr<nsISupportsArray> mProfileLocations;
-  nsCOMPtr<nsIObserverService> mObserverService;
-};
- 
-#endif
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -272,27 +272,40 @@ var PlacesOrganizer = {
   },
 
   /**
    * Sets the search scope based on aNode's properties.
    * @param   aNode
    *          the node to set up scope from
    */
   _setSearchScopeForNode: function PO__setScopeForNode(aNode) {
-    var itemId = aNode.itemId;
+    let itemId = aNode.itemId;
+
+    // Set default buttons status.
+    let bookmarksButton = document.getElementById("scopeBarAll");
+    bookmarksButton.hidden = false;
+    let downloadsButton = document.getElementById("scopeBarDownloads");
+    downloadsButton.hidden = true;
+
     if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
         itemId == PlacesUIUtils.leftPaneQueries["History"]) {
       PlacesQueryBuilder.setScope("history");
     }
-    // Default to All Bookmarks for all other nodes, per bug 469437.
-    else
+    else if (itemId == PlacesUIUtils.leftPaneQueries["Downloads"]) {
+      downloadsButton.hidden = false;
+      bookmarksButton.hidden = true;
+      PlacesQueryBuilder.setScope("downloads");
+    }
+    else {
+      // Default to All Bookmarks for all other nodes, per bug 469437.
       PlacesQueryBuilder.setScope("bookmarks");
+    }
 
     // Enable or disable the folder scope button.
-    var folderButton = document.getElementById("scopeBarFolder");
+    let folderButton = document.getElementById("scopeBarFolder");
     folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode) ||
                           itemId == PlacesUIUtils.allBookmarksFolderId;
   },
 
   /**
    * Handle clicks on the tree.
    * Single Left click, right click or modified click do not result in any
    * special action, since they're related to selection.
@@ -896,19 +909,31 @@ var PlacesSearchBox = {
         var query = PlacesUtils.history.getNewQuery();
         query.searchTerms = filterString;
         var options = currentOptions.clone();
         // Make sure we're getting uri results.
         options.resultType = currentOptions.RESULT_TYPE_URI;
         options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
         content.load([query], options);
       }
-      else
+      else {
         content.applyFilter(filterString);
+      }
       break;
+    case "downloads": {
+        let query = PlacesUtils.history.getNewQuery();
+        query.searchTerms = filterString;
+        query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
+        let options = currentOptions.clone();
+        // Make sure we're getting uri results.
+        options.resultType = currentOptions.RESULT_TYPE_URI;
+        options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+        content.load([query], options);
+      break;
+    }
     default:
       throw "Invalid filterCollection on search";
       break;
     }
 
     PlacesSearchBox.showSearchUI();
 
     // Update the details panel
@@ -928,27 +953,38 @@ var PlacesSearchBox = {
    */
   findCurrent: function PSB_findCurrent() {
     PlacesQueryBuilder.setScope("collection");
     this.focus();
   },
 
   /**
    * Updates the display with the title of the current collection.
-   * @param   title
+   * @param   aTitle
    *          The title of the current collection.
    */
-  updateCollectionTitle: function PSB_updateCollectionTitle(title) {
-    if (title)
-      this.searchFilter.placeholder =
-        PlacesUIUtils.getFormattedString("searchCurrentDefault", [title]);
-    else
-      this.searchFilter.placeholder = this.filterCollection == "history" ?
-                                      PlacesUIUtils.getString("searchHistory") :
-                                      PlacesUIUtils.getString("searchBookmarks");
+  updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
+    let title = "";
+    if (aTitle) {
+      title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
+                                               [aTitle]);
+    }
+    else {
+      switch(this.filterCollection) {
+        case "history":
+          title = PlacesUIUtils.getString("searchHistory");
+          break;
+        case "downloads":
+          title = PlacesUIUtils.getString("searchDownloads");
+          break;
+        default:
+          title = PlacesUIUtils.getString("searchBookmarks");                                    
+      }
+    }
+    this.searchFilter.placeholder = title;
   },
 
   /**
    * Gets/sets the active collection from the dropdown menu.
    */
   get filterCollection() {
     return this.searchFilter.getAttribute("collection");
   },
@@ -1020,32 +1056,36 @@ var PlacesQueryBuilder = {
   onScopeSelected: function PQB_onScopeSelected(aButton) {
     switch (aButton.id) {
     case "scopeBarHistory":
       this.setScope("history");
       break;
     case "scopeBarFolder":
       this.setScope("collection");
       break;
+    case "scopeBarDownloads":
+      this.setScope("downloads");
+      break;
     case "scopeBarAll":
       this.setScope("bookmarks");
       break;
     default:
       throw "Invalid search scope button ID";
       break;
     }
   },
 
   /**
    * Sets the search scope.  This can be called when no search is active, and
    * in that case, when the user does begin a search aScope will be used (see
    * PSB_search()).  If there is an active search, it's performed again to
    * update the content tree.
    * @param   aScope
-   *          the search scope, "bookmarks", "collection", or "history"
+   *          The search scope: "bookmarks", "collection", "downloads" or
+   *          "history".
    */
   setScope: function PQB_setScope(aScope) {
     // Determine filterCollection, folders, and scopeButtonId based on aScope.
     var filterCollection;
     var folders = [];
     var scopeButtonId;
     switch (aScope) {
     case "history":
@@ -1067,16 +1107,20 @@ var PlacesQueryBuilder = {
       // selected node, choose bookmarks scope.
     case "bookmarks":
       filterCollection = "bookmarks";
       scopeButtonId = "scopeBarAll";
       folders.push(PlacesUtils.bookmarksMenuFolderId,
                    PlacesUtils.toolbarFolderId,
                    PlacesUtils.unfiledBookmarksFolderId);
       break;
+    case "downloads":
+      filterCollection = "downloads";
+      scopeButtonId = "scopeBarDownloads";
+      break;
     default:
       throw "Invalid search scope";
       break;
     }
 
     // Check the appropriate scope button in the scope bar.
     document.getElementById(scopeButtonId).checked = true;
 
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -407,28 +407,26 @@
       <toolbox id="searchModifiers" hidden="true">
         <toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
           <label id="scopeBarTitle" value="&search.in.label;"/>
           <toolbarbutton id="scopeBarAll" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          label="&search.scopeBookmarks.label;"
                          accesskey="&search.scopeBookmarks.accesskey;"/>
-          <!--
+          <toolbarbutton id="scopeBarHistory" class="small-margin"
+                         type="radio" group="scopeBar"
+                         oncommand="PlacesQueryBuilder.onScopeSelected(this);"
+                         label="&search.scopeHistory.label;"
+                         accesskey="&search.scopeHistory.accesskey;"/>
           <toolbarbutton id="scopeBarDownloads" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          label="&search.scopeDownloads.label;"
                          accesskey="&search.scopeDownloads.accesskey;"/>
-          -->
-          <toolbarbutton id="scopeBarHistory" class="small-margin"
-                         type="radio" group="scopeBar"
-                         oncommand="PlacesQueryBuilder.onScopeSelected(this);"
-                         label="&search.scopeHistory.label;"
-                         accesskey="&search.scopeHistory.accesskey;"/>
           <toolbarbutton id="scopeBarFolder" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          accesskey="&search.scopeFolder.accesskey;"
                          emptytitle="&search.scopeFolder.label;" flex="1"/>
           <!-- The folder scope button should flex but not take up more room
                 than its label needs.  The only simple way to do that is to
                 set a really big flex on the spacer, e.g., 2^31 - 1. -->
--- a/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
+++ b/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
@@ -134,23 +134,8 @@ let tests = {
     // get the Unsorted Bookmarks node
     PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
     // now we can see what is in the _content tree
     let unsortedNode = PlacesOrganizer._content.view.nodeForTreeIndex(1);
     ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri);
     is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
   },
 };
-
-/**
- * Clears history invoking callback when done.
- */
-function waitForClearHistory(aCallback) {
-  const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
-      aCallback();
-    }
-  };
-  Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
-  PlacesUtils.bhistory.removeAllPages();
-}
--- a/browser/components/places/tests/browser/browser_forgetthissite_single.js
+++ b/browser/components/places/tests/browser/browser_forgetthissite_single.js
@@ -32,35 +32,16 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // This test makes sure that the Forget This Site command is hidden for multiple
 // selections.
-
-/**
- * Clears history invoking callback when done.
- */
-function waitForClearHistory(aCallback) {
-  const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
-      aCallback();
-    }
-  };
-  Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
-
-  let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
-           getService(Ci.nsINavHistoryService);
-  hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
-}
-
 function test() {
   // initialization
   waitForExplicitFinish();
 
   // Add a history entry.
   let TEST_URIs = ["http://www.mozilla.org/test1", "http://www.mozilla.org/test2"];
   ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
   let history = PlacesUtils.history;
--- a/browser/components/places/tests/browser/browser_history_sidebar_search.js
+++ b/browser/components/places/tests/browser/browser_history_sidebar_search.js
@@ -43,30 +43,16 @@ var hs = Cc["@mozilla.org/browser/nav-hi
          getService(Ci.nsINavHistoryService);
 var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
 var ios = Cc["@mozilla.org/network/io-service;1"].
           getService(Ci.nsIIOService);
 function uri(spec) {
   return ios.newURI(spec, null, null);
 }
 
-/**
- * Clears history invoking callback when done.
- */
-function waitForClearHistory(aCallback) {
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-      aCallback(aSubject, aTopic, aData);
-    }
-  };
-  Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
-  PlacesUtils.bhistory.removeAllPages();
-}
-
 var sidebar = document.getElementById("sidebar");
 
 function add_visit(aURI, aDate) {
   var visitId = hs.addVisit(aURI,
                             aDate,
                             null, // no referrer
                             hs.TRANSITION_TYPED, // user typed in URL bar
                             false, // not redirect
--- a/browser/components/places/tests/browser/browser_library_panel_leak.js
+++ b/browser/components/places/tests/browser/browser_library_panel_leak.js
@@ -78,19 +78,8 @@ function test() {
   // Add an history entry.
   ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
   PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_URI), Date.now() * 1000,
                                null, PlacesUtils.history.TRANSITION_TYPED,
                                false, 0);
 
   openLibrary(onLibraryReady);
 }
-
-function waitForClearHistory(aCallback) {
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-      aCallback(aSubject, aTopic, aData);
-    }
-  };
-  Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
-  PlacesUtils.bhistory.removeAllPages();
-}
--- a/browser/components/places/tests/browser/browser_library_search.js
+++ b/browser/components/places/tests/browser/browser_library_search.js
@@ -56,115 +56,127 @@
  *   4. if the folder scope button is enabled clicks it,
  *   5. resets the search and ensures that the content tree is correct and that
  *      the search UI is hidden, and
  *   6. if folder scope was clicked, searches again and ensures folder scope
  *      remains selected.
  */
 
 const TEST_URL = "http://dummy.mozilla.org/";
+const TEST_DOWNLOAD_URL = "http://dummy.mozilla.org/dummy.pdf";
 
-// Add your tests here.  Each is a function that's called by testHelper().
-var testCases = [
+let gLibrary;
+
+let testCases = [
+  function allBookmarksScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
+    search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for All Bookmarks");
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for All Bookmarks");
+    resetSearch("scopeBarAll");
+  },
 
-  // All Bookmarks
-  function () {
-    var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
-    search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), false,
-       "Folder scope should be disabled for All Bookmarks");
+  function historyScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
+    search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for History");
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for History");
+    resetSearch("scopeBarAll");
+  },
+
+  function downloadsScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["Downloads"]);
+    search(PlacesUIUtils.leftPaneQueries["Downloads"], "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for Downloads");
+    ok(!selectScope("scopeBarAll"),
+       "Bookmarks scope should be disabled for Downloads");
     resetSearch(defScope);
   },
 
-  // History
-  function () {
-    var defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
-    search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
-    is(selectScope("scopeBarFolder"), false,
-       "Folder scope should be disabled for History");
-    resetSearch(defScope);
-  },
-
-  // Toolbar folder
-  function () {
-    var defScope = getDefaultScope(bmsvc.toolbarFolder);
-    search(bmsvc.toolbarFolder, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), true,
+  function toolbarFolderScope() {
+    let defScope = getDefaultScope(PlacesUtils.toolbarFolderId);
+    search(PlacesUtils.toolbarFolderId, "dummy", defScope);
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for toolbar folder");
+    ok(selectScope("scopeBarFolder"),
        "Folder scope should be enabled for toolbar folder");
     // Ensure that folder scope is still selected after resetting and searching
     // again.
     resetSearch("scopeBarFolder");
-    search(bmsvc.toolbarFolder, "dummy", "scopeBarFolder");
+    search(PlacesUtils.toolbarFolderId, "dummy", "scopeBarFolder");
   },
 
-  // A regular non-root subfolder
-  function () {
-    var folderId = bmsvc.createFolder(bmsvc.toolbarFolder,
-                                      "dummy folder",
-                                      bmsvc.DEFAULT_INDEX);
-    var defScope = getDefaultScope(folderId);
+  function subFolderScope() {
+    let folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
+                                                      "dummy folder",
+                                                      PlacesUtils.bookmarks.DEFAULT_INDEX);
+    let defScope = getDefaultScope(folderId);
     search(folderId, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), true,
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for regularfolder");
+    ok(selectScope("scopeBarFolder"),
        "Folder scope should be enabled for regular subfolder");
     // Ensure that folder scope is still selected after resetting and searching
     // again.
     resetSearch("scopeBarFolder");
     search(folderId, "dummy", "scopeBarFolder");
-    bmsvc.removeItem(folderId);
+    PlacesUtils.bookmarks.removeItem(folderId);
   },
 ];
 
 ///////////////////////////////////////////////////////////////////////////////
 
-var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-              getService(Ci.nsINavBookmarksService);
-var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
-                getService(Ci.nsINavHistoryService);
-var libraryWin;
-
-///////////////////////////////////////////////////////////////////////////////
-
 /**
  * Returns the default search scope for a given folder.
  *
  * @param  aFolderId
  *         the item ID of a node in the left pane's tree
  * @return the default scope when the folder is newly selected
  */
 function getDefaultScope(aFolderId) {
-  return aFolderId === PlacesUIUtils.leftPaneQueries["History"] ?
-         "scopeBarHistory" :
-         "scopeBarAll";
+  switch (aFolderId) {
+    case PlacesUIUtils.leftPaneQueries["History"]:
+      return "scopeBarHistory"
+    case PlacesUIUtils.leftPaneQueries["Downloads"]:
+      return "scopeBarDownloads";
+    default:
+      return "scopeBarAll";
+  }
 }
 
 /**
  * Returns the ID of the search scope button that is currently checked.
  *
  * @return the ID of the selected scope folder button
  */
 function getSelectedScopeButtonId() {
-  var doc = libraryWin.document;
-  var scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
+  let doc = gLibrary.document;
+  let scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
   for (let i = 0; i < scopeButtons.length; i++) {
     if (scopeButtons[i].checked)
       return scopeButtons[i].id;
   }
   return null;
 }
 
 /**
  * Returns the single nsINavHistoryQuery represented by a given place URI.
  *
  * @param  aPlaceURI
  *         a URI that represents a single query
  * @return an nsINavHistoryQuery object
  */
 function queryStringToQuery(aPlaceURI) {
-  var queries = {};
-  histsvc.queryStringToQueries(aPlaceURI, queries, {}, {});
+  let queries = {};
+  PlacesUtils.history.queryStringToQueries(aPlaceURI, queries, {}, {});
   return queries.value[0];
 }
 
 /**
  * Resets the search by clearing the search box's text and ensures that the
  * search scope remains as expected.
  *
  * @param  aExpectedScopeButtonId
@@ -183,61 +195,76 @@ function resetSearch(aExpectedScopeButto
  * @param  aFolderId
  *         the item ID of a node in the left pane's tree
  * @param  aSearchStr
  *         the search text; may be empty to reset the search
  * @param  aExpectedScopeButtonId
  *         after searching the selected scope button should be this
  */
 function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
-  var doc = libraryWin.document;
-  var folderTree = doc.getElementById("placesList");
-  var contentTree = doc.getElementById("placeContent");
+  let doc = gLibrary.document;
+  let folderTree = doc.getElementById("placesList");
+  let contentTree = doc.getElementById("placeContent");
 
   // First, ensure that selecting the folder in the left pane updates the
   // content tree properly.
   if (aFolderId) {
     folderTree.selectItems([aFolderId]);
     isnot(folderTree.selectedNode, null,
        "Sanity check: left pane tree should have selection after selecting!");
 
     // getFolders() on a History query returns an empty array, so no use
     // comparing against aFolderId in that case.
-    if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"]) {
+    if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"] &&
+        aFolderId !== PlacesUIUtils.leftPaneQueries["Downloads"]) {
       // contentTree.place should be equal to contentTree.result.root.uri,
       // but it's not until bug 476952 is fixed.
-      var query = queryStringToQuery(contentTree.result.root.uri);
+      let query = queryStringToQuery(contentTree.result.root.uri);
       is(query.getFolders()[0], aFolderId,
          "Content tree's folder should be what was selected in the left pane");
     }
   }
 
   // Second, ensure that searching updates the content tree and search UI
   // properly.
-  var searchBox = doc.getElementById("searchFilter");
+  let searchBox = doc.getElementById("searchFilter");
   searchBox.value = aSearchStr;
-  libraryWin.PlacesSearchBox.search(searchBox.value);
-  query = queryStringToQuery(contentTree.result.root.uri);
+  gLibrary.PlacesSearchBox.search(searchBox.value);
+  let query = queryStringToQuery(contentTree.result.root.uri);
   if (aSearchStr) {
     is(query.searchTerms, aSearchStr,
        "Content tree's searchTerms should be text in search box");
     is(doc.getElementById("searchModifiers").hidden, false,
        "Scope bar should not be hidden after searching");
-    if (getSelectedScopeButtonId() == "scopeBarHistory" ||
-        getSelectedScopeButtonId() == "scopeBarAll" ||
-        aFolderId == PlacesUtils.bookmarks.unfiledBookmarksFolder) {
+
+    let scopeButtonId = getSelectedScopeButtonId();
+    if (scopeButtonId == "scopeBarDownloads" ||
+        scopeButtonId == "scopeBarHistory" ||
+        scopeButtonId == "scopeBarAll" ||
+        aFolderId == PlacesUtils.unfiledBookmarksFolderId) {
       // Check that the target node exists in the tree's search results.
-      var node = null;
-      for (var i = 0; i < contentTree.view.rowCount; i++) {
+      let url, count;
+      if (scopeButtonId == "scopeBarDownloads") {
+        url = TEST_DOWNLOAD_URL;
+        count = 1;
+      }
+      else {
+        url = TEST_URL;
+        count = scopeButtonId == "scopeBarHistory" ? 2 : 1;
+      }
+      is(contentTree.view.rowCount, count, "Found correct number of results");
+
+      let node = null;
+      for (let i = 0; i < contentTree.view.rowCount; i++) {
         node = contentTree.view.nodeForTreeIndex(i);
-        if (node.uri === TEST_URL)
+        if (node.uri === url)
           break;
       }
       isnot(node, null, "At least the target node should be in the tree");
-      is(node.uri, TEST_URL, "URI of node should match target URL");
+      is(node.uri, url, "URI of node should match target URL");
     }
   }
   else {
     is(query.hasSearchTerms, false,
        "Content tree's searchTerms should not exist after search reset");
     ok(doc.getElementById("searchModifiers").hidden,
        "Scope bar should be hidden after search reset");
   }
@@ -248,58 +275,58 @@ function search(aFolderId, aSearchStr, a
 /**
  * Clicks the given search scope button if it is enabled.
  *
  * @param  aScopeButtonId
  *         the button with this ID will be clicked
  * @return true if the button is enabled, false otherwise
  */
 function selectScope(aScopeButtonId) {
-  var doc = libraryWin.document;
-  var button = doc.getElementById(aScopeButtonId);
+  let doc = gLibrary.document;
+  let button = doc.getElementById(aScopeButtonId);
   isnot(button, null,
-     "Sanity check: scope button with ID " + aScopeButtonId + "should exist");
+     "Sanity check: scope button with ID " + aScopeButtonId + " should exist");
   // Bug 469436 may hide an inappropriate scope button instead of disabling it.
   if (button.disabled || button.hidden)
     return false;
   button.click();
   return true;
 }
 
 /**
  * test() contains window-launching boilerplate that calls this to really kick
  * things off.  Add functions to the testCases array, and this will call them.
- *
- * @param  aLibraryWin
- *         the Places Library window
  */
-function testHelper(aLibraryWin) {
-  libraryWin = aLibraryWin;
+function onLibraryAvailable() {
   testCases.forEach(function (aTest) aTest());
-  aLibraryWin.close();
+
+  gLibrary.close();
+  gLibrary = null;
 
   // Cleanup.
   PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
-  PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
-  PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
-
-  finish();
+  PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+  waitForClearHistory(finish);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 function test() {
   waitForExplicitFinish();
 
   // Sanity:
   ok(PlacesUtils, "PlacesUtils in context");
-  // Add a visit, a bookmark and a tag.
+
+  // Add visits, a bookmark and a tag.
   PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_URL),
                                Date.now() * 1000, null,
                                PlacesUtils.history.TRANSITION_TYPED, false, 0);
-  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.unfiledBookmarksFolder,
+  PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_DOWNLOAD_URL),
+                               Date.now() * 1000, null,
+                               PlacesUtils.history.TRANSITION_DOWNLOAD, false, 0);
+  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                        PlacesUtils._uri(TEST_URL),
                                        PlacesUtils.bookmarks.DEFAULT_INDEX,
                                        "dummy");
   PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
 
-  openLibrary(testHelper);
+  gLibrary = openLibrary(onLibraryAvailable);
 }
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -168,24 +168,16 @@ function test() {
     EventUtils.synthesizeMouse(aTree.body, x, y, {},
                                aTree.ownerDocument.defaultView);
   }
 
   function changeSidebarDirection(aDirection) {
     sidebar.contentDocument.documentElement.style.direction = aDirection;
   }
 
-  function waitForClearHistory(aCallback) {
-    Services.obs.addObserver(function(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(arguments.callee, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-      aCallback(aSubject, aTopic, aData);
-    }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
-    PlacesUtils.bhistory.removeAllPages();
-  }
-
   function runNextTest() {
     // Remove eventual tabs created by previous sub-tests.
     while (gBrowser.tabs.length > 1) {
       gBrowser.removeTab(gBrowser.tabContainer.lastChild);
     }
 
     if (tests.length == 0) {
       finish();
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -54,17 +54,17 @@ window.onload = function() {
 
   // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
   if (sessionData.value.charAt(0) == '(')
     sessionData.value = sessionData.value.slice(1, -1);
   try {
     gStateObject = JSON.parse(sessionData.value);
   }
   catch (exJSON) {
-    var s = new Cu.Sandbox("about:blank");
+    var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
     gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
     // If we couldn't parse the string with JSON.parse originally, make sure
     // that the value in the textbox will be parsable.
     sessionData.value = JSON.stringify(gStateObject);
   }
 
   // make sure the data is tracked to be restored in case of a subsequent crash
   var event = document.createEvent("UIEvents");
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -130,17 +130,17 @@ SessionStartup.prototype = {
     try {
       // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
       if (iniString.charAt(0) == '(')
         iniString = iniString.slice(1, -1);
       try {
         this._initialState = JSON.parse(iniString);
       }
       catch (exJSON) {
-        var s = new Cu.Sandbox("about:blank");
+        var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
         this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
       }
 
       // If this is a normal restore then throw away any previous session
       if (!doResumeSessionOnce)
         delete this._initialState.lastSessionState;
     }
     catch (ex) { debug("The session file is invalid: " + ex); }
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -4009,17 +4009,17 @@ SessionStoreService.prototype = {
     Services.obs.notifyObservers(null,
       this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
       "");
 
     this._browserSetState = false;
     this._restoreCount = -1;
   },
 
-  /**
+   /**
    * Set the given window's busy state
    * @param aWindow the window
    * @param aValue the window's busy state
    */
   _setWindowStateBusyValue:
     function sss__changeWindowStateBusyValue(aWindow, aValue) {
 
     this._windows[aWindow.__SSi].busy = aValue;
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -173,17 +173,18 @@ var Scratchpad = {
     }
 
     if (!this._contentSandbox ||
         this.browserWindow != this._previousBrowserWindow ||
         this._previousBrowser != this.gBrowser.selectedBrowser ||
         this._previousLocation != this.gBrowser.contentWindow.location.href) {
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
       this._contentSandbox = new Cu.Sandbox(contentWindow,
-        { sandboxPrototype: contentWindow, wantXrays: false });
+        { sandboxPrototype: contentWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-content'});
 
       this._previousBrowserWindow = this.browserWindow;
       this._previousBrowser = this.gBrowser.selectedBrowser;
       this._previousLocation = contentWindow.location.href;
     }
 
     return this._contentSandbox;
   },
@@ -206,17 +207,18 @@ var Scratchpad = {
       Cu.reportError(this.strings.
                      GetStringFromName("browserWindow.unavailable"));
       return;
     }
 
     if (!this._chromeSandbox ||
         this.browserWindow != this._previousBrowserWindow) {
       this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
-        { sandboxPrototype: this.browserWindow, wantXrays: false });
+        { sandboxPrototype: this.browserWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-chrome'});
 
       this._previousBrowserWindow = this.browserWindow;
     }
 
     return this._chromeSandbox;
   },
 
   /**
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -43,9 +43,9 @@ relativesrcdir = browser/devtools/source
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
 		browser_sourceeditor_initialization.js \
 
 libs:: $(_BROWSER_TEST_FILES)
-#	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
+++ b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
@@ -14,31 +14,25 @@ function test()
 {
   waitForExplicitFinish();
 
   const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
     "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
     " title='test for bug 660784' width='600' height='500'><hbox flex='1'/></window>";
   const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
-    gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
-
-    testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
-    testWin.addEventListener("load", initEditor, false);
-  }, true);
-
-  content.location = "data:text/html,<p>bug 660784 - test the SourceEditor";
-
+  testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
 }
 
 function initEditor()
 {
-  testWin.removeEventListener("load", initEditor, false);
   testDoc = testWin.document;
 
   let hbox = testDoc.querySelector("hbox");
 
   editor = new SourceEditor();
   let config = {
     showLineNumbers: true,
     placeholderText: "foobarbaz",
@@ -322,20 +316,17 @@ function editorLoaded()
 
   editor.destroy();
   ok(!editor.parentElement && !editor.editorElement, "destroy() works");
 
   testWin.close();
 
   testWin = testDoc = editor = null;
 
-  waitForFocus(function() {
-    gBrowser.removeCurrentTab();
-    finish();
-  }, content);
+  waitForFocus(finish, window);
 }
 
 function testBackspaceKey()
 {
   editor.setText("       a\n  b\n c");
   editor.setCaretOffset(7);
   EventUtils.synthesizeKey("VK_BACK_SPACE", {}, testWin);
   is(editor.getText(), "a\n  b\n c", "line outdented (Backspace)");
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -2703,16 +2703,22 @@ HUD_SERVICE.prototype =
       // This may be a view-source window or other type of non-browser window.
       return;
     }
 
     let gBrowser = xulWindow.gBrowser;
 
     let _browser = gBrowser.
       getBrowserForDocument(aContentWindow.top.document);
+
+    // ignore newly created documents that don't belong to a tab's browser
+    if (!_browser) {
+      return;
+    }
+
     let nBox = gBrowser.getNotificationBox(_browser);
     let nBoxId = nBox.getAttribute("id");
     let hudId = "hud_" + nBoxId;
     let windowUI = nBox.ownerDocument.getElementById("console_window_" + hudId);
     if (windowUI) {
       // The Web Console popup is already open, no need to continue.
       if (aContentWindow == aContentWindow.top) {
         let hud = this.hudReferences[hudId];
--- a/browser/devtools/webconsole/test/browser/Makefile.in
+++ b/browser/devtools/webconsole/test/browser/Makefile.in
@@ -139,16 +139,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_bug_642615_autocomplete.js \
 	browser_webconsole_bug_585991_autocomplete_popup.js \
 	browser_webconsole_bug_585991_autocomplete_keys.js \
 	browser_webconsole_bug_663443_panel_title.js \
 	browser_webconsole_bug_660806_history_nav.js \
 	browser_webconsole_bug_651501_document_body_autocomplete.js \
 	browser_webconsole_bug_653531_highlighter_console_helper.js \
 	browser_webconsole_bug_659907_console_dir.js \
+	browser_webconsole_bug_678816.js \
 	head.js \
 	$(NULL)
 
 _BROWSER_TEST_PAGES = \
 	test-console.html \
 	test-network.html \
 	test-network-request.html \
 	test-mutation.html \
@@ -207,16 +208,17 @@ include $(topsrcdir)/config/rules.mk
 	test-bug-618078-network-exceptions.html \
 	test-bug-630733-response-redirect-headers.sjs \
 	test-bug-621644-jsterm-dollar.html \
 	test-bug-632347-iterators-generators.html \
 	test-bug-585956-console-trace.html \
 	test-bug-644419-log-limits.html \
 	test-bug-632275-getters.html \
 	test-bug-646025-console-file-location.html \
+	test-bug-678816-content.js \
 	test-file-location.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 
 libs:: $(_BROWSER_TEST_PAGES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser/browser_webconsole_bug_678816.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
+const FRAME_SCRIPT_URI ="chrome://mochitests/content/browser/browser/devtools/webconsole/test/browser/test-bug-678816-content.js";
+
+let HUD;
+let outputItem;
+
+function tabLoad1(aEvent) {
+  browser.removeEventListener(aEvent.type, arguments.callee, true);
+
+  openConsole();
+  HUD = HUDService.getHudByWindow(content);
+
+  browser.addEventListener("load", tabLoad2, true);
+
+  // Reload so we get some output in the console.
+  browser.contentWindow.location.reload();
+}
+
+function tabLoad2(aEvent) {
+  browser.removeEventListener(aEvent.type, tabLoad2, true);
+
+  outputItem = HUD.outputNode.querySelector(".hud-networkinfo .hud-clickable");
+  ok(outputItem, "found a network message");
+  document.addEventListener("popupshown", networkPanelShown, false);
+
+  // Click the network message to open the network panel.
+  EventUtils.synthesizeMouseAtCenter(outputItem, {});
+}
+
+function networkPanelShown(aEvent) {
+  document.removeEventListener(aEvent.type, networkPanelShown, false);
+
+  executeSoon(function() {
+    aEvent.target.addEventListener("popuphidden", networkPanelHidden, false);
+    aEvent.target.hidePopup();
+  });
+}
+
+function networkPanelHidden(aEvent) {
+  this.removeEventListener(aEvent.type, networkPanelHidden, false);
+
+  is(HUD.contentWindow, browser.contentWindow,
+    "console has not been re-attached to the wrong window");
+
+  finishTest();
+}
+
+function test() {
+  messageManager.loadFrameScript(FRAME_SCRIPT_URI, true);
+
+  registerCleanupFunction(function () {
+    // There's no way to unload a frameScript so send a kill signal to
+    // unregister the frame script's webProgressListener
+    messageManager.sendAsyncMessage("bug-678816-kill-webProgressListener");
+  });
+
+  addTab(TEST_URI);
+  browser.addEventListener("load", tabLoad1, true);
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser/test-bug-678816-content.js
@@ -0,0 +1,28 @@
+(function () {
+  let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
+  let webProgress = ifaceReq.getInterface(Ci.nsIWebProgress);
+
+  let WebProgressListener = {
+    onStateChange: function WebProgressListener_onStateChange(
+      webProgress, request, flag, status) {
+
+      if (flag & Ci.nsIWebProgressListener.STATE_START &&
+          flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
+        // ensure the dom window is the top one
+        return (webProgress.DOMWindow.parent == webProgress.DOMWindow);
+      }
+    },
+
+    // ----------
+    // Implements progress listener interface.
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                           Ci.nsISupportsWeakReference])
+  };
+
+  // add web progress listener
+  webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
+
+  addMessageListener("bug-678816-kill-webProgressListener", function () {
+    webProgress.removeProgressListener(WebProgressListener);
+  });
+})();
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -37,16 +37,17 @@ view.sortBy.dateAdded.label=Sort by Adde
 view.sortBy.dateAdded.accesskey=e
 view.sortBy.lastModified.label=Sort by Last Modified
 view.sortBy.lastModified.accesskey=M
 view.sortBy.tags.label=Sort by Tags
 view.sortBy.tags.accesskey=T
 
 searchBookmarks=Search Bookmarks
 searchHistory=Search History
+searchDownloads=Search Downloads
 searchCurrentDefault=Search in '%S'
 findInPrefix=Find in '%S'…
 
 tabs.openWarningTitle=Confirm open
 tabs.openWarningMultipleBranded=You are about to open %S tabs.  This might slow down %S while the pages are loading.  Are you sure you want to continue?
 tabs.openButtonMultiple=Open tabs
 tabs.openWarningPromptMeBranded=Warn me when opening multiple tabs might slow down %S
 
--- a/browser/themes/gnomestripe/browser/inspector.css
+++ b/browser/themes/gnomestripe/browser/inspector.css
@@ -370,8 +370,31 @@ code {
   border-color: #3875d7;
   background-color: #3875d7;
   color: #FFFFFF !important;
 }
 
 .nodeBox.highlighted > .nodeLabel {
   border-color: #3875d7 !important;
 }
+
+.editingAttributeValue {
+  background-color: #492;
+}
+
+#attribute-editor {
+  visibility: hidden;
+  position: absolute;
+  z-index: 5000;
+  background-color: #fff;
+  border: 1px solid #000;
+}
+
+#attribute-editor.editing {
+  visibility: visible;
+}
+
+#attribute-editor-input {
+  border: none;
+  padding: 2px 5px;
+  font-family: Menlo, Andale Mono, monospace;
+  font-size: 11px;
+}
--- a/browser/themes/pinstripe/browser/inspector.css
+++ b/browser/themes/pinstripe/browser/inspector.css
@@ -358,8 +358,31 @@ code {
   border-color: #3875d7;
   background-color: #3875d7;
   color: #FFFFFF !important;
 }
 
 .nodeBox.highlighted > .nodeLabel {
   border-color: #3875d7 !important;
 }
+
+.editingAttributeValue {
+  background-color: #492;
+}
+
+#attribute-editor {
+  visibility: hidden;
+  position: absolute;
+  z-index: 5000;
+  background-color: #fff;
+  border: 1px solid #000;
+}
+
+#attribute-editor.editing {
+  visibility: visible;
+}
+
+#attribute-editor-input {
+  border: none;
+  padding: 2px 5px;
+  font-family: Menlo, Andale Mono, monospace;
+  font-size: 11px;
+}
--- a/browser/themes/winstripe/browser/inspector.css
+++ b/browser/themes/winstripe/browser/inspector.css
@@ -343,8 +343,30 @@ code {
 }
 
 .nodeBox.highlightOpen > .nodeLabel > .twisty,
 .nodeBox.open > .nodeLabel > .twisty
 {
   background-image: url("chrome://global/skin/tree/twisty-open.png") !important;
 }
 
+.editingAttributeValue {
+  background-color: #492;
+}
+
+#attribute-editor {
+  visibility: hidden;
+  position: absolute;
+  z-index: 5000;
+  background-color: #fff;
+  border: 1px solid #000;
+}
+
+#attribute-editor.editing {
+  visibility: visible;
+}
+
+#attribute-editor-input {
+  border: none;
+  padding: 2px 5px;
+  font-family: Menlo, Andale Mono, monospace;
+  font-size: 11px;
+}
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,38 +1,47 @@
 import subprocess
 from devicemanager import DeviceManager, DMError
 import re
 import os
 
 class DeviceManagerADB(DeviceManager):
 
-  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
+  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
+    if packageName == None:
+      if os.getenv('USER'):
+        packageName = 'org.mozilla.fennec_' + os.getenv('USER')
+      else:
+        packageName = 'org.mozilla.fennec_'
     self.Init(packageName)
 
   def Init(self, packageName):
     # Initialization code that may fail: Catch exceptions here to allow
     # successful initialization even if, for example, adb is not installed.
     try:
       root = self.getDeviceRoot()
       self.verifyPackage(packageName)
       self.tmpDir = root + "/tmp"
       if (not self.dirExists(self.tmpDir)):
         self.mkDir(self.tmpDir)
     except:
       self.packageName = None
       self.tmpDir = None
     try:
       # a test to see if we have root privs
-      self.checkCmd(["shell", "ls", "/sbin"])
+      files = self.listFiles("/data/data")
+      if (len(files) == 1):
+        if (files[0].find("Permission denied") != -1):
+          print "NOT running as root"
+          raise Exception("not running as root")
     except:
       try:
         self.checkCmd(["root"])
       except:
         print "restarting as root failed"
 
   # external function
   # returns:
@@ -93,17 +102,17 @@ class DeviceManagerADB(DeviceManager):
   #  failure: None
   def pushDir(self, localDir, remoteDir):
     # adb "push" accepts a directory as an argument, but if the directory
     # contains symbolic links, the links are pushed, rather than the linked
     # files; we push file-by-file to get around this limitation
     try:
       if (not self.dirExists(remoteDir)):
         self.mkDirs(remoteDir+"/x")
-      for root, dirs, files in os.walk(localDir):
+      for root, dirs, files in os.walk(localDir, followlinks='true'):
         relRoot = os.path.relpath(root, localDir)
         for file in files:
           localFile = os.path.join(root, file)
           remoteFile = remoteDir + "/"
           if (relRoot!="."):
             remoteFile = remoteFile + relRoot + "/"
           remoteFile = remoteFile + file
           self.pushFile(localFile, remoteFile)
@@ -129,18 +138,22 @@ class DeviceManagerADB(DeviceManager):
 
   # Because we always have / style paths we make this a lot easier with some
   # assumptions
   # external function
   # returns:
   #  success: True
   #  failure: False
   def fileExists(self, filepath):
-    self.checkCmd(["shell", "ls", filepath])
-    return True
+    p = self.runCmd(["shell", "ls", "-a", filepath])
+    data = p.stdout.readlines()
+    if (len(data) == 1):
+      if (data[0].rstrip() == filepath):
+        return True
+    return False
 
   def removeFile(self, filename):
     return self.runCmd(["shell", "rm", filename]).stdout.read()
 
   # does a recursive delete of directory on the device: rm -Rf remoteDir
   # external function
   # returns:
   #  success: output of telnet, i.e. "removing file: /mnt/sdcard/tests/test.txt"
@@ -376,28 +389,21 @@ class DeviceManagerADB(DeviceManager):
     devroot = self.getDeviceRoot()
     if (devroot == None):
       return None
 
     if (self.dirExists(devroot + '/fennec')):
       return devroot + '/fennec'
     elif (self.dirExists(devroot + '/firefox')):
       return devroot + '/firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec')):
-      return '/data/data/org.mozilla.fennec'
-    elif (self.dirExists('/data/data/org.mozilla.firefox')):
-      return '/data/data/org.mozilla.firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
-      return '/data/data/org.mozilla.fennec_unofficial'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
-      return '/data/data/org.mozilla.fennec_aurora'
-    elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
-      return '/data/data/org.mozilla.firefox_beta'
+    elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
+      return '/data/data/' + self.packageName
 
     # Failure (either not installed or not a recognized platform)
+    print "devicemanagerADB: getAppRoot failed"
     return None
 
   # Gets the directory location on the device for a specific test type
   # Type is one of: xpcshell|reftest|mochitest
   # external function
   # returns:
   #  success: path for test root
   #  failure: None
--- a/build/mobile/sutagent/android/watcher/WatcherService.java
+++ b/build/mobile/sutagent/android/watcher/WatcherService.java
@@ -102,17 +102,16 @@ public class WatcherService extends Serv
     private Method mStartForeground;
     private Method mStopForeground;
     private Object[] mSetForegroundArgs = new Object[1];
     private Object[] mStartForegroundArgs = new Object[2];
     private Object[] mStopForegroundArgs = new Object[1];
 
 
     private IWatcherService.Stub stub = new IWatcherService.Stub() {
-        @Override
         public int UpdateApplication(String sAppName, String sFileName, String sOutFile, int bReboot) throws RemoteException
             {
             return UpdtApp(sAppName, sFileName, sOutFile, bReboot);
             }
     };
 
     @Override
     public IBinder onBind(Intent arg0) {
@@ -869,17 +868,16 @@ public class WatcherService extends Serv
             runner = new Thread(this);
             msPkgName = sPkgName;
             msPkgFileName = sPkgFileName;
             msOutFile = sOutFile;
             mbReboot = bReboot;
             runner.start();
         }
 
-        @Override
         public void run() {
                bInstalling = true;
             UpdtApp(msPkgName, msPkgFileName, msOutFile, mbReboot);
                bInstalling = false;
         }
     }
 
     private class MyTime extends TimerTask
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1732,17 +1732,18 @@ nsScriptSecurityManager::CheckFunctionAc
     nsIPrincipal* subject =
         GetFunctionObjectPrincipal(aCx, (JSObject *)aFunObj, nsnull, &rv);
 
     // If subject is null, get a principal from the function object's scope.
     if (NS_SUCCEEDED(rv) && !subject)
     {
 #ifdef DEBUG
         {
-            JSFunction *fun = GET_FUNCTION_PRIVATE(cx, (JSObject *)aFunObj);
+            JS_ASSERT(JS_ObjectIsFunction(aCx, (JSObject *)aFunObj));
+            JSFunction *fun = (JSFunction *)JS_GetPrivate(aCx, (JSObject *)aFunObj);
             JSScript *script = JS_GetFunctionScript(aCx, fun);
 
             NS_ASSERTION(!script, "Null principal for non-native function!");
         }
 #endif
 
         subject = doGetObjectPrincipal((JSObject*)aFunObj);
     }
@@ -2213,17 +2214,17 @@ nsScriptSecurityManager::GetFunctionObje
     {
         // Protect against pseudo-functions (like SJOWs).
         nsIPrincipal *result = doGetObjectPrincipal(obj);
         if (!result)
             *rv = NS_ERROR_FAILURE;
         return result;
     }
 
-    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
+    JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
     JSScript *script = JS_GetFunctionScript(cx, fun);
 
     if (!script)
     {
         // A native function: skip it in order to find its scripted caller.
         return nsnull;
     }
 
@@ -2279,17 +2280,17 @@ nsScriptSecurityManager::GetFramePrincip
         return GetScriptPrincipal(cx, script, rv);
     }
 
     nsIPrincipal* result = GetFunctionObjectPrincipal(cx, obj, fp, rv);
 
 #ifdef DEBUG
     if (NS_SUCCEEDED(*rv) && !result)
     {
-        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
+        JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
         JSScript *script = JS_GetFunctionScript(cx, fun);
 
         NS_ASSERTION(!script, "Null principal for non-native function!");
     }
 #endif
 
     return result;
 }
--- a/client.mk
+++ b/client.mk
@@ -207,16 +207,17 @@ ifdef MOZ_OBJDIR
 else
   PGO_OBJDIR := $(TOPSRCDIR)
 endif
 
 profiledbuild::
 	$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1
 	$(MAKE) -C $(PGO_OBJDIR) package
 	OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT)
+	$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
 	$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1
 
 #####################################################
 # Build date unification
 
 ifdef MOZ_UNIFY_BDATE
 ifndef MOZ_BUILD_DATE
 ifdef MOZ_BUILD_PROJECTS
@@ -248,17 +249,17 @@ else
 	done
 endif
 endif
 
 # If we're building multiple projects, but haven't specified which project,
 # loop through them.
 
 ifeq (,$(MOZ_CURRENT_PROJECT)$(if $(MOZ_BUILD_PROJECTS),,1))
-configure depend realbuild install export libs clean realclean distclean alldep preflight postflight upload sdk::
+configure depend realbuild install export libs clean realclean distclean alldep preflight postflight maybe_clobber_profiledbuild upload sdk::
 	set -e; \
 	for app in $(MOZ_BUILD_PROJECTS); do \
 	  $(MAKE) -f $(TOPSRCDIR)/client.mk $@ MOZ_CURRENT_PROJECT=$$app; \
 	done
 
 else
 
 # MOZ_CURRENT_PROJECT: either doing a single-project build, or building an
@@ -348,17 +349,17 @@ endif
 realbuild::  $(OBJDIR)/Makefile $(OBJDIR)/config.status
 	@$(PYTHON) $(TOPSRCDIR)/js/src/config/check-sync-dirs.py $(TOPSRCDIR)/js/src/config $(TOPSRCDIR)/config
 	$(MOZ_MAKE)
 
 ####################################
 # Other targets
 
 # Pass these target onto the real build system
-install export libs clean realclean distclean alldep upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
+install export libs clean realclean distclean alldep maybe_clobber_profiledbuild upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
 	$(MOZ_MAKE) $@
 
 ####################################
 # Postflight
 
 realbuild alldep postflight::
 ifdef MOZ_POSTFLIGHT
 	set -e; \
@@ -407,9 +408,9 @@ cleansrcdir:
 echo-variable-%:
 	@echo $($*)
 
 # This makefile doesn't support parallel execution. It does pass
 # MOZ_MAKE_FLAGS to sub-make processes, so they will correctly execute
 # in parallel.
 .NOTPARALLEL:
 
-.PHONY: checkout real_checkout depend realbuild build profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk
+.PHONY: checkout real_checkout depend realbuild build profiledbuild maybe_clobber_profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -218,17 +218,16 @@ MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO
 MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@
 
 MOZ_BUILD_ROOT             = @MOZ_BUILD_ROOT@
 
 MOZ_XUL                    = @MOZ_XUL@
 MOZ_RDF                    = @MOZ_RDF@
 
 NECKO_PROTOCOLS = @NECKO_PROTOCOLS@
-NECKO_DISK_CACHE = @NECKO_DISK_CACHE@
 NECKO_COOKIES = @NECKO_COOKIES@
 NECKO_WIFI = @NECKO_WIFI@
 MOZ_AUTH_EXTENSION = @MOZ_AUTH_EXTENSION@
 
 MOZ_NATIVE_HUNSPELL = @SYSTEM_HUNSPELL@
 MOZ_HUNSPELL_LIBS = @MOZ_HUNSPELL_LIBS@
 MOZ_HUNSPELL_CFLAGS = @MOZ_HUNSPELL_CFLAGS@
 
deleted file mode 100644
--- a/config/gtscc.c
+++ /dev/null
@@ -1,2809 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* */
-/*
- *--------------------------------------------------------------------------
- *
- *    
- *
- *--------------------------------------------------------------------------
- *
- *    gtscc - Global To Static C/C++ compiler driver.
- *
- *    Syntax:
- *
- *    gtscc [options] -c file.cpp ...
- *    gtscc [options] file.o ... libxx.a ...
- *
- *    gtscc is a compiler and linker driver/wrapper for Irix only.
- *    gtscc takes all compiler options and passes them onto the Irix
- *    cc/CC compiler/linker.
- *    Typically, gtscc is used in two phases. Phase one is during compilation.
- *    gtscc, the compiler, converts all inline globals to statics, and records
- *    the existence of other globals and how to compile the file in the gtscc
- *    database file.
- *    During linking, globals dependencies are analyzed, and a list of
- *    "convertable" globals is determined. Globals that are not referenced
- *    globally, but are referenced locally are considered convertable.
- *    The linker then recompiles the files that those symbols are in, and
- *    converts them to statics. It also calls the archiver to install
- *    the converted objects into libraries.
- *    Finally the linker is called.
- *
- *    Created: David Williams, djw@netscape.com, 13-Feb-1997
- *
- *--------------------------------------------------------------------------
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#if defined(LINUX) && defined(__GLIBC__)
-#include <libelf/libelf.h>
-#else
-#include <libelf.h>
-#endif
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/time.h>
-
-#define DEFAULT_MAX_GLOBALS 15500
-
-#define ELFSYM_IS_DEFINED(x)   ((x).st_shndx != SHN_UNDEF)
-#define ELFSYM_IS_UNDEFINED(x) ((x).st_shndx == SHN_UNDEF)
-
-#ifdef IRIX
-#define CC_COMMAND  "cc"
-#define CCC_COMMAND "CC"
-#define AS_COMMAND  "cc"
-#define LD_COMMAND  "CC"
-#define AR_COMMAND  "ar"
-#define AR_OPTIONS  "cr"
-#else
-#define HANDLES_DASHSO
-#define CC_COMMAND  "gcc"
-#define CCC_COMMAND "g++"
-#define AS_COMMAND  "gcc"
-#define LD_COMMAND  "g++"
-#define AR_COMMAND  "ar"
-#define AR_OPTIONS  "cr"
-#endif
-
-#define EH_NEW(type) (type*)malloc(sizeof(type))
-
-#define TRUE 1
-#define FALSE 0
-
-#define EH_TAG_FILE   'F'
-#define EH_TAG_GLOBAL 'G'
-#define EH_TAG_ZAPPED 'Z'
-#define EH_TAG_INLINE 'I'
-#define EH_TAG_UNDEFINED 'U'
-
-#define VERBOSITY_USER(x)  ((x) > 0)
-#define VERBOSITY_DEBUG(x) ((x) > 1)
-#define VERBOSITY_MAJOR(x) ((x) > 2)
-
-static char eh_unnamed_object[] = "<name not known>";
-
-typedef struct {
-	char*    name;       /* archive */
-} EhArchive;
-
-typedef struct {
-	char*      name;     /* name of C/C++ file, relative to rootdir */
-	char*      directory;/* must compile in this directory */
-	char**     cc_args;  /* cc -I ..... */
-	char*      as_savefile;
-	time_t     compile_time;
-	char*      target_object;
-} EhSource;
-
-typedef struct EhObject {
-	struct EhObject* _recompile; /* used for recompilation link list */
-	unsigned   _needs_unzap;
-	char*      name;     /* name of .o */
-	EhArchive* archive;  /* it is stored in */
-	EhSource*  source;
-	char*      pathname;
-	unsigned   nusers;
-} EhObject;
-
-typedef enum {
-	EH_SYM_UNDEFINED,
-	EH_SYM_DEFINED,
-	EH_SYM_ZAPPED,
-	EH_SYM_INLINE /* are treated special - they belong to no file */
-} EhSymState;
-
-typedef struct EhSym {
-	struct EhSym* _next; /* used for link list */
-	char*      name;     /* name of symbol */
-	EhObject*  object;   /* if symbol is undefined == NULL */
-	unsigned   ngusers;   /* number of global users */
-	unsigned   nlusers;   /* number of local file users */
-
-#if 0
-	unsigned   section;  /* section in elf file */
-	unsigned   index;    /* index into symbol table */
-	unsigned char info;
-	unsigned   dirty;
-#endif
-	EhSymState state;
-} EhSym;
-
-#define EHSYM_ISDEFINED(x)   ((x)->object!=NULL && (x)->state==EH_SYM_DEFINED)
-#define EHSYM_ISZAPPED(x)    ((x)->object!=NULL && (x)->state==EH_SYM_ZAPPED)
-#define EHSYM_ISUNDEFINED(x) ((x)->object == NULL)
-#define EHSYM_ISUSED(x)      ((x)->nusers != 0)
-#define EHSYM_ISINLINE(x)    ((x)->state == EH_SYM_INLINE)
-
-#define EH_OBJECT_CANBUILD(x) \
-((x)->source != NULL && (x)->name != eh_unnamed_object)
-
-#define USE_HASHING
-
-typedef struct {
-#ifdef USE_HASHING
-	EhSym** heads;
-	unsigned size;
-#else
-	EhSym* head;
-#endif
-	unsigned nentries;
-} EhSymTable;
-
-static char*
-make_relative_pathname(char* buf, char* filename, char* rootdir)
-{
-	char  buf1[MAXPATHLEN];
-	char  buf2[MAXPATHLEN];
-	char* p;
-	char* q;
-
-	if (rootdir == NULL) {
-		strcpy(buf, filename);
-		return filename;
-	}
-
-	if (filename[0] != '/') {
-		if (getcwd(buf2, sizeof(buf2)) == NULL) {
-			fprintf(stderr, "cannot get pwd\n");
-			return NULL;
-		}
-
-		strcat(buf2, "/");
-		strcat(buf2, filename);
-
-		filename = buf2;
-	}
-
-	if (realpath(filename, buf1) == NULL) {
-		fprintf(stderr, "realpath(%s,..) failed\n", filename);
-		return NULL;
-	}
-	
-	if (realpath(rootdir, buf2) == NULL) {
-		fprintf(stderr, "realpath(%s,..) failed\n", rootdir);
-		return NULL;
-	}
-
-	strcat(buf2, "/");
-
-	for (p = buf1, q = buf2; *p == *q; p++, q++)
-		;
-
-	strcpy(buf, p);
-
-	return buf;
-}
-
-static EhArchive*
-EhArchiveNew(char* name, char* rootdir)
-{
-	EhArchive* archive = EH_NEW(EhArchive);
-	char pathbuf[MAXPATHLEN];
-
-	make_relative_pathname(pathbuf, name, rootdir);
-
-	archive->name = strdup(pathbuf);
-
-	return archive;
-}
-
-#if 0
-/*
- *    This is evil, we should never free anything, because it messes up
- *    interning.
- */
-static void
-EhSourceDelete(EhSource* source)
-{
-	unsigned n;
-	if (source->name != NULL)
-		free(source->name);
-	if (source->directory != NULL)
-		free(source->directory);
-	if (source->cc_args != NULL) {
-		for (n = 0; source->cc_args[n] != NULL; n++)
-			free(source->cc_args[n]);
-		free(source->cc_args);
-	}
-	if (source->as_savefile != NULL)
-		free(source->as_savefile);
-}
-#endif
-
-static EhSource*
-EhSourceNew(char* name, char** cc_args, char* directory)
-{
-	EhSource* source = EH_NEW(EhSource);
-	unsigned n;
-	unsigned m;
-
-	source->name = strdup(name);
-	source->directory = (directory != NULL)? strdup(directory): NULL;
-	source->as_savefile = NULL;
-	source->compile_time = 0;
-	source->target_object = NULL;
-	source->cc_args = NULL;
-
-	if (cc_args != NULL) {
-
-		for (n = 0; cc_args[n] != NULL; n++)
-			;
-
-		source->cc_args = (char**)malloc(sizeof(char*) * (n+1));
-
-		for (m = 0, n = 0; cc_args[n] != NULL;) {
-			if (strcmp(cc_args[n], "-o") == 0 && cc_args[n+1] != NULL) {
-				source->target_object = strdup(cc_args[n+1]);
-				n += 2;
-			} else {
-				source->cc_args[m++] =  strdup(cc_args[n++]);
-			}
-		}
-
-		source->cc_args[m] = NULL;
-	}
-
-	return source;
-}
-
-static EhObject*
-EhObjectNewArchiveObject(EhArchive* archive, char* name)
-{
-	EhObject* object = EH_NEW(EhObject);
-
-	if (name == eh_unnamed_object)
-		object->name = name;
-	else
-		object->name = strdup(name);
-	object->archive = archive;
-	object->source = NULL;
-	object->_recompile = NULL;
-	object->_needs_unzap = 0;
-	object->pathname = NULL;
-	object->nusers = 0;
-
-	return object;
-}
-
-static EhObject*
-EhObjectNew(char* name, char* rootdir)
-{
-	EhObject* object = EhObjectNewArchiveObject(NULL, name);
-	char pathname[MAXPATHLEN];
-
-	make_relative_pathname(pathname, name, rootdir);
-	object->pathname = strdup(pathname);
-
-	return object;
-}
-
-static EhObject*
-EhObjectNewFromSource(EhSource* source)
-{
-	EhObject* object = EhObjectNewArchiveObject(NULL, eh_unnamed_object);
-
-	object->source = source;
-
-	return object;
-}
-
-static char*
-EhObjectGetFilename(EhObject* object, char* buf)
-{
-	if (object->archive) {
-		strcpy(buf, object->archive->name);
-		strcat(buf, ":");
-		strcat(buf, object->name);
-		return buf;
-	} else {
-		return object->name;
-	}
-}
-
-static EhSym*
-EhSymNewDefined(char* name, EhObject* object)
-{
-	EhSym* sym = EH_NEW(EhSym);
-
-	sym->name = strdup(name);
-	sym->object = object;
-	sym->state = EH_SYM_DEFINED;
-	sym->ngusers = 0;
-	sym->nlusers = 0;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewInline(char* name)
-{
-	EhSym* sym = EhSymNewDefined(name, NULL);
-	sym->state = EH_SYM_INLINE;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewUndefined(char* name)
-{
-	EhSym* sym = EhSymNewDefined(name, NULL);
-	sym->state = EH_SYM_UNDEFINED;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewZapped(char* name, EhObject* object)
-{
-	EhSym* sym = EhSymNewDefined(name, object);
-	sym->state = EH_SYM_ZAPPED;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewRandomZap(char* name)
-{
-	EhSym* sym = EhSymNewZapped(name, NULL);
-
-	return sym;
-}
-
-EhSymTable*
-EhSymTableNew(unsigned p_size)
-{
-	EhSymTable* table = EH_NEW(EhSymTable);
-
-#ifdef USE_HASHING
-	unsigned size;
-	for (size = 0x1; size < (16*1024); size <<= 1) {
-		if (size >= p_size)
-			break;
-	}
-	table->size = size;
-	table->heads = (EhSym**)calloc(size, sizeof(EhSym*));
-#else
-	table->head = NULL;
-#endif
-	table->nentries = 0;
-
-	return table;
-}
-
-EhSym*
-EhSymTableInsert(EhSymTable* table, EhSym* sym)
-{
-#ifdef USE_HASHING
-	unsigned long hash = elf_hash(sym->name);
-	unsigned long mask = table->size - 1;
-	unsigned index = (hash & mask);
-
-	sym->_next = table->heads[index];
-	table->heads[index] = sym;
-#else
-	sym->_next = table->head;
-	table->head = sym;
-#endif
-	table->nentries++;
-
-	return sym;
-}
-
-EhSym*
-EhSymTableFind(EhSymTable* table, char* name)
-{
-	EhSym* sym;
-	EhSym* head;
-
-#ifdef USE_HASHING
-	unsigned long hash = elf_hash(name);
-	unsigned long mask = table->size - 1;
-	unsigned index = (hash & mask);
-	head = table->heads[index];
-#else
-	head = table->head;
-#endif
-
-	for (sym = head; sym != NULL; sym = sym->_next) {
-		if (strcmp(name, sym->name) == 0)
-			break;
-	}
-
-	return sym;
-}
-
-typedef int (*eh_dump_mappee_t)(EhSym* sym, void* arg);
-
-static int
-EhSymTableMap(EhSymTable* table, eh_dump_mappee_t func, void* arg)
-{
-	EhSym* sym;
-	EhSym* head;
-
-#ifdef USE_HASHING
-	unsigned n;
-	for (n = 0; n < table->size; n++) {
-		head = table->heads[n];
-#else
-		head = table->head; {
-#endif
-		for (sym = head; sym != NULL; sym = sym->_next) {
-			if ((func)(sym, arg) == -1)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-typedef struct {
-	EhObject* o_old;
-	EhObject* o_new;
-} fixup_info;
-
-static int
-fixup_mappee(EhSym* sym, void* arg)
-{
-	fixup_info* info = (fixup_info*)arg;
-
-	if (sym->object == info->o_old)
-		sym->object = info->o_new;
-
-	return 0;
-}
-
-static EhObject*
-EhSymTableObjectFixup(EhSymTable* table, EhObject* o_old, EhObject* o_new)
-{
-	fixup_info info;
-
-	/*
-	 *    Now visit every sym that pointed to tmp, and point it
-	 *    at object.
-	 */
-	info.o_old = o_old;
-	info.o_new = o_new;
-	EhSymTableMap(table, fixup_mappee, &info);
-	
-	return o_new;
-}
-
-
-
-static char*
-safe_fgets(char* buf, unsigned size, FILE* fp)
-{
-	unsigned nread = 0;
-
-	if (buf == NULL)
-		buf = (char*)malloc(size);
-
-	for (;;) {
-
-		if (fgets(&buf[nread], size - nread, fp) == NULL) {
-			free(buf);
-			return NULL;
-		}
-
-		if (strchr(buf, '\n') != NULL)
-			return buf;
-
-		/*
-		 *    fgets returns n-1 characters and \0
-		 */
-		nread += (size - nread) - 1;
-		size += 1024;
-		buf = (char*)realloc(buf, size);
-	}
-}
-
-static int
-EhSymTableSetSymbolState(EhSymTable* table, char* name, EhSymState new_state)
-{
-	EhSym* sym = EhSymTableFind(table, name);
-
-	if (sym == NULL) {
-		sym = EhSymNewDefined(name, NULL);
-
-		EhSymTableInsert(table, sym);
-	}
-
-	/* new_state must be EH_SYM_DEFINED || EH_SYM_ZAPPED */
-	if (sym->state == EH_SYM_DEFINED || sym->state == EH_SYM_ZAPPED) {
-		sym->state = new_state;
-	} else if (sym->state == EH_SYM_INLINE) {
-		char* state_name;
-		if (new_state == EH_SYM_DEFINED)
-			state_name = "global";
-		else
-			state_name = "static";
-		fprintf(stderr,
-				"WARNING: Symbol %s is an inline.\n"
-				"         Forcing the symbol %s will be ignored.\n",
-				name,
-				state_name);
-	} else { /* EH_SYM_UNDEFINED */
-		/*
-		 *    This call is being made after objects have started being
-		 *    read. This is too late. I'm not sure I care though.
-		 */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-EhSymTableFpLoad(EhSymTable* table, FILE* fp)
-{
-	char* buf = NULL; /* I hope this is big enough */
-	char* p;
-	char* name;
-	char* state;
-	EhSym* sym;
-	EhSource* source = NULL;
-	EhObject* object = NULL;
-	char* cc_args[512];
-	unsigned n;
-	unsigned line_n = 0;
-	char* ctime = NULL;
-	char* directory;
-	char* savefile;
-
-	while ((buf = safe_fgets(buf, 1024, fp)) != NULL) {
-
-		if ((p = strchr(buf, '\n')) == NULL) {
-			fprintf(stderr, "line to long: %d\n", line_n);
-			return -1;
-		}
-		*p = '\0';
-
-		line_n++;
-
-		if (buf[0] == '!') /* comment */
-			continue;
-
-		for (p = buf; isspace(*p); p++)
-			;
-
-		name = p;
-		for (; !isspace(*p); p++)
-			;
-		*p++ = '\0';
-
-		if (name[0] == '\0')
-			continue;
-		
-		for (; isspace(*p); p++)
-			;
-
-		state = p;
-		for (; !isspace(*p) && *p != '\0'; p++)
-			;
-		*p++ = '\0';
-
-		if (state[0] == EH_TAG_GLOBAL
-			||
-			state[0] == EH_TAG_ZAPPED
-			||
-			state[0] == EH_TAG_INLINE) {
-			sym = EhSymTableFind(table, name);
-			if (sym == NULL) { /* install a new one */
-				
-				if (source == NULL && state[0] != EH_TAG_INLINE) {
-					fprintf(stderr,
-							"[%d] found new style symbol (%s) but no source\n",
-							line_n, name);
-				}
-
-				if (state[0] == EH_TAG_GLOBAL)
-					sym = EhSymNewDefined(name, object);
-				else if (state[0] == EH_TAG_INLINE)
-					sym = EhSymNewInline(name);
-				else
-					sym = EhSymNewZapped(name, object);
-				
-				EhSymTableInsert(table, sym);
-			} else {
-				if (state[0] == EH_TAG_GLOBAL) {
-					if (sym->state != EH_SYM_DEFINED) {
-						fprintf(stderr,
-								"out of sync defined symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_DEFINED;
-					}
-				} else if (state[0] == EH_TAG_INLINE) {
-					if (sym->state != EH_SYM_INLINE) {
-						fprintf(stderr,
-								"out of sync inlined symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_INLINE;
-					}
-				} else {
-					if (sym->state != EH_SYM_ZAPPED) {
-						fprintf(stderr,
-								"out of sync zapped symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_ZAPPED;
-					}
-				}
-
-#if 0
-				/* these are probably "special" symbols like .div */
-				if (sym->object != object) {
-					fprintf(stderr,
-							"out of sync object for symbol: %s, ignoring\n",
-							sym->name);
-				}
-#endif
-			}
-
-			continue; /* no more fields we care about */
-		} else if (state[0] == EH_TAG_FILE) {
-
-			directory = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			savefile = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			ctime = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			for (n = 0; *p != '\0';) {
-
-				for (; isspace(*p); p++)
-					;
-			
-				cc_args[n++] = p++;
-				
-				for (; !isspace(*p) && *p != '\0'; p++)
-					;
-				
-				if (*p == '\0')
-					break;
-
-				*p++ = '\0';
-			}
-			cc_args[n] = NULL;
-
-			if (strcmp(directory, ".") == 0)
-				directory = NULL;
-			source = EhSourceNew(name, cc_args, directory);
-			if (ctime != NULL)
-				source->compile_time = (time_t)atoi(ctime);
-			object = EhObjectNewFromSource(source);
-
-		} else { /* old style symbol list */
-			sym = EhSymTableFind(table, name);
-			if (sym != NULL) {
-				if (sym->state != EH_SYM_ZAPPED) {
-					fprintf(stderr,
-							"out of sync random zapped symbol: %s, fixing\n",
-							sym->name);
-					sym->state = EH_SYM_ZAPPED;
-				}
-			} else {
-				sym = EhSymNewRandomZap(name);
-			}
-		}
-	}
-
-	return line_n;
-}
-
-typedef struct {
-	EhSym**  vector;
-	unsigned index;
-} flush_info;
-
-static int
-flush_mappee(EhSym* sym, void* arg)
-{
-	flush_info* info = (flush_info*)arg;
-
-	if (sym->state == EH_SYM_INLINE
-		||
-		(sym->object != NULL && sym->state == EH_SYM_DEFINED)
-		||
-		(sym->object != NULL && sym->state == EH_SYM_ZAPPED)) {
-		if (info->vector != NULL)
-			info->vector[info->index] = sym;
-		info->index++;
-	}
-
-	return 0;
-}
-
-static  int
-flush_compare(const void* ap, const void* bp)
-{
-	EhSym** ax = (EhSym**)ap;
-	EhSym** bx = (EhSym**)bp;
-	EhSym* a = *ax;
-	EhSym* b = *bx;
-	EhObject* oa = a->object;
-	EhObject* ob = b->object;
-	int foo;
-
-	if (oa == NULL && ob != NULL)
-		return -1;
-	if (oa != NULL && ob == NULL)
-		return 1;
-	if (oa == NULL && ob == NULL) {
-		foo = strcmp(a->name, b->name);
-		if (foo < 0)
-			return -1;
-		else if (foo > 0)
-			return 1;
-		return 0;
-	}
-
-	if (oa->source == NULL && ob->source != NULL)
-		return -1;
-	if (oa->source != NULL && ob->source == NULL)
-		return 1;
-	if (oa->source == ob->source)
-		return 0;
-	if (oa->source < ob->source)
-		return -1;
-	if (oa->source > ob->source)
-		return 1;
-	foo = strcmp(a->name, b->name);
-	if (foo < 0)
-		return -1;
-	else if (foo > 0)
-		return 1;
-	return 0;
-}
-
-static void
-EhSourceFpWrite(EhSource* source, FILE* fp)
-{
-	unsigned n = 0;
-
-	fputs(source->name, fp);
-	fputc(' ', fp);
-	fputc(EH_TAG_FILE, fp);
-
-	fputc(' ', fp);
-	if (source->directory != NULL)
-		fprintf(fp, "%s", source->directory);
-	else
-		fputc('.', fp);
-	
-	fputc(' ', fp);
-	if (source->as_savefile != NULL)
-		fprintf(fp, "%s", source->as_savefile);
-	else
-		fputc('.', fp);
-	
-	fputc(' ', fp);
-	fprintf(fp, "%d", source->compile_time);
-
-	if (source->target_object != NULL) {
-		fputs(" -o ", fp);
-		fputs(source->target_object, fp);
-	}
-	
-	if (source->cc_args != NULL) {
-		for (n = 0; source->cc_args[n] != NULL; n++) {
-			fputc(' ', fp);
-			fputs(source->cc_args[n], fp);
-		}
-	}
-
-	if (n < 1)
-		fprintf(stderr, "WARNING: %s has no args\n", source->name);
-
-	fputc('\n', fp);
-}
-
-static int
-EhSymTableFpDump(EhSymTable* table, FILE* fp)
-{
-	flush_info info;
-	unsigned n;
-	EhObject* object = NULL;
-	EhSym**   syms;
-	EhSym*    sym;
-	unsigned size;
-
-	info.index = 0;
-	info.vector = NULL;
-	EhSymTableMap(table, flush_mappee, (void*)&info);
-	size = info.index;
-
-	syms = (EhSym**)malloc(sizeof(EhSym*) * size);
-	info.index = 0;
-	info.vector = syms;
-	EhSymTableMap(table, flush_mappee, (void*)&info);
-
-	/* sort */
-	qsort(syms, size, sizeof(EhSym*), flush_compare);
-
-	/* dump */
-	for (n = 0; n < size; n++) {
-		sym = syms[n];
-
-		if (sym->object != object) {
-			object = sym->object;
-
-			if (object->source != NULL) {
-				EhSourceFpWrite(object->source, fp);
-			}
-		}
-
-		if (sym->state == EH_SYM_INLINE) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_INLINE);
-		} else if (object->source != NULL && sym->state == EH_SYM_ZAPPED) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_ZAPPED);
-		} else if (object->source != NULL && sym->state == EH_SYM_DEFINED) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_GLOBAL);
-		}
-	}
-
-	free(syms);
-
-	return n;
-}
-
-int djw_debug;
-char* djw_test_name;
-
-int
-eh_process_object(Elf* elf, EhObject* object, EhSymTable* table)
-{
-	Elf32_Shdr *   shdr;
-	Elf32_Ehdr *   ehdr;
-	Elf_Scn * scn;
-	Elf_Data *     shstr_data;
-	Elf_Data*      sym_data = NULL;
-	Elf_Data*      str_data = NULL;
-	Elf_Data*      rel_data[4];
-	int            nrel_data = 0;
-	Elf32_Rel*     rel_entries;
-	Elf_Data*      rela_data[10];
-	int            nrela_data = 0;
-	Elf32_Rela*    rela_entries;
-	unsigned int   cnt;
-	Elf32_Sym* elf_sym;
-	int i;
-	int j;
-	int k;
-	char*  name;
-	EhSym* sym;
-	char buf[MAXPATHLEN];
-
-	/* Obtain the .shstrtab data buffer */
-	if (((ehdr = elf32_getehdr(elf)) == NULL) ||
-		((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
-		((shstr_data = elf_getdata(scn, NULL)) == NULL)) {
-		fprintf(stderr, "problems on %s\n", EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	/* get the string table */
-	for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) {
-		if ((shdr = elf32_getshdr(scn)) == NULL) {
-			fprintf(stderr, "problems on %s, section %d\n",
-					EhObjectGetFilename(object, buf), cnt);
-			return -1;
-		}
-
-#if 0
-		fprintf(stderr, "%s: section %d type %d name %s\n",
-				EhObjectGetFilename(object, buf),
-				cnt,
-				shdr->sh_type,
-				(char*)shstr_data->d_buf + shdr->sh_name);
-#endif
-
-		/*
-		 *    Get the string table.
-		 */
-		if (shdr->sh_type == SHT_STRTAB &&
-#ifdef sun
-			strcmp((char*)shstr_data->d_buf + shdr->sh_name, ".strtab") == 0 &&
-#endif
-			cnt != ehdr->e_shstrndx) {
-			if (str_data != NULL) {
-				fprintf(stderr, "multiple string tables for %s - bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			str_data = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_SYMTAB) { /* look into sym table */
-			if (sym_data != NULL) {
-				fprintf(stderr, "multiple symbol tables for %s - bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			sym_data = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_REL) { /* look into rel table */
-			if (nrel_data >= 4) {
-				fprintf(stderr, "too many relocation tables for %s bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			rel_data[nrel_data++] = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_RELA) { /* look into rela table */
-			if (nrela_data >= 10) {
-				fprintf(stderr, "too many RELA tables for %s bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			rela_data[nrela_data++] = elf_getdata(scn, NULL);
-		}
-	}
-
-	if (sym_data == NULL) {
-		fprintf(stderr, "could not load sym table for %s\n",
-				EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	if (str_data == NULL) {
-		fprintf(stderr, "could not load string table for %s\n",
-				EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	elf_sym = (Elf32_Sym*)sym_data->d_buf;
-
-	for (i = 0; i < (sym_data->d_size/sizeof(Elf32_Sym)); i++) {
-
-		/*
-		 *    We are only interested in globals.
-		 */
-		if (ELF32_ST_BIND(elf_sym[i].st_info) != STB_GLOBAL)
-			continue;
-		
-		name = (char *)str_data->d_buf + elf_sym[i].st_name;
-		
-		if (djw_test_name != NULL
-			&& strcmp(djw_test_name, name) == 0) {
-			printf("found %s\n", name);
-		}
-		
-		sym = EhSymTableFind(table, name);
-		
-		/*
-		 *    Treat inlines as non-globals
-		 */
-		if (sym != NULL && sym->state == EH_SYM_INLINE)
-			continue;
-		
-#if 0
-		printf("name = %s value = %d type = %d, info = %d,"
-			   " other = %d, size = %d\n",
-			   name,
-			   elf_sym[i].st_value,
-			   ELF32_ST_TYPE(elf_sym[i].st_info),
-			   elf_sym[i].st_info,
-			   elf_sym[i].st_other,
-			   elf_sym[i].st_size);
-#endif
-		
-		/* defined */
-		if (ELFSYM_IS_DEFINED(elf_sym[i])) {
-			
-			if (sym != NULL) {
-				
-				if (sym->object == NULL) { /* object undefined */
-					sym->object = object;
-				} else if (sym->object->name==eh_unnamed_object) {
-					
-					if (object->source != NULL
-						&&
-						object->source != sym->object->source) {
-						
-						fprintf(stderr,
-								"warning: symbol %s defined in more than one source file\n"
-								"last time: %s\n"
-								"this time: %s (ignored)\n",
-								sym->name,
-								object->source->name,
-								sym->object->source->name);
-					} else {
-						object->source = sym->object->source;
-						/*
-						 *    Do a global: sym->object = object;
-						 */
-						EhSymTableObjectFixup(table,
-											  sym->object, /*old*/
-											  object); /*new*/
-						
-					}
-					
-				} else if (sym->object != object) {
-					fprintf(stderr,
-							"warning: symbol %s define in multiple object files\n"
-							"last time: %s\n"
-							"this time: %s (ignored)\n",
-							sym->name,
-							object->name,
-							sym->object->name);
-				}
-				
-				sym->state = EH_SYM_DEFINED;
-
-			} else {
-				sym = EhSymNewDefined(name, object);
-				EhSymTableInsert(table, sym);
-			}				
-
-	        for (k = 0; k < nrel_data; k++) {
-				int nentries = rel_data[k]->d_size/sizeof(Elf32_Rel);
-
-				rel_entries = (Elf32_Rel*)rel_data[k]->d_buf;
-				
-				for (j = 0; j < nentries; j++) {
-					if (ELF32_R_SYM(rel_entries[j].r_info) == i) {
-						/* locally referenced */
-						sym->nlusers++;
-					}
-				}
-			}
-	        for (k = 0; k < nrela_data; k++) {
-				int nentries = rela_data[k]->d_size/sizeof(Elf32_Rela);
-
-				rela_entries = (Elf32_Rela*)rela_data[k]->d_buf;
-				
-				for (j = 0; j < nentries; j++) {
-					if (ELF32_R_SYM(rela_entries[j].r_info) == i) {
-						/* locally referenced */
-						sym->nlusers++;
-					}
-				}
-			}
-		}  
-		
-		/* Undefined. */
-		else if (ELFSYM_IS_UNDEFINED(elf_sym[i])) {
-			
-			if (sym == NULL) {
-				sym = EhSymNewUndefined(name);
-				EhSymTableInsert(table, sym);
-			}
-			sym->ngusers++;
-		} else {
-			
-#if 1
-			printf("what is this: "
-				   "name = %s value = %d type = %d, "
-				   "info = %d, other = %d, size = %d\n",
-				   name,
-				   elf_sym[i].st_value,
-				   ELF32_ST_TYPE(elf_sym[i].st_info),
-				   elf_sym[i].st_info,
-				   elf_sym[i].st_other,
-				   elf_sym[i].st_size);
-#endif
-			;
-		}/* type ==... */
-	} /* for each symbol */
-
-	return 0;
-}
-
-int
-eh_process_file(char* filename, EhSymTable* table, char* rootdir)
-{
-	Elf* elf;
-	Elf* arf;
-	int  fd;
-	Elf_Cmd cmd;
-	Elf_Kind e_kind;
-	EhObject* object;
-	EhArchive* archive;
-	Elf_Arhdr* arhdr;
-	char* name;
-	int   rv = 0;
-
-	if ((fd = open(filename, O_RDONLY)) == -1) {
-		fprintf(stderr, "error opening %s\n", filename);
-		return -1;
-	}
-
-	elf_version(EV_CURRENT);
-	if ((arf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
-		return -1;
-	}
-
-	e_kind = elf_kind(arf);
-	if (e_kind == ELF_K_ELF) {
-		object = EhObjectNew(filename, rootdir);
-		rv = eh_process_object(arf, object, table);
-		
-	} else if (e_kind == ELF_K_AR) {
-
-		archive = EhArchiveNew(filename, rootdir);
-		cmd = ELF_C_READ;
-
-#if 0
-		arsyms = elf_getarsym(arf, &narsyms);
-
-		for (i = 0; i < narsyms && arsyms[i].as_name != NULL; i++) {
-			printf("%s - %d\n", arsyms[i].as_name, arsyms[i].as_off);
-		}
-
-		arhdr = elf_getarhdr(arf);
-		for (i = 0; arhdr[i].ar_rawname != NULL; i++) {
-
-			if (arhdr[i].ar_name != NULL)
-				printf("%s\n", arhdr[i].ar_name);
-			else
-				printf("[%s]\n", arhdr[i].ar_rawname);
-		}
-#endif
-
-		rv = 0;
-
-		while ((elf = elf_begin(fd, cmd, arf)) != 0) {
-
-			e_kind = elf_kind(elf);
-
-			if (e_kind != ELF_K_ELF)
-				continue;
-
-			arhdr = elf_getarhdr(elf);
-
-			if (arhdr != NULL) {
-				if (arhdr->ar_name != NULL)
-					name = arhdr->ar_name;
-				else
-					name = arhdr->ar_rawname;
-			} else {
-				name = eh_unnamed_object;
-			}
-
-			object = EhObjectNewArchiveObject(archive, name);
-			rv = eh_process_object(elf, object, table);
-
-			if (rv == -1)
-				break;
-
-			cmd = elf_next(elf);
-			elf_end(elf);
-		}
-	}
-
-	elf_end(arf);
-
-	close(fd);
-
-	return rv;
-}
-
-static int
-eh_dump_unused(EhSym* sym, void* arg)
-{
-	char buf[MAXPATHLEN];
-
-	printf(/*"0x%x "*/ "%s %d %d ", /*sym,*/
-		   sym->name, sym->ngusers, sym->nlusers);
-
-	if (EHSYM_ISINLINE(sym))
-		printf("%c ", EH_TAG_INLINE);
-	else if (EHSYM_ISZAPPED(sym))
-		printf("%c ", EH_TAG_ZAPPED);
-	else if (EHSYM_ISDEFINED(sym))
-		printf("%c ", EH_TAG_GLOBAL);
-	else
-		printf("%c ", EH_TAG_UNDEFINED);
-
-	if (sym->object != NULL) {
-		printf("%s ", EhObjectGetFilename(sym->object, buf));
-		if (sym->object->source != NULL) {
-			printf("%s recompilable\n", sym->object->source->name);
-		} else {
-			printf("nosource notrecompilable\n");
-		}
-	} else {
-		printf("noobject nosource notrecompilable\n");
-	}
-	
-	return 0;
-}
-
-static void
-print_dump(EhSymTable* table)
-{
-	printf("everything\n");
-	EhSymTableMap(table, eh_dump_unused, NULL);
-}
-
-typedef struct {
-	unsigned ndefined;
-	unsigned nused; /* globally */
-	unsigned nundefined;
-	unsigned nzapped;
-	unsigned nzapped_nowused;
-	unsigned ninlined;
-	unsigned nunlinked;
-	unsigned ndeadcode;
-} SummaryInfo;
-
-static int
-eh_summary_mappee(EhSym* sym, void* arg) {
-	SummaryInfo* info = (SummaryInfo*)arg;
-
-	if (EHSYM_ISDEFINED(sym)) {
-		if (sym->ngusers != 0)
-			info->nused++;
-		else if (sym->object != NULL && sym->object->nusers == 0)
-			info->nunlinked++;
-		else if (sym->nlusers != 0)
-			info->ndefined++;
-		else
-			info->ndeadcode++;
-			
-	} else if (EHSYM_ISZAPPED(sym)) { /* one of ours */
-		if (sym->ngusers != 0)
-			info->nzapped_nowused++;
-		else
-			info->nzapped++;
-	} else if (EHSYM_ISINLINE(sym)) { /* one of ours */
-		info->ninlined++;
-	} else {
-		info->nundefined++;
-	}
-
-	return 0;
-}
-
-static void
-get_summary(EhSymTable* table, SummaryInfo* info)
-{
-	info->ndefined = 0;
-	info->nused = 0;
-	info->nundefined = 0;
-	info->nzapped = 0;
-	info->nzapped_nowused = 0;
-	info->ninlined = 0;
-	info->nunlinked = 0;
-	info->ndeadcode = 0;
-	
-	EhSymTableMap(table, eh_summary_mappee, info);
-} 
-
-static void
-print_summary(EhSymTable* table)
-{
-	SummaryInfo info;
-
-	get_summary(table, &info);
-	
-	printf("summary:\n"
-		   "defined and used:             %d\n"
-		   "defined but unused globally:  %d\n"
-		   "total globals in target:      %d\n"
-		   "--------------------------------\n"
-		   "global to statics *:          %d\n"
-		   "global to statics (now used): %d\n"
-		   "inlined to statics *:         %d\n"
-		   "defined in unlinked objects:  %d\n"
-		   "defined but unused (deadcode):%d\n"
-		   "undefined but used:           %d\n",
-		   info.nused,
-		   info.ndefined,
-		   (info.nused + info.ndefined),
-		   info.nzapped,
-		   info.nzapped_nowused,
-		   info.ninlined,
-		   info.nunlinked,			   
-		   info.ndeadcode,			   
-		   info.nundefined);
-}
-
-typedef struct EhDirMapEntree {
-	char* dirname;
-	struct EhDirMapEntree* _next;
-} EhDirMapEntree;
-
-typedef struct EhDirMap {
-	EhDirMapEntree* head;
-} EhDirMap;
-
-static EhDirMap*
-EhDirMapNew(void)
-{
-	EhDirMap* dm = EH_NEW(EhDirMap);
-	dm->head = NULL;
-	return dm;
-}
-
-static void
-EhDirMapAddDirectory(EhDirMap* map, char* dirname)
-{
-	EhDirMapEntree* entree = EH_NEW(EhDirMapEntree);
-	EhDirMapEntree* foo;
-
-	entree->dirname = strdup(dirname);
-	entree->_next = NULL;
-
-	if (map->head == NULL) {
-		map->head = entree;
-	} else {
-		for (foo = map->head; foo->_next != NULL; foo = foo->_next)
-			;
-
-		foo->_next = entree;
-	}
-}
-
-static char*
-EhDirMapGetLibName(EhDirMap* map, char* name, char* libbuf)
-{
-	EhDirMapEntree* foo;
-	struct stat     buf;
-
-	for (foo = map->head; foo != NULL; foo = foo->_next) {
-		sprintf(libbuf, "%s/lib%s.a", foo->dirname, name);
-
-		if (stat(libbuf, &buf) != -1)
-			return libbuf;
-	}
-
-	return NULL;
-}
-
-static char*
-test_for_global(char* buf)
-{
-#ifdef IRIX
-	if (strncmp(buf, "\t.globl\t", 8) == 0)
-		return &buf[8];
-#else
-	if (strncmp(buf, "\t.global ", 9) == 0)
-		return &buf[9];
-#endif
-	return NULL;
-}
-
-static char*
-test_for_file(char* foo, char* buf)
-{
-#ifdef IRIX
-	char* p;
-	char* q;
-	if (strncmp(buf, "\t.file\t", 6) == 0) {
-		for (p = &buf[6]; *p != '"' && *p != '\0'; p++)
-			;
-		if (*p == '\0')
-			return NULL;
-		p++; /* quote */
-		q = strchr(p, '"');
-		if (q == NULL)
-			return NULL;
-		memcpy(foo, p, q - p);
-		foo[q - p] = '\0';
-		return foo;
-	}
-#else
-	printf("test_for_file() not implemented\n");
-#endif
-	return NULL;
-}
-
-static int
-EhSourceZapFp(EhSource* source, EhSymTable* table, FILE* fpi, FILE* fpo,
-			  unsigned verbosity, unsigned cplusplus)
-{
-	char*     buf = NULL;
-	char*     p;
-	int       nzap = 0;
-	char*     name;
-	EhSym*    sym;
-	int       i_zapped;
-	EhObject* object = EhObjectNewFromSource(source);
-	char*     filename = source->name;
-	char*     tmp_name;
-	char      foo[256];
-	unsigned  line_n = 0;
-
-	if (VERBOSITY_DEBUG(verbosity))
-		fputs("gts: ", stderr);
-
-	while ((buf = safe_fgets(buf, 4192, fpi)) != NULL) {
-
-		i_zapped = 0;
-		for (p = buf; *p != '\0' && *p != '\n'; p++)
-			;
-		*p = '\0';
-
-		if ((tmp_name = test_for_file(foo, buf)) != NULL) {
-			if (strcmp(tmp_name, filename) != 0) /* not the same file */
-				filename = "non local file";
-			else
-				filename = source->name;
-		}
-
-		else if ((name = test_for_global(buf)) != NULL) {
-
-			sym = EhSymTableFind(table, name);
-
-			/* an inline, we have to treat specially */
-			if ((filename != source->name && cplusplus != 0) /* inline now */
-				||
-				(sym != NULL && sym->state == EH_SYM_INLINE)) {/* was inline */
-
-				if (!sym) { 
-
-					sym = EhSymNewInline(name);
-					
-					EhSymTableInsert(table, sym);
-				}
-				sym->state = EH_SYM_INLINE; /* just make sure */
-
-				if (fpo != NULL) /* always zap inlines we see */
-					fputs(" # gts", fpo);
-
-			} else { /* a real global */
-
-				if (fpo != NULL && sym != NULL && EHSYM_ISZAPPED(sym)) {
-					if (VERBOSITY_DEBUG(verbosity)) {
-						fprintf(stderr, "%s ", &buf[8]);
-					}
-					nzap++;
-
-					if (fpo != NULL)
-						fputs(" # gts", fpo);
-				}
-
-				if (sym != NULL) {
-					if (sym->object == NULL) {
-						sym->object = object;
-					} else if (sym->object != object) {
-						sym->object->source = source;
-						EhSymTableObjectFixup(table, object, sym->object);
-						object = sym->object;
-					}
-				} else { /* install a new one */
-					
-					sym = EhSymNewDefined(name, object);
-					
-					EhSymTableInsert(table, sym);
-				}
-
-			}
-		}
-
-		if (fpo != NULL) {
-			fputs(buf, fpo);
-			fputc('\n', fpo);
-		}
-		line_n++;
-	}
-	
-	if (VERBOSITY_DEBUG(verbosity))
-		fputc('\n', stderr);
-
-	return nzap;
-}
-
-static void
-print_command(char* command, char** args, unsigned verbosity)
-{
-	int i;
-	FILE* fp = stderr;
-	if (!VERBOSITY_USER(verbosity))
-		return;
-
-	fprintf(fp, "%s: ", command);
-	for (i = 0; args[i]; i++) {
-		fprintf(fp, "%s ", args[i]);
-	}
-	fprintf(fp, "\n");
-}
-
-static int
-do_command(char* label, char** args, unsigned verbosity)
-{
-	int status;
-	pid_t child_pid;
-	char* file = args[0];
-
-	print_command(label, args, verbosity);
-
-	if ((child_pid = fork()) == -1) {
-		fprintf(stderr, "could not fork: ");
-		perror(NULL);
-		return -1;
-	}
-
-	if (child_pid == 0) { /* i am the child */
-		if (execvp(file, args) == -1) {
-			fprintf(stderr, "could not exec %s: ", file);
-			perror(NULL);
-			exit(3);
-		}
-		/*NOTREACHED*/
-	}
-
-	if (waitpid(child_pid, &status, 0) == -1) {
-		fprintf(stderr, "wait on %s failed: ", file);
-		perror(NULL);
-		return -1;
-	}
-
-	return WEXITSTATUS(status);
-}
-
-static char*
-suffix_name(char* s)
-{
-	char* p;
-
-	if ((p = strrchr(s, '.')) != NULL)
-		return p;
-	else
-		return "";
-}
-
-static char base_name_buf[MAXPATHLEN];
-
-static char*
-base_name(char* s)
-{
-	char* p;
-
-	if ((p = strrchr(s, '.')) != NULL) {
-		memcpy(base_name_buf, s, p - s);
-		base_name_buf[p - s] = '\0';
-		s = base_name_buf;
-	}
-	return s;
-}
-
-static char*
-file_base_name(char *s)
-{
-	char* p;
-
-	s = base_name(s);
-
-	if ((p = strrchr(s, '/')) != NULL)
-		s = &p[1];
-	
-	return s;
-}
-static int
-EhSourceCompile(EhSource*   source,
-				EhSymTable* table,
-				unsigned    verbosity,
-				unsigned    do_compile,
-				unsigned    do_zap,
-				unsigned    do_assem)
-{
-	char* filename = source->name;
-	char** opts = source->cc_args;
-	char asname[MAXPATHLEN];
-	char o_asname[MAXPATHLEN];
-	char* cc_opts[256];
-	unsigned i = 0;
-	unsigned j = 0;
-	FILE* in_fp;
-	FILE* out_fp;
-	int   status;
-	int nzap = 0;
-	char* save_prefix = NULL;
-	unsigned do_dash_s = (do_zap != 0 || save_prefix != NULL);
-	char* cc_command;
-	char* use_savefile = NULL;
-	struct timeval start_time;
-	struct timeval end_time;
-#ifdef DEBUG_djw
-	char savebuf[1024];
-#endif
-	unsigned is_cplusplus = 0;
-
-#ifdef LINUX
-	gettimeofday(&start_time,NULL);
-#else
-	gettimeofday(&start_time);
-#endif
-
-	/* munge file */
-#ifdef HANDLES_DASHSO
-	if (source->target_object != NULL)
-		strcpy(asname, base_name(source->target_object));
-	else
-#endif
-		strcpy(asname, file_base_name(filename));
-	strcat(asname, ".s");
-
-	strcpy(o_asname, asname);
-	strcat(o_asname, ".gts_tmp");
-
-	if (strcmp(suffix_name(filename), ".cpp") == 0) {
-		cc_command = CCC_COMMAND;
-		is_cplusplus = 1;
-	} else if (strcmp(suffix_name(filename), ".s") == 0) {
-		do_compile = FALSE;
-		cc_command = CC_COMMAND;
-	} else {
-		cc_command = CC_COMMAND;
-	}
-
-	if (do_compile) {
-
-		j = 0;
-		cc_opts[j++] = cc_command;
-		cc_opts[j++] = "-c";
-
-		if (do_dash_s) {
-			cc_opts[j++] = "-S";
-#ifdef HANDLES_DASHSO
-			if (source->target_object != NULL) {
-				cc_opts[j++] = "-o";
-				cc_opts[j++] = asname;
-			}
-#endif
-		} else if (source->target_object != NULL) {
-			cc_opts[j++] = "-o";
-			cc_opts[j++] = source->target_object;
-		}
-		
-		i = 0;
-		while (opts[i] != NULL)
-			cc_opts[j++] = opts[i++];
-		
-		cc_opts[j++] = filename;
-		cc_opts[j] = NULL;
-		
-		if ((status = do_command("compile", cc_opts, verbosity)) != 0) {
-			fprintf(stderr, "compile failed (returned %d)\n", status);
-			return -1;
-		}
-
-		if (!do_dash_s)
-			return 0;
-	}
-
-	/*
-	 *    Now we have a foo.s file, what do we do with it?
-	 */
-	if (do_zap > 1) {
-
-		if (use_savefile == NULL)
-			use_savefile = asname;
-
-		if ((in_fp = fopen(use_savefile, "r")) == NULL) {
-			fprintf(stderr, "could not open %s for reading\n", asname);
-			return -1;
-		}
-	
-		if ((out_fp = fopen(o_asname, "w")) == NULL) {
-			fprintf(stderr, "could not open %s for writing\n", o_asname);
-			return -1;
-		}
-	
-		j = 0;
-		cc_opts[j++] = "gts";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = NULL;
-		print_command("gts", cc_opts, verbosity);
-
-		nzap = EhSourceZapFp(source, table, in_fp, out_fp, verbosity, is_cplusplus);
-
-		fclose(in_fp);
-		fclose(out_fp);
-
-		j = 0;
-		cc_opts[j++] = "rename";
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("rename", cc_opts, verbosity);
-
-#ifdef DEBUG_djw
-		strcpy(savebuf, "gts_pre_");
-		strcat(savebuf, asname);
-		rename(asname, savebuf);
-#endif
-
-		if (rename(o_asname, asname) == -1) {
-			fprintf(stderr, "could not rename %s\n", o_asname);
-			return -1;
-		}
-
-	} else if (do_zap > 0) { /* audit only */
-
-		if ((in_fp = fopen(asname, "r")) == NULL) {
-			fprintf(stderr, "could not open %s for reading\n", asname);
-			return -1;
-		}
-	
-		j = 0;
-		cc_opts[j++] = "audit";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("audit", cc_opts, verbosity);
-
-		nzap = EhSourceZapFp(source, table, in_fp, NULL, verbosity, is_cplusplus);
-
-		fclose(in_fp);
-	}
-
-	if (do_assem) {
-		i = 0;
-		j = 0;
-		cc_opts[j++] = AS_COMMAND;
-		cc_opts[j++] = "-c";
-
-		if (source->target_object != NULL) {
-			cc_opts[j++] = "-o";
-			cc_opts[j++] = source->target_object;
-		}
-
-		while (opts[i] != NULL)
-			cc_opts[j++] = opts[i++];
-
-		cc_opts[j++] = asname;
-		cc_opts[j] = NULL;
-
-		if ((status = do_command("assemble", cc_opts, verbosity)) != 0) {
-
-			unlink(asname);
-
-			fprintf(stderr,
-				"gtscc of %s failed (exit status = %d), reverting to %s:\n",
-					filename,
-					status,
-					cc_command);
-			
-			i = 0;
-			j = 0;
-			cc_opts[j++] = cc_command;
-			cc_opts[j++] = "-c";
-
-			if (source->target_object != NULL) {
-				cc_opts[j++] = "-o";
-				cc_opts[j++] = source->target_object;
-			}
-
-			for (; opts[i]; i++, j++)
-				cc_opts[j] = opts[i];
-			
-			cc_opts[j++] = filename;
-			cc_opts[j] = NULL;
-			
-			if ((status = do_command("fix-compile", cc_opts, verbosity)) != 0)
-				return -1;
-
-			return 0;
-		}
-	}
-
-	if (save_prefix != NULL && save_prefix[0] != '\0') {
-
-		sprintf(o_asname, save_prefix, file_base_name(filename));
-
-		j = 0;
-		cc_opts[j++] = "rename";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = NULL;
-		print_command("savefile", cc_opts, verbosity);
-
-		if (rename(asname, o_asname) == -1) {
-			fprintf(stderr, "could not rename %s to %s - sorry\n",
-					asname, o_asname);
-			return -1;
-		}
-
-		if (source->as_savefile != NULL)
-			free(source->as_savefile);
-		source->as_savefile = strdup(o_asname);
-	} else {
-
-		j = 0;
-		cc_opts[j++] = "unlink";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("unlink", cc_opts, verbosity);
-
-#ifdef DEBUG_djw
-		strcpy(savebuf, "gts_post_");
-		strcat(savebuf, asname);
-		rename(asname, savebuf);
-#else
-		unlink(asname);
-#endif
-	}
-
-#ifdef LINUX
-	gettimeofday(&end_time,NULL);
-#else
-	gettimeofday(&end_time);
-#endif
-
-	source->compile_time = ((end_time.tv_sec - start_time.tv_sec) * 1000) +
-                           ((end_time.tv_usec - start_time.tv_usec) / 1000);
-
-	return nzap;
-}
-
-static char target_buf[MAXPATHLEN]; /* this will go away with rel source */
-
-static char*
-EhSourceGetTarget(EhSource* source)
-{
-	if (source->target_object != NULL)
-		return source->target_object;
-
-	strcpy(target_buf, base_name(source->name));
-	strcat(target_buf, ".o");
-
-	return target_buf;
-}
-
-static int
-EhArchiveUpdate(EhArchive* archive, char* target, char* rootdir,
-				unsigned verbosity)
-{
-	char* args[8];
-	unsigned nargs;
-	int status;
-	char pathname[MAXPATHLEN];
-
-	pathname[0] = '\0';
-	if (rootdir != NULL) {
-		strcat(pathname, rootdir);
-		strcat(pathname, "/");
-	}
-	strcat(pathname, archive->name);
-
-#if 0
-	nargs = 0;
-	args[nargs++] = AR_COMMAND;
-	args[nargs++] = "dc";
-	args[nargs++] = pathname;
-	args[nargs++] = target;
-	args[nargs++] = NULL;
-	
-	if ((status = do_command("delete from archive", args, verbosity)) != 0) {
-		fprintf(stderr, "archive: %s delete %s failed (status = %d)\n",
-				pathname,
-				target);
-		return -1;
-	}
-#endif
-
-	nargs = 0;
-	args[nargs++] = AR_COMMAND;
-	args[nargs++] = AR_OPTIONS;
-	args[nargs++] = pathname;
-	args[nargs++] = target;
-	args[nargs++] = NULL;
-	
-	if ((status = do_command("archive", args, verbosity)) != 0) {
-		fprintf(stderr, "archive: %s <- %s failed (status = %d)\n",
-				pathname,
-				target);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-EhObjectRebuild(EhObject*   object,
-				EhSymTable* table,
-				unsigned    verbosity,
-				char*       rootdir)
-{
-	EhSource* source = object->source;
-	char  cwd[MAXPATHLEN];
-	char  fullpath[MAXPATHLEN];
-	int   rv = 0;
-	int   do_chdir = 0;
-
-	if (!source) {
-		fprintf(stderr,
-				"wanted to recompile %s, but I don't how\n",
-				object->name);
-		return -1;
-	}
-	
-#if 0
-	if (VERBOSITY_USER(verbosity))
-#endif
-		fprintf(stderr, "recompiling %s\n", source->name);
-	
-	/*
-	 *    Check to see if we need to chdir
-	 */
-	if (source->directory != NULL) {
-		if (getcwd(cwd, sizeof(cwd)) == NULL) {
-			fprintf(stderr, "cannot get pwd: cannot compile\n");
-			return -1;
-		}
-		
-		make_relative_pathname(fullpath, cwd, rootdir);
-		
-		if (strcmp(fullpath, source->directory) != 0) {
-			fullpath[0] = '\0';
-			if (rootdir != NULL) {
-				strcat(fullpath, rootdir);
-				strcat(fullpath, "/");
-			}
-			strcat(fullpath, source->directory);
-
-			if (chdir(fullpath) == -1) {
-				fprintf(stderr, "cannot chdir - can't compile\n");
-				return -1;
-			}
-			do_chdir++;
-		}
-	}
-
-	rv = EhSourceCompile(source,
-						 table,
-						 verbosity,
-						 TRUE,  /* compile  */
-						 2,     /* do zap   */
-						 TRUE); /* do assem */
-
-	if (do_chdir) {
-		if (chdir(cwd) == -1) {
-			fprintf(stderr, "cannot chdir - this will be very confused\n");
-			return -1;
-		}
-	}
-
-	if (rv == -1) {
-		fprintf(stderr, "recompiling %s failed\n",  source->name);
-		return -1;
-	}
-	
-	/* do archive */
-	fullpath[0] = '\0';
-	if (rootdir != NULL) {
-		strcat(fullpath, rootdir);
-		strcat(fullpath, "/");
-	}
-
-	if (source->directory != NULL)
-		strcat(fullpath, source->directory);
-
-	strcat(fullpath, "/");
-	strcat(fullpath, EhSourceGetTarget(source));
-	
-	if (object->archive != NULL) {
-		if (EhArchiveUpdate(object->archive, fullpath, rootdir,
-							verbosity) == -1)
-			return -1;
-	}
-
-	/* do install */
-#if 0
-	if (rv != -1) {
-	}
-#endif
-
-	return rv;
-}
-
-static int
-object_nusers_mappee(EhSym* sym, void* arg)
-{
-	if (sym->object != NULL)
-		sym->object->nusers += sym->ngusers;
-	return 0;
-}
-
-typedef struct {
-	EhObject* recompile_list;
-	unsigned  recompile_count;
-	unsigned  recompile_wish_count;
-	unsigned  unzap_count;
-	unsigned  zap_count;
-} RecompileInfo;
-
-static int
-recompile_init_mappee(EhSym* sym, void* arg)
-{
-	RecompileInfo* info = (RecompileInfo*)arg;
-
-	if (EHSYM_ISZAPPED(sym) && sym->ngusers != 0) {
-		if (EH_OBJECT_CANBUILD(sym->object)) {
-			sym->state = EH_SYM_DEFINED;
-			if (sym->object->_recompile == NULL) {
-				sym->object->_recompile = info->recompile_list;
-				info->recompile_list = sym->object;
-				info->recompile_count++;
-			}
-			info->unzap_count++;
-			sym->object->_needs_unzap++;
-		}
-		info->recompile_wish_count++;
-	}
-	else if (EHSYM_ISDEFINED(sym) /* it's defined */
-			 && sym->ngusers == 0 /* there are no global users */
-			 && sym->nlusers != 0 /* BUT, ther are local users */
-			 && sym->object->nusers != 0) { /* object is linked */
-
-		if (EH_OBJECT_CANBUILD(sym->object)) {
-			sym->state = EH_SYM_ZAPPED;
-			if (sym->object->_recompile == NULL) {
-				sym->object->_recompile = info->recompile_list;
-				info->recompile_list = sym->object;
-				info->recompile_count++;
-			}
-			info->zap_count++;
-		}
-		info->recompile_wish_count++;
-	}
-
-	return 0;
-}
-
-static char**    recompile_compare_prefs;
-static char**    recompile_compare_unprefs;
-
-static unsigned
-match_prefs(char* candidate, char** prefs)
-{
-	unsigned n;
-
-	for (n = 0; prefs[n] != NULL; n++) {
-		char*    pref = prefs[n];
-		unsigned len = strlen(pref);
-		if (strncmp(pref, candidate, len) == 0)
-			return n; /* cool */
-	}
-	return (unsigned)-1; /* big! */
-}
-
-static  int
-recompile_compare(const void* ap, const void* bp)
-{
-	EhObject** ax = (EhObject**)ap;
-	EhObject** bx = (EhObject**)bp;
-	EhObject*  obj_a = *ax;
-	EhObject*  obj_b = *bx;
-	EhSource*  src_a = obj_a->source;
-	EhSource*  src_b = obj_b->source;
-	unsigned   matcha;
-	unsigned   matchb;
-	int        foo;
-
-	if (obj_a->_needs_unzap == 0 && obj_b->_needs_unzap != 0)
-		return -1;
-	if (obj_a->_needs_unzap != 0 && obj_b->_needs_unzap == 0)
-		return 1;
-
-	if (src_a == NULL && src_b != NULL)
-		return 1;
-	if (src_a != NULL && src_b == NULL)
-		return -1;
-	if (src_a == src_b)
-		return 0;
-
-	if (recompile_compare_unprefs != NULL
-		&& src_a->directory != NULL && src_b->directory != NULL) {
-
-		matcha = match_prefs(src_a->directory, recompile_compare_unprefs);
-		matchb = match_prefs(src_b->directory, recompile_compare_unprefs);
-
-		if (matcha > matchb) /* greater is good */
-			return -1;
-		if (matcha < matchb)
-			return 1;
-	}
-
-	if (recompile_compare_prefs != NULL
-		&& src_a->directory != NULL && src_b->directory != NULL) {
-
-		matcha = match_prefs(src_a->directory, recompile_compare_prefs);
-		matchb = match_prefs(src_b->directory, recompile_compare_prefs);
-
-		if (matcha > matchb) /* greater is bad */
-			return 1;
-		if (matcha < matchb)
-			return -1;
-	}
-
-	/* else same directory probably */
-	foo = strcmp(src_a->name, src_b->name);
-
-	if (foo < 0)
-		return -1;
-	if (foo > 0)
-		return 1;
-
-	return 0;
-}
-
-static int
-do_recompilation(EhSymTable* table, char* gts_file, unsigned max_globals,
-				 char** prefs, char** unprefs,
-				 char* rootdir, unsigned verbosity)
-{
-	SummaryInfo s_info;
-	RecompileInfo info;
-	unsigned    size;
-	unsigned n;
-	EhObject* object;
-	EhObject** recompiles;
-	unsigned delta;
-	int rv;
-	unsigned nzaps;
-	EhObject dummy; /* just marks the end of the recomp list */
-	time_t  eta;
-
-	get_summary(table, &s_info);
-
-	if ((s_info.nused + s_info.ndefined) <= max_globals) {
-		if (VERBOSITY_USER(verbosity))
-			fprintf(stderr,
-			"number of globals <= requested max, skipping recompilation\n");
-		return 0;
-	}
-
-	/* Init recompilation. */
-	info.recompile_list = &dummy; /* cannot use NULL, because syms test that */
-	info.recompile_count = 0;
-	info.recompile_wish_count = 0;
-	info.unzap_count = 0;
-	info.zap_count = 0;
-	EhSymTableMap(table, recompile_init_mappee, (void*)&info);
-	size = info.recompile_count;
-
-	recompiles = (EhObject**)malloc(sizeof(EhObject*) * size);
-
-	/* install */
-	n = 0;
-	for (object = info.recompile_list;
-		 object != &dummy;
-		 object = object->_recompile) {
-		recompiles[n++] = object;
-	}
-
-	/* sort */
-	recompile_compare_prefs = prefs;
-	recompile_compare_unprefs = unprefs;
-	qsort(recompiles, size, sizeof(EhObject*), recompile_compare);
-
-	/*
-	 *    sorted !
-	 *    less recompile the first n, n = ndefined - max
-	 */
-	delta = (s_info.nused + s_info.ndefined) - max_globals;
-
-	if (delta > info.zap_count) {
-		fprintf(stderr,
-				"WARNING: there too many globals (%d/%d fixables).\n"
-				"         I don't think I can fix this, but I'll try.\n"
-				"         You might get lucky.\n",
-				info.zap_count,
-				delta);
-	}
-
-	if (VERBOSITY_USER(verbosity))
-		fprintf(stderr, "scheduling recompilation targets:\n");
-
-	eta = 0;
-	for (n = 0; n < size; n++) {
-		char* cname = "unknown";
-		object = recompiles[n];
-		if (object->source != NULL) {
-			cname = object->source->name;
-			eta += object->source->compile_time;
-		}
-		
-		if (VERBOSITY_DEBUG(verbosity))
-			fprintf(stderr, "object %s from source %s\n", object->name, cname);
-	}
-
-#if 0
-	if (VERBOSITY_USER(verbosity))
-#endif
-		fprintf(stderr, "gts-ing %d symbols, eta = %d minutes\n", delta,
-				eta/(60*1000));
-
-	if (gts_file != NULL) {
-		FILE* zap_fp;
-		if ((zap_fp = fopen(gts_file, "w")) == NULL) {
-			perror(0);
-			fprintf(stderr,
-					"WARNING: could not open the gtscc db file %s.\n"
-					"         I will continue with the recompilation, but\n"
-					"         if you recompile any of the files I touched\n"
-					"         I'll have to recompile them after you!\n",
-					gts_file);
-		} else {
-		
-			EhSymTableFpDump(table, zap_fp);
-			
-			fclose(zap_fp);
-		}
-	}
-
-	for (n = 0, nzaps = 0; n < size && nzaps < delta; n++) {
-
-		object = recompiles[n];
-		rv = EhObjectRebuild(object, table, verbosity, rootdir);
-
-		if (rv == -1)
-			return -1;
-
-		nzaps += rv;
-
-		object->_recompile = NULL; /* clean up now */
-	}
-
-	if (nzaps < delta) {
-		fprintf(stderr,
-				"WARNING: I wanted to gts %d symbols, but only managed\n"
-				"         to get %d of them.\n"
-				"         Your link may fail with GOT errors.\n",
-				delta,
-				nzaps);
-	}
-	
-	free(recompiles);
-
-	return n;
-}
-
-typedef struct FileList
-{
-	char*            name;
-	struct FileList* next;
-} FileList;
-
-static FileList*
-fileListFind(FileList* list, char* name)
-{
-	FileList* foo;
-
-	for (foo = list; foo != NULL; foo = foo->next) {
-		if (strcmp(name, foo->name) == 0)
-			return foo;
-	}
-	return NULL;
-}
-
-static FileList*
-fileListAppend(FileList** list_a, char* name)
-{
-	FileList* list = *list_a;
-	FileList* foo;
-	FileList* last;
-
-	for (foo = list, last = NULL; foo != NULL; last = foo, foo = foo->next)
-		;
-
-	if (last == NULL) {
-		foo = EH_NEW(FileList);
-		foo->next = NULL;
-		foo->name = strdup(name);
-		*list_a = foo;
-	} else {
-		foo = EH_NEW(FileList);
-		foo->next = NULL;
-		foo->name = strdup(name);
-		last->next = foo;
-	}
-
-	return *list_a;
-}
-
-#if 0
-static FileList* c_list;
-#endif
-static FileList* o_list;
-
-#if 0
-static char*
-EhSourceAdjustPathname(EhSource* source, char* rootdir)
-{
-	char buf[MAXPATHLEN];
-	char buf2[MAXPATHLEN];
-	char* p;
-	char* q;
-	char* filename = source->name;
-
-	if (getcwd(buf, sizeof(buf)) == NULL) {
-		fprintf(stderr, "cannot get pwd\n");
-		return NULL;
-	}
-
-	strcat(buf, "/");
-	strcat(buf, filename);
-
-	if (rootdir == NULL) {
-		filename = buf;
-	} else {
-		if (realpath(buf, buf2) == NULL) {
-			fprintf(stderr, "realpath() failed: %s\n", buf2);
-			return NULL;
-		}
-
-		if (realpath(rootdir, buf) == NULL) {
-			fprintf(stderr, "realpath() failed: %s\n", buf);
-			return NULL;
-		}
-		strcat(buf, "/"); 
-		
-		for (p = buf, q = buf2; *p == *q; p++, q++)
-			;
-
-		filename = q;
-	}
-
-	free(source->name);
-	source->name = strdup(filename);
-
-	return source->name;
-}
-#endif
-
-static unsigned
-katoi(char *buf)
-{
-	unsigned base = 1;
-	char* s;
-	
-	for (s = buf; isdigit(*s); s++)
-		;
-
-	if (*s == 'k' || *s == 'K')
-		base = 1024;
-
-	*s = '\0';
-
-	return base * atoi(buf);
-}
-
-static void
-usage(void)
-{
-	fprintf(stderr,
-			"Usage:\n"
-			"as a compiler:\n"
-			"gtscc [gtscc_options] [compiler_options] -c file.c file.cpp ...\n"
-			"gtscc_options:\n"
-			"-gtsfile <db.gts>       the gts database file (use this)\n"
-			"-gtszapsymbol <name>    convert symbol <name>\n"
-			"-gtsnozapsymbol <name>  don't convert symbol <name>\n"
-			"-gtsrootdir <directory> the root for the tree (use this)\n"
-			"-gtsverbose             be more verbose (3 levels)\n"
-			"-gtsnozap               don't convert globals to statics\n"
-			"-gtsnoupdate            don't update the database file\n"
-			"as a linker:\n"
-			"gtscc [gtscc_options] [linker_options] file.o ... libxx.a ...\n"
-			"gtscc_options:\n"
-			"-gtsfile <db.gts>       the gts database file (use this)\n"
-			"-gtszapsymbol <name>    convert symbol <name>\n"
-			"-gtsnozapsymbol <name>  don't convert symbol <name>\n"
-			"-gtsrootdir <directory> the root for the tree (use this)\n"
-			"-gtspref <directory>    please recompile these paths first\n"
-			"-gtsunpref <directory>  please try to avoid recompiling these\n"
-			"-gtsverbose             be more verbose (3 levels)\n"
-			"-gtssummary             print a summary of global usage\n"
-			"-gtsdump                print a detailed listing of all symbols\n"
-			"-gtsmaxglobals <number>[k] maximum globals allowed in target\n"
-			"-gtsnorecompile         don't do the normal recompilation\n"
-			"-gtsnolink              don't call linker after recompilation\n"
-			"-gtsnoupdate            don't update the database file\n"
-			"-help                   print this\n"
-	);
-}
-
-int
-main(int argc, char** argv)
-{
-	EhSymTable* table = EhSymTableNew(1000);
-	EhSym* sym;
-	FILE* zap_fp;
-	unsigned n = 0;
-	unsigned verbosity = 0;
-	char* arg_buf[256];
-	unsigned nargs = 0;
-	EhDirMap*   dmap = EhDirMapNew();
-	unsigned do_dump = 0;
-	unsigned do_summary = 0;
-	unsigned do_link = 1;
-	unsigned in_link = 1;
-	unsigned do_audit = 1;
-	unsigned do_zap = 1;
-	unsigned do_assem = 1;
-	unsigned do_recompile = 1;
-	unsigned do_collect = 1;
-	char* name;
-	char* saveprefix = NULL;
-	char* rootdir = NULL;
-	int rv;
-	EhSource* source = NULL;
-	char* gts_file = NULL;
-	char* path_prefs[32];
-	unsigned npath_prefs = 0;
-	char* path_un_prefs[32];
-	unsigned npath_un_prefs = 0;
-	char* suffix;
-	unsigned max_globals = DEFAULT_MAX_GLOBALS;
-	FileList* list;
-
-	if (elf_version(EV_CURRENT) == EV_NONE) {
-		fprintf(stderr, "something losing about your elf lib - sorry!\n");
-		return 3;
-		/* library out of date */
-		/* recover from error */
-	}
-
-	arg_buf[nargs] = NULL;
-
-	for (n = 1; n < argc; n++) {
-
-		if (strcmp(argv[n], "-help") == 0) {
-			usage();
-			return 0;
-		} else if (strcmp(argv[n], "-gtssummary") == 0) {
-			do_summary = 1;
-		} else if (strcmp(argv[n], "-gtsdump") == 0) {
-			do_dump = 1;
-		} else if (strcmp(argv[n], "-gtsnorecompile") == 0) {
-			do_recompile = 0;
-		} else if (strcmp(argv[n], "-gtsnolink") == 0) {
-			do_link = 0;
-		} else if (strcmp(argv[n], "-gtsverbose") == 0) {
-			verbosity++;
-		} else if (strcmp(argv[n], "-gtsnoupdate") == 0) {
-			do_collect = 0;
-		} else if (strcmp(argv[n], "-gtsnoaudit") == 0) {
-			do_audit = 0;
-		} else if (strcmp(argv[n], "-gtsnozap") == 0) {
-			do_zap = 0;
-		} else if (strcmp(argv[n], "-gtsrootdir") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsrootdir requires an argument\n");
-				usage();
-				return 2;
-			}
-			rootdir = argv[n+1];
-			n++;
-		} else if (strcmp(argv[n], "-gtsdebugsym") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsdebugsym requires an argument\n");
-				usage();
-				return 2;
-			}
-			djw_test_name = argv[n+1];
-			n++;
-		} else if (strcmp(argv[n], "-gtsmaxglobals") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsmaxglobals requires an argument\n");
-				usage();
-				return 2;
-			}
-			max_globals = katoi(argv[n+1]);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtspref") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtspref requires an argument\n");
-				usage();
-				return 2;
-			}
-			path_prefs[npath_prefs++] = argv[n+1];
-			path_prefs[npath_prefs] = NULL;
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsunpref") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsunpref requires an argument\n");
-				usage();
-				return 2;
-			}
-			path_un_prefs[npath_un_prefs++] = argv[n+1];
-			path_un_prefs[npath_un_prefs] = NULL;
-			n++;
-
-		} else if (strcmp(argv[n], "-gtssaveprefix") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtssaveprefix requires an argument\n");
-				usage();
-				return 2;
-			}
-			saveprefix = argv[n+1];
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsfile") == 0) {
-
-			struct stat sbuf;
-
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsfile requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			gts_file = argv[n+1];
-				
-			if (stat(gts_file, &sbuf) == -1) {
-				fprintf(stderr,
-						"warning: %s does not exist, will be created\n",
-						gts_file);
-			} else {
-				
-				if ((zap_fp = fopen(gts_file, "r")) == NULL) {
-					fprintf(stderr,	"you lose cannot open %s\n", gts_file);
-					usage();
-					return 2;
-				}
-
-				if (EhSymTableFpLoad(table, zap_fp) == -1) {
-					fprintf(stderr,
-							"error: failed reading symbols from gtsfile %s\n",
-							argv[n+1]);
-					usage();
-					return 2;
-				}
-				
-				fclose(zap_fp);
-			}
-
-			n++;
-
-		} else if (strcmp(argv[n], "-gtszapsymbol") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtszapsymbol requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_ZAPPED);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsnozapsymbol") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsnozapsymbol requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_DEFINED);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsname") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsname requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			sym = EhSymTableFind(table, argv[n+1]);
-			if (!sym)
-				sym = EhSymNewRandomZap(argv[n+1]);
-			n++;
-			do_audit = 1;
-
-		} else if (strcmp(argv[n], "-c") == 0) { /* do not link */
-			in_link = 0;
-			do_link = 0;
-		} else if (strcmp(argv[n], "-S") == 0) { /* do not assem */
-			do_assem = 0;
-		} else if (strcmp(argv[n], "-o") == 0) { /* parse through */
-			arg_buf[nargs++] = argv[n++];
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		} else if (strcmp((suffix = suffix_name(argv[n])), ".cpp") == 0
-				   ||
-				   strcmp(suffix, ".c") == 0
-				   ||
-				   strcmp(suffix, ".s") == 0) {
-			char pathname[MAXPATHLEN];
-
-			make_relative_pathname(pathname, ".", rootdir);
-
-			source = EhSourceNew(argv[n], arg_buf, pathname);
-
-			rv = EhSourceCompile(source,
-								 table,
-								 verbosity,
-								 TRUE, /* compile, .s files ignore anyway */
-								 (do_audit + do_zap),
-								 do_assem);
-			if (rv == -1)
-				return 1;
-
-#if 0
-			EhSourceAdjustPathname(source, rootdir);
-#endif
-
-		} else if (strcmp(suffix, ".o") == 0 || strcmp(suffix, ".a") == 0) {
-
-			if (fileListFind(o_list, argv[n]) == NULL) {
-				fileListAppend(&o_list, argv[n]);
-			} else {
-				fprintf(stderr,
-						"%s repeated on command line - ignored\n",
-						argv[n]);
-			}
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-
-		} else if (strncmp(argv[n], "-L", 2) == 0) {
-			EhDirMapAddDirectory(dmap, &argv[n][2]);
-		} else if (strncmp(argv[n], "-l", 2) == 0) {
-			char pathbuf[MAXPATHLEN];
-			name = EhDirMapGetLibName(dmap, &argv[n][2], pathbuf);
-			if (name != NULL) {
-				if (fileListFind(o_list, name) == NULL) {
-					fileListAppend(&o_list, name);
-				} else {
-					fprintf(stderr,
-							"%s repeated on command line - ignored\n",
-							name);
-				}
-			} else {
-				fprintf(stderr, 
-						"unable to resolve library reference %s - ignoring\n",
-						argv[n]);
-			}
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		} else {
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		}
-	}
-
-	/*
-	 *    Analyse objects.
-	 */
-	if (o_list != NULL) {
-		for (list = o_list; list != NULL; list = list->next) {
-
-			if (eh_process_file(list->name, table, rootdir)) {
-				fprintf(stderr, "oops we died around %s\n", list->name);
-				return 1;
-			}
-		}
-		
-		/* look for unused objects */
-		EhSymTableMap(table, object_nusers_mappee, 0);
-	}
-
-	if (do_summary) {
-		print_summary(table);
-	}
-
-	if (do_dump) {
-		print_dump(table);
-	}
-
-	if (!in_link && gts_file != NULL) {
-		FILE* zap_fp;
-		if ((zap_fp = fopen(gts_file, "w")) == NULL) {
-			perror(0);
-			usage();
-			return 2;
-		}
-
-		EhSymTableFpDump(table, zap_fp);
-		fclose(zap_fp);
-		return 0;
-	}
-
-	/*
-	 *    Now the fun really starts.
-	 */
-	if (do_recompile) {
-		char** pp = NULL;
-		char** up = NULL;
-		
-		if (npath_prefs > 0)
-			pp = path_prefs;
-		
-		if (npath_un_prefs > 0)
-			up = path_un_prefs;
-
-		if (!do_collect)
-			gts_file = NULL;
-		
-		rv = do_recompilation(table, gts_file, max_globals, pp, up, rootdir,
-							  verbosity);
-		if (rv == -1)
-			return 1;
-	}
-
-	/*
-	 *    Finally.
-	 */
-	if (do_link) {
-
-		int status;
-
-		arg_buf[nargs+1] = NULL;
-		for (n = nargs; n > 0; n--)
-			arg_buf[n] = arg_buf[n-1];
-		arg_buf[0] = LD_COMMAND;
-		
-		status = do_command("link", arg_buf, verbosity);
-
-		if (status == -1)
-			return 3;
-		else
-			return status;
-	}
-	
-	return 0;
-}
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -148,16 +148,30 @@ xpcshell-tests:
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
+
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
 # start the test. Instead, present the xpcshell prompt so the user can
 # attach a debugger and then start the test.
 check-interactive:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
@@ -177,16 +191,33 @@ check-one:
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+check-one-remote: DM_TRANS?=adb
+check-one-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(testxpcsrcdir)/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --test-path=$(SOLO_FILE) \
+	  --profile-name=$(MOZ_APP_NAME) \
+	  --verbose \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+          --noSetup \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 endif # XPCSHELL_TESTS
 
 ifdef CPP_UNIT_TESTS
 
 # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
 # through TestHarness.h, by modifying the list of includes and the libs against
 # which stuff links.
 CPPSRCS += $(CPP_UNIT_TESTS)
@@ -893,19 +924,16 @@ ifdef PROGRAM
 	$(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \
 	  $(PROGRAM:$(BIN_SUFFIX)=) $(DIST)/$(MOZ_APP_NAME)
 endif
 ifdef SHARED_LIBRARY
 	$(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \
 	  $(SHARED_LIBRARY_NAME) $(DIST)/$(MOZ_APP_NAME)
 endif
 endif # SHARED_LIBRARY || PROGRAM
-else  # ! WINNT_
-# Force rebuilding all objects on the second pass
-$(OBJS): FORCE
 endif # WINNT_
 endif # MOZ_PROFILE_USE
 ifdef MOZ_PROFILE_GENERATE
 # Clean up profiling data during PROFILE_GENERATE phase
 export::
 ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
 	-$(RM) *.pgd
 else
--- a/configure.in
+++ b/configure.in
@@ -965,16 +965,17 @@ if test -n "$_WIN32_MSVC"; then
     SKIP_COMPILER_CHECKS=1
     SKIP_LIBRARY_CHECKS=1
 
     # Since we're skipping compiler and library checks, hard-code
     # some facts here.
     AC_DEFINE(HAVE_IO_H)
     AC_DEFINE(HAVE_SETBUF)
     AC_DEFINE(HAVE_ISATTY)
+    AC_DEFINE(HAVE_STDCALL)
 fi
 
 fi # COMPILE_ENVIRONMENT
 
 AC_SUBST(MIDL_FLAGS)
 AC_SUBST(_MSC_VER)
 
 AC_SUBST(GNU_AS)
@@ -2102,16 +2103,18 @@ case "$target" in
     DSO_LDOPTS=''
     STRIP="$STRIP -x -S"
     _PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
     TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
     # The ExceptionHandling framework is needed for Objective-C exception
     # logging code in nsObjCExceptions.h. Currently we only use that in debug
     # builds.
     MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling"
+    # Debug builds should always have frame pointers
+    MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
 
     if test "x$lto_is_enabled" = "xyes"; then
         echo "Skipping -dead_strip because lto is enabled."
     dnl DTrace and -dead_strip don't interact well. See bug 403132.
     dnl ===================================================================
     elif test "x$enable_dtrace" = "xyes"; then
         echo "Skipping -dead_strip because DTrace is enabled. See bug 403132."
     else
@@ -2248,16 +2251,18 @@ ia64*-hpux*)
 
     MOZ_GFX_OPTIMIZE_MOBILE=1
     # If we're building with --enable-profiling, we need a frame pointer.
     if test -z "$MOZ_PROFILING"; then
         MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer"
     else
         MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer"
     fi
+    # Debug builds should always have frame pointers
+    MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
     ;;
 
 *-*linux*)
     # Note: both GNU_CC and INTEL_CC are set when using Intel's C compiler.
     # Similarly for GNU_CXX and INTEL_CXX.
     if test "$INTEL_CC" -o "$INTEL_CXX"; then
         # -Os has been broken on Intel's C/C++ compilers for quite a
         # while; Intel recommends against using it.
@@ -2273,17 +2278,18 @@ ia64*-hpux*)
         # If we're building with --enable-profiling, we need a frame pointer.
         if test -z "$MOZ_PROFILING"; then
             MOZ_FRAMEPTR_FLAGS="-fomit-frame-pointer"
         else
             MOZ_FRAMEPTR_FLAGS="-fno-omit-frame-pointer"
         fi
         MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
         MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
-        MOZ_DEBUG_FLAGS="-g"
+        # Debug builds should always have frame pointers
+        MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
     fi
 
     TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
 
     MOZ_MEMORY=1
 
     case "${target_cpu}" in
     alpha*)
@@ -2366,17 +2372,18 @@ ia64*-hpux*)
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
         CXXFLAGS="$CXXFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
         CXXFLAGS="$CXXFLAGS -wd4800" # disable warning "forcing value to bool"
         # make 'foo == bar;' error out
         CFLAGS="$CFLAGS -we4553"
         CXXFLAGS="$CXXFLAGS -we4553"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib"
-        MOZ_DEBUG_FLAGS='-Zi'
+        # Debug builds should always have frame pointers
+        MOZ_DEBUG_FLAGS='-Zi -Oy-'
         MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
         WARNINGS_AS_ERRORS='-WX'
         # If we're building with --enable-profiling, we need -Oy-, which forces a frame pointer.
         if test -z "$MOZ_PROFILING"; then
             MOZ_OPTIMIZE_FLAGS='-O1'
         else
             MOZ_OPTIMIZE_FLAGS='-O1 -Oy-'
         fi
@@ -3583,63 +3590,16 @@ then
 				CFLAGS="$CFLAGS -mt" 
 				CXXFLAGS="$CXXFLAGS -mt" 
 			fi
 			;;
 	esac
     LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}"
 fi
 
-dnl ========================================================
-dnl See if mmap sees writes
-dnl For cross compiling, just define it as no, which is a safe default
-dnl ========================================================
-AC_MSG_CHECKING(whether mmap() sees write()s)
-
-changequote(,)
-mmap_test_prog='
-    #include <stdlib.h>
-    #include <unistd.h>
-    #include <sys/mman.h>
-    #include <sys/types.h>
-    #include <sys/stat.h>
-    #include <fcntl.h>
-
-    char fname[] = "conftest.file";
-    char zbuff[1024]; /* Fractional page is probably worst case */
-
-    int main() {
-	char *map;
-	int fd;
-	int i;
-	unlink(fname);
-	fd = open(fname, O_RDWR | O_CREAT, 0660);
-	if(fd<0) return 1;
-	unlink(fname);
-	write(fd, zbuff, sizeof(zbuff));
-	lseek(fd, 0, SEEK_SET);
-	map = (char*)mmap(0, sizeof(zbuff), PROT_READ, MAP_SHARED, fd, 0);
-	if(map==(char*)-1) return 2;
-	for(i=0; fname[i]; i++) {
-	    int rc = write(fd, &fname[i], 1);
-	    if(map[i]!=fname[i]) return 4;
-	}
-	return 0;
-    }
-'
-changequote([,])
-
-AC_TRY_RUN($mmap_test_prog , result="yes", result="no", result="yes")
-
-AC_MSG_RESULT("$result")
-
-if test "$result" = "no"; then
-    AC_DEFINE(MMAP_MISSES_WRITES)
-fi
-
 
 dnl Checks for library functions.
 dnl ========================================================
 AC_PROG_GCC_TRADITIONAL
 AC_FUNC_MEMCMP
 AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat64 lstat64 truncate64 statvfs64 setbuf isatty)
 AC_CHECK_FUNCS(flockfile getpagesize)
 AC_CHECK_FUNCS(localtime_r strtok_r)
@@ -4773,17 +4733,16 @@ MOZ_XTF=1
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 MOZ_PDF_PRINTING=
 MOZ_DISABLE_DOMCRYPTO=
 NSS_DISABLE_DBM=
 NECKO_WIFI=1
 NECKO_COOKIES=1
-NECKO_DISK_CACHE=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 
 
 case "${target}" in
 *android*|*darwin*)
@@ -5189,30 +5148,31 @@ incorrect])
                       MOZ_ENABLE_QTNETWORK=)
 
     if test "$MOZ_ENABLE_QTNETWORK"; then
       MOZ_ENABLE_QTNETWORK=1
       AC_DEFINE(MOZ_ENABLE_QTNETWORK)
     fi
 
     MOZ_ENABLE_QTMOBILITY=
-    PKG_CHECK_MODULES(_QTMOBILITY, QtSensors QtFeedback,
+    PKG_CHECK_MODULES(_QTMOBILITY, QtSensors QtFeedback QtLocation,
                       MOZ_ENABLE_QTMOBILITY=1,
                       MOZ_ENABLE_QTMOBILITY=)
     if test "$MOZ_ENABLE_QTMOBILITY"; then
        MOZ_ENABLE_QTMOBILITY=1
        MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $_QTMOBILITY_CFLAGS"
        MOZ_QT_LIBS="$MOZ_QT_LIBS $_QTMOBILITY_LIBS"
     else
-       AC_CHECK_LIB(QtSensors QtFeedback, main, [
+       AC_CHECK_LIB(QtSensors QtFeedback QtLocation, main, [
           MOZ_ENABLE_QTMOBILITY=1
           MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtMobility"
           MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtSensors"
           MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtFeedback"
-          MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors -lQtFeedback"
+          MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtLocation"
+          MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors -lQtFeedback -lQtLocation"
        ])
     fi
     if test "$MOZ_ENABLE_QTMOBILITY"; then
        AC_DEFINE(MOZ_ENABLE_QTMOBILITY)
     fi
 fi
 
 AC_SUBST(GTK_CONFIG)
@@ -8760,29 +8720,16 @@ done],
 dnl Remove dupes
 NECKO_PROTOCOLS=`${PERL} ${srcdir}/build/unix/uniq.pl ${NECKO_PROTOCOLS}`
 AC_SUBST(NECKO_PROTOCOLS)
 for p in $NECKO_PROTOCOLS; do
     AC_DEFINE_UNQUOTED(NECKO_PROTOCOL_$p)
 done
 
 dnl
-dnl option to disable necko's disk cache
-dnl
-MOZ_ARG_DISABLE_BOOL(necko-disk-cache,
-[  --disable-necko-disk-cache
-                          Disable necko disk cache],
-    NECKO_DISK_CACHE=,
-    NECKO_DISK_CACHE=1)
-AC_SUBST(NECKO_DISK_CACHE)
-if test "$NECKO_DISK_CACHE"; then
-    AC_DEFINE(NECKO_DISK_CACHE)
-fi
-
-dnl
 dnl option to disable necko's wifi scanner
 dnl
 MOZ_ARG_DISABLE_BOOL(necko-wifi,
 [  --disable-necko-wifi    Disable necko wifi scanner],
     NECKO_WIFI=,
     NECKO_WIFI=1)
 
 if test "$OS_ARCH" = "OS2"; then
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIFrameMessageManager.idl
@@ -113,18 +113,25 @@ interface nsIContentFrameMessageManager 
 };
 
 [uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
 };
 
-[scriptable, uuid(ed6522fd-ffb6-4920-b50d-cf629309616b)]
-interface nsIChromeFrameMessageManager : nsIFrameMessageManager
+[scriptable, uuid(6331bbca-2c9f-4766-b3c7-ae75554bf1ec)]
+interface nsITreeItemFrameMessageManager : nsIFrameMessageManager
+{
+  readonly attribute unsigned long childCount;
+  nsITreeItemFrameMessageManager getChildAt(in unsigned long aIndex);
+};
+
+[scriptable, uuid(23e6ef7b-8cc5-4e8b-9391-453440a3b858)]
+interface nsIChromeFrameMessageManager : nsITreeItemFrameMessageManager
 {
   /*
    * Load a script in the (remote) frame. aURL must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If aAllowDelayedLoad is true, script will be loaded when the
    * remote frame becomes available. Otherwise the script will be loaded
    * only if the frame is already available.
    */
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -90,16 +90,17 @@ CPPSRCS		= \
 		nsContentUtils.cpp \
 		nsCopySupport.cpp \
 		nsCrossSiteListenerProxy.cpp \
 		nsCSPService.cpp \
 		nsDataDocumentContentPolicy.cpp \
 		nsDOMAttribute.cpp \
 		nsDOMAttributeMap.cpp \
 		nsDOMBlobBuilder.cpp \
+		nsDOMCaretPosition.cpp \
 		nsDOMDocumentType.cpp \
 		nsDOMEventTargetWrapperCache.cpp \
 		nsDOMFile.cpp \
 		nsDOMFileReader.cpp \
 		nsDOMLists.cpp \
 		nsDOMParser.cpp \
 		nsDOMSerializer.cpp \
 		nsDOMTokenList.cpp \
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsDOMCaretPosition.cpp
@@ -0,0 +1,77 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Lassey <blassey@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 GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDOMCaretPosition.h"
+#include "nsDOMClassInfoID.h"
+#include "nsIDOMClassInfo.h"
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCaretPosition)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMCaretPosition)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCaretPosition)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CaretPosition)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_1(nsDOMCaretPosition, mNode)
+ 
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCaretPosition)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCaretPosition)
+
+DOMCI_DATA(CaretPosition, nsDOMCaretPosition)
+
+
+nsDOMCaretPosition::nsDOMCaretPosition(nsIDOMNode* aNode, PRUint32 aOffset)
+  : mNode(aNode), mOffset(aOffset)
+{
+}
+
+nsDOMCaretPosition::~nsDOMCaretPosition()
+{
+}
+
+NS_IMETHODIMP nsDOMCaretPosition::GetOffsetNode(nsIDOMNode** aOffsetNode)
+{
+  nsCOMPtr<nsIDOMNode> node = mNode;
+  node.forget(aOffsetNode);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsDOMCaretPosition::GetOffset(PRUint32* aOffset)
+{
+  *aOffset = mOffset;
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsDOMCaretPosition.h
@@ -0,0 +1,59 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Lassey <blassey@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 GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDOMCaretPosition_h
+#define nsDOMCaretPosition_h
+
+#include "nsIDOMCaretPosition.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsCOMPtr.h"
+
+class nsDOMCaretPosition : public nsIDOMCaretPosition
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCaretPosition)
+  NS_DECL_NSIDOMCARETPOSITION
+
+  nsDOMCaretPosition(nsIDOMNode* aNode, PRUint32 aOffset);
+
+protected:
+  virtual ~nsDOMCaretPosition();
+  PRUint32 mOffset;
+  nsCOMPtr<nsIDOMNode> mNode;
+};
+#endif
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -197,19 +197,23 @@
 #include "nsHTMLCSSStyleSheet.h"
 
 #include "mozilla/dom/Link.h"
 #include "nsIHTMLDocument.h"
 #include "nsXULAppAPI.h"
 #include "nsDOMTouchEvent.h"
 
 #include "mozilla/Preferences.h"
+#include "nsFrame.h"
 
 #include "imgILoader.h"
 
+#include "nsDOMCaretPosition.h"
+#include "nsIDOMHTMLTextAreaElement.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
@@ -8389,16 +8393,68 @@ nsDocument::CreateTouchList(nsIVariant* 
       nsMemory::Free(rawArray);
     }
   }
 
   *aRetVal = retval.forget().get();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDocument::CaretPositionFromPoint(float aX, float aY, nsIDOMCaretPosition** aCaretPos)
+{
+  NS_ENSURE_ARG_POINTER(aCaretPos);
+  *aCaretPos = nsnull;
+  
+  nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
+  nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
+  nsPoint pt(x, y);
+
+  nsIPresShell *ps = GetShell();
+  if (!ps) {
+    return NS_OK;
+  }
+
+  nsIFrame *rootFrame = ps->GetRootFrame();
+
+  // XUL docs, unlike HTML, have no frame tree until everything's done loading
+  if (!rootFrame) {
+    return NS_OK; // return null to premature XUL callers as a reminder to wait
+  }
+
+  nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, pt, PR_TRUE,
+                                                      PR_FALSE);
+  if (!ptFrame) {
+    return NS_OK;
+  }
+
+  nsFrame::ContentOffsets offsets = ptFrame->GetContentOffsetsFromPoint(pt);
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(offsets.content);
+  nsIContent* ptContent = offsets.content;
+  PRInt32 offset = offsets.offset;
+  if (ptContent && ptContent->IsInNativeAnonymousSubtree()) {
+    nsIContent* nonanon = ptContent->FindFirstNonNativeAnonymous();
+    nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(nonanon);
+    nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea = do_QueryInterface(nonanon);
+    PRBool isText;
+    if (textArea || (input &&
+                     NS_SUCCEEDED(input->MozIsTextField(PR_FALSE, &isText)) && 
+                     isText)) {
+      node = do_QueryInterface(nonanon);
+    } else {
+      node = nsnull;
+      offset = 0;
+    }
+  }
+
+  *aCaretPos = new nsDOMCaretPosition(node, offset);
+  NS_ADDREF(*aCaretPos);
+  return NS_OK;
+}
+
 PRInt64
 nsIDocument::SizeOf() const
 {
   PRInt64 size = sizeof(*this);
 
   for (nsIContent* node = GetFirstChild(); node;
        node = node->GetNextNode(this)) {
     size += node->SizeOf();
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1786,17 +1786,17 @@ nsFrameLoader::TryRemoteBrowser()
   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
   if (!window) {
     return false;
   }
   if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
     return false;
   }
 
-  ContentParent* parent = ContentParent::GetSingleton();
+  ContentParent* parent = ContentParent::GetNewOrUsed();
   NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
   mRemoteBrowser = parent->CreateTab(chromeFlags);
   if (mRemoteBrowser) {
     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
     mRemoteBrowser->SetOwnerElement(element);
 
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -93,16 +93,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
                                          static_cast<nsIChromeFrameMessageManager*>(this)) :
                                        static_cast<nsIFrameMessageManager*>(
                                          static_cast<nsIContentFrameMessageManager*>(this))))
   /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager,
                                      !mChrome && !mIsProcessManager)
   /* Message managers in child process support nsISyncMessageSender. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
+  /* Message managers in chrome process support nsITreeItemFrameMessageManager. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITreeItemFrameMessageManager, mChrome)
   /* Process message manager doesn't support nsIChromeFrameMessageManager. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager,
                                      mChrome && !mIsProcessManager)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager)
 
@@ -319,16 +321,34 @@ nsFrameMessageManager::GetContent(nsIDOM
 NS_IMETHODIMP
 nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
 {
   *aDocShell = nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsFrameMessageManager::GetChildCount(PRUint32* aChildCount)
+{
+  *aChildCount = static_cast<PRUint32>(mChildManagers.Count()); 
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrameMessageManager::GetChildAt(PRUint32 aIndex, 
+                                  nsITreeItemFrameMessageManager** aMM)
+{
+  *aMM = nsnull;
+  nsCOMPtr<nsITreeItemFrameMessageManager> mm =
+    do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<PRUint32>(aIndex)));
+  mm.swap(*aMM);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
                             nsAString& aAsciiBase64String)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::Atob(const nsAString& aAsciiString,
@@ -818,17 +838,17 @@ NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner,
 nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nsnull;
 nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nsnull;
 
 bool SendAsyncMessageToChildProcess(void* aCallbackData,
                                     const nsAString& aMessage,
                                     const nsAString& aJSON)
 {
   mozilla::dom::ContentParent* cp =
-    mozilla::dom::ContentParent::GetSingleton(PR_FALSE);
+    static_cast<mozilla::dom::ContentParent*>(aCallbackData);
   NS_WARN_IF_FALSE(cp, "No child process!");
   if (cp) {
     return cp->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
   }
   return true;
 }
 
 bool SendSyncMessageToParentProcess(void* aCallbackData,
@@ -852,36 +872,56 @@ bool SendAsyncMessageToParentProcess(voi
   mozilla::dom::ContentChild* cc =
     mozilla::dom::ContentChild::GetSingleton();
   if (cc) {
     return cc->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
   }
   return true;
 }
 
+// This creates the global parent process message manager.
 nsresult
 NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
 {
   NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
                "Re-creating sParentProcessManager");
   NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
   nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
                                                         nsnull,
-                                                        SendAsyncMessageToChildProcess,
+                                                        nsnull,
                                                         nsnull,
-                                                        &nsFrameMessageManager::sParentProcessManager,
+                                                        nsnull,
                                                         nsnull,
                                                         nsnull,
                                                         PR_FALSE,
                                                         PR_TRUE);
   NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
   nsFrameMessageManager::sParentProcessManager = mm;
   return CallQueryInterface(mm, aResult);
 }
 
+nsFrameMessageManager*
+nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aProcess)
+{
+  if (!nsFrameMessageManager::sParentProcessManager) {
+     nsCOMPtr<nsIFrameMessageManager> dummy;
+     NS_NewParentProcessMessageManager(getter_AddRefs(dummy));
+  }
+
+  nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
+                                                        nsnull,
+                                                        SendAsyncMessageToChildProcess,
+                                                        nsnull,
+                                                        aProcess,
+                                                        nsFrameMessageManager::sParentProcessManager,
+                                                        nsnull,
+                                                        PR_FALSE,
+                                                        PR_TRUE);
+  return mm;
+}
 
 nsresult
 NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
 {
   NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager,
                "Re-creating sChildProcessManager");
   NS_ENSURE_TRUE(!IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
   nsFrameMessageManager* mm = new nsFrameMessageManager(PR_FALSE,
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -47,16 +47,22 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsDataHashtable.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 
+namespace mozilla {
+namespace dom {
+class ContentParent;
+}
+}
+
 class nsAXPCNativeCallContext;
 struct JSContext;
 struct JSObject;
 
 struct nsMessageListenerInfo
 {
   nsCOMPtr<nsIFrameMessageListener> mListener;
   nsCOMPtr<nsIAtom> mMessage;
@@ -120,16 +126,20 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager,
                                            nsIContentFrameMessageManager)
   NS_DECL_NSIFRAMEMESSAGEMANAGER
   NS_DECL_NSISYNCMESSAGESENDER
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
   NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
+  NS_DECL_NSITREEITEMFRAMEMESSAGEMANAGER
+
+  static nsFrameMessageManager*
+  NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
 
   nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
                           PRBool aSync, const nsAString& aJSON,
                           JSObject* aObjectsArray,
                           InfallibleTArray<nsString>* aJSONRetVal,
                           JSContext* aContext = nsnull);
   void AddChildManager(nsFrameMessageManager* aManager,
                        PRBool aLoadScripts = PR_TRUE);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1054,18 +1054,19 @@ nsINode::AddEventListener(const nsAStrin
   if (!aWantsUntrusted &&
       (aOptionalArgc < 2 &&
        !nsContentUtils::IsChromeDoc(GetOwnerDoc()))) {
     aWantsUntrusted = PR_TRUE;
   }
 
   nsEventListenerManager* listener_manager = GetListenerManager(PR_TRUE);
   NS_ENSURE_STATE(listener_manager);
-  return listener_manager->AddEventListener(aType, aListener, aUseCapture,
-                                            aWantsUntrusted);
+  listener_manager->AddEventListener(aType, aListener, aUseCapture,
+                                     aWantsUntrusted);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsINode::RemoveEventListener(const nsAString& aType,
                              nsIDOMEventListener* aListener,
                              PRBool aUseCapture)
 {
   nsEventListenerManager* elm = GetListenerManager(PR_FALSE);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -65,16 +65,17 @@ GK_ATOM(_empty, "")
 GK_ATOM(moz, "_moz")
 GK_ATOM(moztype, "_moz-type")
 GK_ATOM(mozdirty, "_moz_dirty")
 GK_ATOM(mozdonotsend, "moz-do-not-send")
 GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node")
 GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before")
 GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after")
 GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image")
+GK_ATOM(_moz_original_size, "_moz_original_size")
 GK_ATOM(_moz_target, "_moz_target")
 GK_ATOM(_moz_type, "_moz-type")
 GK_ATOM(menuactive, "_moz-menuactive")
 GK_ATOM(_poundDefault, "#default")
 GK_ATOM(_asterix, "*")
 GK_ATOM(a, "a")
 GK_ATOM(abbr, "abbr")
 GK_ATOM(abort, "abort")
@@ -1868,16 +1869,17 @@ GK_ATOM(scrollbar_start_backward, "scrol
 GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward")
 GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
 GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
 GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
 GK_ATOM(images_in_menus, "images-in-menus")
 GK_ATOM(images_in_buttons, "images-in-buttons")
 GK_ATOM(windows_default_theme, "windows-default-theme")
 GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
+GK_ATOM(mac_lion_theme, "mac-lion-theme")
 GK_ATOM(windows_compositor, "windows-compositor")
 GK_ATOM(touch_enabled, "touch-enabled")
 GK_ATOM(maemo_classic, "maemo-classic")
 GK_ATOM(menubar_drag, "menubar-drag")
 
 // windows theme selector metrics
 GK_ATOM(windows_classic, "windows-classic")
 GK_ATOM(windows_theme_aero, "windows-theme-aero")
@@ -1893,16 +1895,17 @@ GK_ATOM(_moz_scrollbar_start_backward, "
 GK_ATOM(_moz_scrollbar_start_forward, "-moz-scrollbar-start-forward")
 GK_ATOM(_moz_scrollbar_end_backward, "-moz-scrollbar-end-backward")
 GK_ATOM(_moz_scrollbar_end_forward, "-moz-scrollbar-end-forward")
 GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional")
 GK_ATOM(_moz_images_in_menus, "-moz-images-in-menus")
 GK_ATOM(_moz_images_in_buttons, "-moz-images-in-buttons")
 GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
 GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")
+GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme")
 GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor")
 GK_ATOM(_moz_windows_classic, "-moz-windows-classic")
 GK_ATOM(_moz_windows_theme, "-moz-windows-theme")
 GK_ATOM(_moz_touch_enabled, "-moz-touch-enabled")
 GK_ATOM(_moz_maemo_classic, "-moz-maemo-classic")
 GK_ATOM(_moz_menubar_drag, "-moz-menubar-drag")
 GK_ATOM(_moz_device_pixel_ratio, "-moz-device-pixel-ratio")
 GK_ATOM(_moz_device_orientation, "-moz-device-orientation")
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -498,16 +498,17 @@ include $(topsrcdir)/config/rules.mk
 		invalid_accesscontrol.resource^headers^ \
 		somedatas.resource \
 		somedatas.resource^headers^ \
 		delayedServerEvents.sjs \
 		test_bug664916.html \
 		test_bug666604.html \
 		test_bug675121.html \
 		file_bug675121.sjs \
+		test_bug654352.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug654352.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=654352
+-->
+<head>
+  <title>Test for Bug 654352</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=654352">Mozilla Bug 654352</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 654352 **/
+SimpleTest.waitForExplicitFinish();
+function afterLoad() {
+  var testpre = document.getElementById("testpre");
+  var rect1 = testpre.getBoundingClientRect();
+  dump(rect1 + "\n");
+  var caret1 = document.caretPositionFromPoint(rect1.right - 5, rect1.top + 10);
+  ok(caret1.offsetNode == testpre.firstChild, "node in CaretPosition not correct (" + caret1.offsetNode + " == " + testpre.firstChild + ")")
+  ok(caret1.offset == 9, "offset in CaretPosition not correct (" + caret1.offset + "== 9)")
+
+  var testinput = document.getElementById("testinput");
+  var rect2 = testinput.getBoundingClientRect();
+  dump(rect2.top +", " + rect2.left + "\n");
+  var caret2 = document.caretPositionFromPoint( rect2.right - 5, rect2.top + 10);
+  ok(caret2.offsetNode == testinput, "node in CaretPosition not correct (" + caret2.offsetNode + " == " + testinput + ")")
+  ok(caret2.offset == 9, "offset in CaretPosition not correct (" + caret2.offset + "== 9)")
+  SimpleTest.finish();
+};
+addLoadEvent(afterLoad);
+</script>
+</pre>
+<span id="testdiv">
+  <pre id="testpre">test text</pre>
+</span>
+<br>
+<br>
+</div>
+  <input id="testinput" type="text" value="test text"></input>
+</div>
+</body>
+</html>
--- a/content/base/test/test_copypaste.html
+++ b/content/base/test/test_copypaste.html
@@ -48,18 +48,18 @@ function testCopyPaste () {
 
   var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
                             .getService(Components.interfaces.nsIClipboard);
 
   var textarea = document.getElementById('input');
 
   function copySelectionToClipboard() {
     documentViewer.copySelection();
-    is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
-    is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
+    ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), "check text/unicode");
+    ok(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), "check text/html");
   }
   function copyToClipboard(node) {
     textarea.blur();
     clipboard.emptyClipboard(1);
     var sel = window.getSelection();
     sel.removeAllRanges();
     var r = document.createRange();
     r.selectNode(node);
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -121,17 +121,18 @@ nsDOMEventTargetHelper::AddEventListener
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> doc =
       nsContentUtils::GetDocumentFromScriptContext(context);
     aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
   }
 
   nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
   NS_ENSURE_STATE(elm);
-  return elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
+  elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, PRBool* aRetVal)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =
     nsEventDispatcher::DispatchDOMEvent(this, nsnull, aEvent, nsnull, &status);
--- a/content/events/src/nsDOMMessageEvent.cpp
+++ b/content/events/src/nsDOMMessageEvent.cpp
@@ -98,19 +98,21 @@ nsDOMMessageEvent::UnrootData()
 {
   NS_ASSERTION(mDataRooted, "...");
   NS_DROP_JS_OBJECTS(this, nsDOMMessageEvent);
   mDataRooted = false;
   mData = JSVAL_VOID;
 }
 
 NS_IMETHODIMP
-nsDOMMessageEvent::GetData(jsval* aData)
+nsDOMMessageEvent::GetData(JSContext* aCx, jsval* aData)
 {
   *aData = mData;
+  if (!JS_WrapValue(aCx, aData))
+    return NS_ERROR_FAILURE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMMessageEvent::GetOrigin(nsAString& aOrigin)
 {
   aOrigin = mOrigin;
   return NS_OK;
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -204,34 +204,37 @@ nsEventListenerManager::GetInnerWindowFo
   if (window) {
     NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
     return window;
   }
 
   return nsnull;
 }
 
-nsresult
+void
 nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
                                          PRUint32 aType,
                                          nsIAtom* aTypeAtom,
                                          PRInt32 aFlags)
 {
-  NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
-  NS_ENSURE_TRUE(aType, NS_ERROR_FAILURE);
+  NS_ABORT_IF_FALSE(aType && aTypeAtom, "Missing type");
+
+  if (!aListener) {
+    return;
+  }
 
   nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = aListener;
 
   nsListenerStruct* ls;
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
     ls = &mListeners.ElementAt(i);
     if (ls->mListener == aListener && ls->mFlags == aFlags &&
         EVENT_TYPE_EQUALS(ls, aType, aTypeAtom)) {
-      return NS_OK;
+      return;
     }
   }
 
   mNoListenerForEvent = NS_EVENT_TYPE_NULL;
   mNoListenerForEventAtom = nsnull;
 
   ls = mListeners.AppendElement();
   ls->mListener = aListener;
@@ -286,18 +289,16 @@ nsEventListenerManager::AddEventListener
               aTypeAtom == nsGkAtoms::ontouchenter ||
               aTypeAtom == nsGkAtoms::ontouchleave ||
               aTypeAtom == nsGkAtoms::ontouchcancel)) {
     mMayHaveTouchEventListener = PR_TRUE;
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window)
       window->SetHasTouchEventListeners();
   }
-
-  return NS_OK;
 }
 
 void
 nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, 
                                             PRUint32 aType,
                                             nsIAtom* aUserType,
                                             PRInt32 aFlags)
 {
@@ -329,24 +330,24 @@ ListenerCanHandle(nsListenerStruct* aLs,
   // This is slightly different from EVENT_TYPE_EQUALS in that it returns
   // true even when aEvent->message == NS_USER_DEFINED_EVENT and
   // aLs=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are the same
   return aEvent->message == NS_USER_DEFINED_EVENT ?
     (aLs->mTypeAtom == aEvent->userType) :
     (aLs->mEventType == aEvent->message);
 }
 
-nsresult
+void
 nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aListener, 
                                                const nsAString& aType,
                                                PRInt32 aFlags)
 {
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
   PRUint32 type = nsContentUtils::GetEventId(atom);
-  return AddEventListener(aListener, type, atom, aFlags);
+  AddEventListener(aListener, type, atom, aFlags);
 }
 
 void
 nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener *aListener, 
                                                   const nsAString& aType,
                                                   PRInt32 aFlags)
 {
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
@@ -938,18 +939,17 @@ nsEventListenerManager::HandleEventInter
 
 void
 nsEventListenerManager::Disconnect()
 {
   mTarget = nsnull;
   RemoveAllListeners();
 }
 
-// nsIDOMEventTarget interface
-nsresult
+void
 nsEventListenerManager::AddEventListener(const nsAString& aType,
                                          nsIDOMEventListener* aListener,
                                          PRBool aUseCapture,
                                          PRBool aWantsUntrusted)
 {
   PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
 
   if (aWantsUntrusted) {
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -79,31 +79,31 @@ class nsEventListenerManager
 public:
   nsEventListenerManager(nsISupports* aTarget);
   virtual ~nsEventListenerManager();
 
   NS_INLINE_DECL_REFCOUNTING(nsEventListenerManager)
 
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
 
-  nsresult AddEventListener(const nsAString& aType,
-                            nsIDOMEventListener* aListener,
-                            PRBool aUseCapture,
-                            PRBool aWantsUntrusted);
+  void AddEventListener(const nsAString& aType,
+                        nsIDOMEventListener* aListener,
+                        PRBool aUseCapture,
+                        PRBool aWantsUntrusted);
   void RemoveEventListener(const nsAString& aType,
                            nsIDOMEventListener* aListener,
                            PRBool aUseCapture);
 
   /**
   * Sets events listeners of all types. 
   * @param an event listener
   */
-  nsresult AddEventListenerByType(nsIDOMEventListener *aListener,
-                                  const nsAString& type,
-                                  PRInt32 aFlags);
+  void AddEventListenerByType(nsIDOMEventListener *aListener,
+                              const nsAString& type,
+                              PRInt32 aFlags);
   void RemoveEventListenerByType(nsIDOMEventListener *aListener,
                                  const nsAString& type,
                                  PRInt32 aFlags);
   nsresult AddScriptEventListener(nsIAtom *aName,
                                   const nsAString& aFunc,
                                   PRUint32 aLanguage,
                                   PRBool aDeferCompilation,
                                   PRBool aPermitUntrustedEvents);
@@ -205,20 +205,20 @@ protected:
                                        nsListenerStruct *aListenerStruct,
                                        nsISupports* aCurrentTarget,
                                        PRBool aNeedsCxPush);
   nsListenerStruct* FindJSEventListener(PRUint32 aEventType, nsIAtom* aTypeAtom);
   nsresult SetJSEventListener(nsIScriptContext *aContext,
                               void *aScopeGlobal,