Merge cvs-trunk-mirror to mozilla-central.
authorbenjamin@smedbergs.us
Wed, 27 Feb 2008 11:33:49 -0500
changeset 12365 99848dc55a1a6fae90e69e03c3819fdf3b3d088f
parent 12116 7dc5a61c3b07fca66e3356d935838087f4fefd81 (current diff)
parent 12364 7d1e0bfa9aeb20d23a502329a6d35aa178e5c96d (diff)
child 12412 0cf3fc5d7d4e91367526318814f7a66cb149bd52
push idunknown
push userunknown
push dateunknown
milestone2.0a1pre
Merge cvs-trunk-mirror to mozilla-central.
browser/components/safebrowsing/content/browser-view.js
browser/components/safebrowsing/content/controller.js
browser/components/safebrowsing/content/firefox-commands.js
browser/components/safebrowsing/content/phishing-afterload-displayer.js
browser/components/safebrowsing/content/reporter.js
browser/components/safebrowsing/content/warning-overlay.xul
browser/components/safebrowsing/public/Makefile.in
browser/components/safebrowsing/public/nsIDocNavStartProgressListener.idl
browser/components/safebrowsing/src/nsDocNavStartProgressListener.cpp
browser/components/safebrowsing/src/nsDocNavStartProgressListener.h
browser/components/safebrowsing/tests/Makefile.in
browser/components/safebrowsing/tests/jar.mn
browser/components/safebrowsing/tests/unittests.xul
browser/themes/gnomestripe/browser/places/livemark-folder-rtl.png
browser/themes/gnomestripe/browser/places/livemark-folder.png
browser/themes/gnomestripe/browser/places/livemark-item-rtl.png
browser/themes/gnomestripe/browser/safebrowsing/browser-protection.css
browser/themes/gnomestripe/browser/safebrowsing/close16x16.png
browser/themes/gnomestripe/browser/safebrowsing/dim.png
browser/themes/gnomestripe/browser/safebrowsing/tail.png
browser/themes/gnomestripe/browser/safebrowsing/warning16x16.png
browser/themes/gnomestripe/browser/safebrowsing/warning24x24.png
browser/themes/pinstripe/browser/safebrowsing/browser-protection.css
browser/themes/pinstripe/browser/safebrowsing/close16x16.png
browser/themes/pinstripe/browser/safebrowsing/dim.png
browser/themes/pinstripe/browser/safebrowsing/tail.png
browser/themes/pinstripe/browser/safebrowsing/warning16x16.png
browser/themes/pinstripe/browser/safebrowsing/warning24x24.png
browser/themes/winstripe/browser/safebrowsing/browser-protection.css
browser/themes/winstripe/browser/safebrowsing/close16x16.png
browser/themes/winstripe/browser/safebrowsing/dim.png
browser/themes/winstripe/browser/safebrowsing/tail.png
browser/themes/winstripe/browser/safebrowsing/warning16x16.png
browser/themes/winstripe/browser/safebrowsing/warning24x24.png
config/autoconf.mk.in
config/config.mk
config/rules.mk
configure.in
embedding/components/printingui/src/mac/nsPrintDialogExtension.r
embedding/components/printingui/src/mac/nsPrintingPromptService.cpp
embedding/components/printingui/src/mac/nsPrintingPromptServiceX.cpp
embedding/components/printingui/src/mac/printpde/PrintPDE.pbproj/project.pbxproj
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsdate.cpp
js/src/jsemit.cpp
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsscope.cpp
js/src/jsstr.cpp
js/src/prmjtime.cpp
toolkit/components/places/tests/bookmarks/test_sort_by_count.js
toolkit/components/url-classifier/content/url-crypto.js
uriloader/exthandler/mac/nsInternetConfig.cpp
uriloader/exthandler/mac/nsInternetConfigService.cpp
uriloader/exthandler/mac/nsLocalHandlerAppMac.cpp
uriloader/exthandler/mac/nsMIMEInfoMac.cpp
uriloader/exthandler/mac/nsOSHelperAppService.cpp
xpcom/io/nsLocalFileOSX.cpp
xpcom/obsolete/nsFileSpecMac.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -42,16 +42,18 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/config.mk
 
 default alldep all::
 	$(RM) -rf $(DIST)/sdk
 	$(RM) -rf $(DIST)/include
+	$(RM) -rf $(DIST)/private
+	$(RM) -rf $(DIST)/public
 	$(RM) -rf _tests
 
 TIERS += base
 
 #
 # tier "base" - basic setup
 #
 tier_base_dirs = \
@@ -133,16 +135,19 @@ ifdef MOZ_PROFILE
 	/bin/find $(DIST) -name "*.dbg" -exec mv {} $(DIST)/$(BUILDID) \;
 endif # MOZ_PROFILE
 endif # MOZILLA_OFFICIAL
 endif # WINNT
 
 ifeq ($(OS_ARCH),WINNT)
 # we want to copy PDB files on Windows
 MAKE_SYM_STORE_ARGS := -c
+ifdef PDBSTR_PATH
+MAKE_SYM_STORE_ARGS += -i
+endif
 ifeq (,$(CYGWIN_WRAPPER))
 # this doesn't work with Cygwin Python
 MAKE_SYM_STORE_ARGS += --vcs-info
 endif
 DUMP_SYMS_BIN ?= $(topsrcdir)/toolkit/crashreporter/tools/win32/dump_syms.exe
 # PDB files don't get moved to dist, so we need to scan the whole objdir
 MAKE_SYM_STORE_PATH := .
 endif
--- a/accessible/public/nsIAccessibilityService.idl
+++ b/accessible/public/nsIAccessibilityService.idl
@@ -39,18 +39,19 @@
 #include "nsISupports.idl"
 #include "nsIAccessibleRetrieval.idl"
 
 interface nsIAccessibleEventListener;
 interface nsIDocument;
 interface nsIFrame;
 interface nsObjectFrame;
 interface nsIContent;
+interface nsITimer;
 
-[uuid(933f7472-cbe3-4d95-a77a-ce7ea3812b32)]
+[uuid(27386cf1-f27e-4d2d-9bf4-c4621d50d299)]
 interface nsIAccessibilityService : nsIAccessibleRetrieval
 {
   nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
   nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
 
   nsIAccessible createHTML4ButtonAccessible(in nsISupports aFrame);
   nsIAccessible createHyperTextAccessible(in nsISupports aFrame);
   nsIAccessible createHTMLBRAccessible(in nsISupports aFrame);
@@ -95,16 +96,27 @@ interface nsIAccessibilityService : nsIA
    *                           Must be one of:
    *                           EVENT_REORDER (change),
    *                           EVENT_SHOW (make visible or create) or 
    *                           EVENT_HIDE (destroy or hide)
    */
   void invalidateSubtreeFor(in nsIPresShell aPresShell,
                             in nsIContent aChangedContent,
                             in PRUint32 aEvent);
+
+  /**
+   *  An internal doc load event has occured. Handle the event and remove it from the list.
+   *  @param aTimer      The timer created to handle this doc load event
+   *  @param aClosure    The nsIWebProgress* for the load event
+   *  @param aEventType  The type of load event, one of: nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
+   *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE or
+   *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
+   */
+  void processDocLoadEvent(in nsITimer aTimer, in voidPtr aClosure, in PRUint32 aEventType);
+
 };
 
 
 %{ C++
 
 // for component registration
 // {DE401C37-9A7F-4278-A6F8-3DE2833989EF}
 #define NS_ACCESSIBILITY_SERVICE_CID \
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -59,144 +59,117 @@
 static const nsStateMapEntry kEndEntry = {nsnull, 0, 0};  // To fill in array of state mappings
 
 nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
 {
   {"alert", nsIAccessibleRole::ROLE_ALERT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED},
             {&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
   {"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax,
                nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
             // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED}, kEndEntry},
   {"description", nsIAccessibleRole::ROLE_TEXT_CONTAINER, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"dialog", nsIAccessibleRole::ROLE_DIALOG, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"document", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"grid", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_FOCUSABLE,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"gridcell", nsIAccessibleRole::ROLE_CELL, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
             {&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"group", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"heading", nsIAccessibleRole::ROLE_HEADING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"img", nsIAccessibleRole::ROLE_GRAPHIC, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"label", nsIAccessibleRole::ROLE_LABEL, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
-  {"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED, kEndEntry},
   {"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"listbox", nsIAccessibleRole::ROLE_LISTBOX, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
-  {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
-  {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
   {"menuitemcheckbox", nsIAccessibleRole::ROLE_CHECK_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
   {"menuitemradio", nsIAccessibleRole::ROLE_RADIO_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
   {"option", nsIAccessibleRole::ROLE_OPTION, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
   {"presentation", nsIAccessibleRole::ROLE_NOTHING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
-  {"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY, kEndEntry},
   {"radio", nsIAccessibleRole::ROLE_RADIOBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED}, kEndEntry},
-  {"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"region", nsIAccessibleRole::ROLE_PANE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"row", nsIAccessibleRole::ROLE_ROW, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
             {&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED}, kEndEntry},
   {"rowheader", nsIAccessibleRole::ROLE_ROWHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"section", nsIAccessibleRole::ROLE_SECTION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"separator", nsIAccessibleRole::ROLE_SEPARATOR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"slider", nsIAccessibleRole::ROLE_SLIDER, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"spinbutton", nsIAccessibleRole::ROLE_SPINBUTTON, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"status", nsIAccessibleRole::ROLE_STATUSBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
-  {"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"tablist", nsIAccessibleRole::ROLE_PAGETABLIST, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"tabpanel", nsIAccessibleRole::ROLE_PROPERTYPAGE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"textbox", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eNoValue, kNoReqStates,
             // Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aria-multiline
             // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
             {&nsAccessibilityAtoms::aria_autocomplete, "list", nsIAccessibleStates::STATE_HASPOPUP},
             {&nsAccessibilityAtoms::aria_autocomplete, "both", nsIAccessibleStates::STATE_HASPOPUP},
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
-  {"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
+  {"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"tooltip", nsIAccessibleRole::ROLE_TOOLTIP, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"tree", nsIAccessibleRole::ROLE_OUTLINE, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"treegrid", nsIAccessibleRole::ROLE_TREE_TABLE, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"treeitem", nsIAccessibleRole::ROLE_OUTLINEITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
             {&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},},
 };
@@ -227,11 +200,12 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap 
  * whether there is an ARIA role or not:
  */
 nsStateMapEntry nsARIAMap::gWAIUnivStateMap[] = {
   {&nsAccessibilityAtoms::aria_required, kBoolState, nsIAccessibleStates::STATE_REQUIRED},
   {&nsAccessibilityAtoms::aria_invalid,  kBoolState, nsIAccessibleStates::STATE_INVALID},
   {&nsAccessibilityAtoms::aria_haspopup, kBoolState, nsIAccessibleStates::STATE_HASPOPUP},
   {&nsAccessibilityAtoms::aria_busy,     "true",     nsIAccessibleStates::STATE_BUSY},
   {&nsAccessibilityAtoms::aria_busy,     "error",    nsIAccessibleStates::STATE_INVALID},
+  {&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
   kEndEntry
 };
 
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -90,16 +90,19 @@ PRBool nsAccessNode::gIsCacheDisabled = 
 PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
 nsAccessNodeHashtable nsAccessNode::gGlobalDocAccessibleCache;
 
 nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
 
 nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
 nsIAccessibilityService *nsAccessNode::GetAccService()
 {
+  if (!gIsAccessibilityActive)
+    return nsnull;
+
   if (!sAccService) {
     nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
                                  &sAccService);
     NS_ASSERTION(NS_SUCCEEDED(rv), "No accessibility service");
   }
 
   return sAccService;
 }
@@ -217,18 +220,20 @@ NS_IMETHODIMP nsAccessNode::Shutdown()
 NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
 {
   *aUniqueID = static_cast<void*>(mDOMNode);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAccessNode::GetOwnerWindow(void **aWindow)
 {
+  *aWindow = nsnull;
   nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
-  NS_ASSERTION(docAccessible, "No root accessible pointer back, Init() not called.");
+  if (!docAccessible)
+    return NS_ERROR_FAILURE; // This node or doc accessible is shut down
   return docAccessible->GetWindowHandle(aWindow);
 }
 
 already_AddRefed<nsApplicationAccessibleWrap>
 nsAccessNode::GetApplicationAccessible()
 {
   if (!gIsAccessibilityActive) {
     return nsnull;
@@ -310,17 +315,17 @@ void nsAccessNode::ShutdownXPAccessibili
   }
   NS_IF_RELEASE(gStringBundle);
   NS_IF_RELEASE(gKeyStringBundle);
   NS_IF_RELEASE(gDoCommandTimer);
   NS_IF_RELEASE(gLastFocusedNode);
   NS_IF_RELEASE(sAccService);
 
   nsApplicationAccessibleWrap::Unload();
-  ClearCache(gGlobalDocAccessibleCache);
+  gGlobalDocAccessibleCache.Enumerate(ClearDocCacheEntry, nsnull);
 
   // Release gApplicationAccessible after everything else is shutdown
   // so we don't accidently create it again while tearing down root accessibles
   NS_IF_RELEASE(gApplicationAccessible);
   gApplicationAccessible = nsnull;  
 
   gIsAccessibilityActive = PR_FALSE;
   NotifyA11yInitOrShutdown();
@@ -786,16 +791,24 @@ nsAccessNode::GetCacheEntry(nsAccessNode
 PLDHashOperator nsAccessNode::ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
 {
   nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
   privateAccessNode->Shutdown();
 
   return PL_DHASH_REMOVE;
 }
 
+PLDHashOperator nsAccessNode::ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
+{
+  nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
+  privateAccessNode->Shutdown();
+
+  return PL_DHASH_NEXT; // nsDocAccessible::Shutdown() removes the doc from doc cache
+}
+
 void
 nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
 {
   aCache.Enumerate(ClearCacheEntry, nsnull);
 }
 
 already_AddRefed<nsIDOMNode> nsAccessNode::GetCurrentFocus()
 {
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -93,16 +93,17 @@ class nsAccessNode: public nsIAccessNode
     // Static methods for handling per-document cache
     static void PutCacheEntry(nsAccessNodeHashtable& aCache,
                               void* aUniqueID, nsIAccessNode *aAccessNode);
     static void GetCacheEntry(nsAccessNodeHashtable& aCache,
                               void* aUniqueID, nsIAccessNode **aAccessNode);
     static void ClearCache(nsAccessNodeHashtable& aCache);
 
     static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
+    static PLDHashOperator PR_CALLBACK ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
 
     // Static cache methods for global document cache
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIWeakReference *aWeakShell);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocShellTreeItem *aContainer, PRBool aCanCreate = PR_FALSE);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDOMNode *aNode);
 
     static already_AddRefed<nsIDOMNode> GetDOMNodeForContainer(nsISupports *aContainer);
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsAccessibilityUtils.h"
 #include "nsARIAMap.h"
+#include "nsIContentViewer.h"
 #include "nsCURILoader.h"
 #include "nsDocAccessible.h"
 #include "nsHTMLImageAccessibleWrap.h"
 #include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsHTMLTableAccessibleWrap.h"
 #include "nsHTMLTextAccessible.h"
 #include "nsHyperTextAccessibleWrap.h"
@@ -150,94 +151,129 @@ nsAccessibilityService::Observe(nsISuppo
 {
   if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     nsCOMPtr<nsIObserverService> observerService = 
       do_GetService("@mozilla.org/observer-service;1");
     if (observerService) {
       observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
     }
     nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
-    if (progress) {
+    if (progress)
       progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
+    nsAccessNodeWrap::ShutdownAccessibility();
+    // Cancel and release load timers
+    while (mLoadTimers.Count() > 0 ) {
+      nsCOMPtr<nsITimer> timer = mLoadTimers.ObjectAt(0);
+      void *closure = nsnull;
+      timer->GetClosure(&closure);
+      if (closure) {
+        nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(closure);
+        NS_RELEASE(webProgress);  // Release nsIWebProgress for timer
+      }
+      timer->Cancel();
+      mLoadTimers.RemoveObjectAt(0);
     }
-    nsAccessNodeWrap::ShutdownAccessibility();
   }
   return NS_OK;
 }
 
 // nsIWebProgressListener
 NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress,
   nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
 {
   NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
 
-  if (0 == (aStateFlags & (STATE_START | STATE_STOP))) {
+  if (!aWebProgress || 0 == (aStateFlags & (STATE_START | STATE_STOP))) {
     return NS_OK;
   }
-
-  nsCOMPtr<nsIDOMWindow> domWindow;
-  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
-  NS_ASSERTION(domWindow, "DOM Window for state change is null");
-  NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
+  
+  nsCAutoString name;
+  aRequest->GetName(name);
+  if (name.EqualsLiteral("about:blank"))
+    return NS_OK;
 
-  nsCOMPtr<nsIDOMDocument> domDoc;
-  domWindow->GetDocument(getter_AddRefs(domDoc));
-  nsCOMPtr<nsIDOMNode> domDocNode(do_QueryInterface(domDoc));
-  NS_ENSURE_TRUE(domDocNode, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIAccessibleDocument> docAccessible;
+  if (NS_FAILED(aStatus) && (aStateFlags & STATE_START))
+    return NS_OK;
+ 
+  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
+  if (!timer)
+    return NS_OK;
+  mLoadTimers.AppendObject(timer);
+  NS_ADDREF(aWebProgress);
 
-  PRUint32 eventType = 0;
-  if (aStateFlags & STATE_STOP) {
-    // Do not create accessible for page load end events
-    // in case it was already shut down before page finished loading
-    docAccessible = nsAccessNode::GetDocAccessibleFor(domDocNode);  // Cached doc accessibles only
-    if (!docAccessible)
-      return NS_OK;
-    nsCOMPtr<nsIDOMDocument> domDocTest;
-    docAccessible->GetDocument(getter_AddRefs(domDocTest));
-    if (domDocTest != domDoc) {
-      // Doc from accessible is not the doc we started from
-      // We must be shutdown, and domDocTest should be null
-      NS_ASSERTION(!domDocTest, "Doc not shut down but reports incorrect DOM document");
-      return NS_OK;
-    }
-    
-    eventType = NS_FAILED(aStatus) ? nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED :
-                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
-  }
-  else {
-    // Get the accessible for the new document.
-    // If it not created yet this will create it & cache it, as well as 
-    // set up event listeners so that MSAA/ATK toolkit and internal 
-    // accessibility events will get fired.
-    nsCOMPtr<nsIAccessible> accessible;
-    GetAccessibleFor(domDocNode, getter_AddRefs(accessible));  // Create if necessary
-    docAccessible = do_QueryInterface(accessible);
-    eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START;
+  if (aStateFlags & STATE_START)
+    timer->InitWithFuncCallback(StartLoadCallback, aWebProgress, 0,
+                                nsITimer::TYPE_ONE_SHOT);
+  else if (NS_SUCCEEDED(aStatus)) 
+    timer->InitWithFuncCallback(EndLoadCallback, aWebProgress, 0,
+                                nsITimer::TYPE_ONE_SHOT);
+  else // Failed end load
+    timer->InitWithFuncCallback(FailedLoadCallback, aWebProgress, 0,
+                                nsITimer::TYPE_ONE_SHOT);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsAccessibilityService::ProcessDocLoadEvent(nsITimer *aTimer, void *aClosure, PRUint32 aEventType)
+{
+  nsCOMPtr<nsIDOMWindow> domWindow;
+  nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(aClosure);
+  webProgress->GetDOMWindow(getter_AddRefs(domWindow));
+  NS_RELEASE(webProgress);
+  mLoadTimers.RemoveObject(aTimer);
+  NS_ENSURE_STATE(domWindow);
+
+  if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) {
     nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
-    NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
+    NS_ENSURE_STATE(docShell);
     PRUint32 loadType;
     docShell->GetLoadType(&loadType);
     if (loadType == LOAD_RELOAD_NORMAL ||
         loadType == LOAD_RELOAD_BYPASS_CACHE ||
         loadType == LOAD_RELOAD_BYPASS_PROXY ||
         loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
-      eventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
+      aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
     }
   }
       
-  nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(docAccessible);
-  if (eventType && privDocAccessible) {
-    privDocAccessible->FireDocLoadEvents(eventType);
-  }
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  domWindow->GetDocument(getter_AddRefs(domDoc));
+  nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(domDoc);
+  NS_ENSURE_STATE(docNode);
+
+  nsCOMPtr<nsIAccessible> accessible;
+  GetAccessibleFor(docNode, getter_AddRefs(accessible));
+  nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(accessible);
+  NS_ENSURE_STATE(privDocAccessible);
+  privDocAccessible->FireDocLoadEvents(aEventType);
 
   return NS_OK;
 }
 
+void nsAccessibilityService::StartLoadCallback(nsITimer *aTimer, void *aClosure)
+{
+  nsIAccessibilityService *accService = nsAccessNode::GetAccService();
+  if (accService)
+    accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START);
+}
+
+void nsAccessibilityService::EndLoadCallback(nsITimer *aTimer, void *aClosure)
+{
+  nsIAccessibilityService *accService = nsAccessNode::GetAccService();
+  if (accService)
+    accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
+}
+
+void nsAccessibilityService::FailedLoadCallback(nsITimer *aTimer, void *aClosure)
+{
+  nsIAccessibilityService *accService = nsAccessNode::GetAccService();
+  if (accService)
+    accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
+}
+
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
   nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
   PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
@@ -373,16 +409,35 @@ nsAccessibilityService::CreateRootAccess
 
   nsIPresShell *presShell = aShell;
   if (!presShell) {
     presShell = aDocument->GetPrimaryShell();
   }
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
 
   nsCOMPtr<nsISupports> container = aDocument->GetContainer();
+  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
+  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIContentViewer> contentViewer;
+  docShell->GetContentViewer(getter_AddRefs(contentViewer));
+  NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE); // Doc was already shut down
+  PRUint32 busyFlags;
+  docShell->GetBusyFlags(&busyFlags);
+  if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
+    nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(docShell));
+    nsCOMPtr<nsIURI> uri;
+    webNav->GetCurrentURI(getter_AddRefs(uri));
+    NS_ENSURE_STATE(uri);
+    nsCAutoString url;
+    uri->GetSpec(url);
+    if (url.EqualsLiteral("about:blank")) {
+      return NS_OK;  // No load events for a busy about:blank -- they are often temporary
+    }
+  }
+
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     do_QueryInterface(container);
   NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
   
   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
   docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
 
   if (parentTreeItem) {
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -35,17 +35,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __nsAccessibilityService_h__
 #define __nsAccessibilityService_h__
 
 #include "nsIAccessibilityService.h"
+#include "nsCOMArray.h"
 #include "nsIObserver.h"
+#include "nsITimer.h"
+#include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 #include "nsWeakReference.h"
 
 class nsIFrame;
 class nsIWeakReference;
 class nsIDOMNode;
 class nsObjectFrame;
 class nsIDocShell;
@@ -130,16 +133,21 @@ private:
    * Does this content node have a universal ARIA property set on it?
    * A universal ARIA property is one that can be defined on any element even if there is no role.
    *
    * @param aContent The content node to test
    * @param aWeakShell  A weak reference to the pres shell
    * @return PR_TRUE if there is a universal ARIA property set on the node
    */
   PRBool HasUniversalAriaProperty(nsIContent *aContent, nsIWeakReference *aWeakShell);
+
+  static void StartLoadCallback(nsITimer *aTimer, void *aClosure);
+  static void EndLoadCallback(nsITimer *aTimer, void *aClosure);
+  static void FailedLoadCallback(nsITimer *aTimer, void *aClosure);
+  nsCOMArray<nsITimer> mLoadTimers;
 };
 
 /**
  * Map nsIAccessibleRole constants to strings. Used by
  * nsIAccessibleRetrieval::getStringRole() method.
  */
 static const char kRoleNames[][20] = {
   "nothing",             //ROLE_NOTHING
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -73,21 +73,24 @@ void nsCaretAccessible::Shutdown()
   ClearControlSelectionListener(); // Clear the selection listener for the currently focused control
   mLastTextAccessible = nsnull;
   mLastUsedSelection = nsnull;
   mRootAccessible = nsnull;
 }
 
 nsresult nsCaretAccessible::ClearControlSelectionListener()
 {
-  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
-  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
+  mCurrentControl = nsnull;
+  mCurrentControlSelection = nsnull;
 
-  mCurrentControlSelection = nsnull;
-  mCurrentControl = nsnull;
+  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
+  if (!selPrivate) {
+    return NS_OK;
+  }
+
   return selPrivate->RemoveSelectionListener(this);
 }
 
 nsresult nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode)
 {
   NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
 
   ClearControlSelectionListener();
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -80,17 +80,17 @@
 PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
 nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
 
 //-----------------------------------------------------
 // construction
 //-----------------------------------------------------
 nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
-  mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE)
+  mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE), mIsLoadCompleteFired(PR_FALSE)
 {
   // For GTK+ native window, we do nothing here.
   if (!mDOMNode)
     return;
 
   // Because of the way document loading happens, the new nsIWidget is created before
   // the old one is removed. Since it creates the nsDocAccessible, for a brief moment
   // there can be 2 nsDocAccessible's for the content area, although for 2 different
@@ -521,43 +521,43 @@ NS_IMETHODIMP nsDocAccessible::Shutdown(
   if (!mWeakShell) {
     return NS_OK;  // Already shutdown
   }
 
   nsCOMPtr<nsIDocShellTreeItem> treeItem =
     nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
   ShutdownChildDocuments(treeItem);
 
-  if (mDocLoadTimer) {
-    mDocLoadTimer->Cancel();
-    mDocLoadTimer = nsnull;
-  }
-
   RemoveEventListeners();
 
   mWeakShell = nsnull;  // Avoid reentrancy
 
   ClearCache(mAccessNodeCache);
 
+  nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
   mDocument = nsnull;
 
   nsHyperTextAccessibleWrap::Shutdown();
 
   if (mFireEventTimer) {
     // Doc being shut down before events fired,
     mFireEventTimer->Cancel();
     mFireEventTimer = nsnull;
     if (mEventsToFire.Count() > 0 ) {
       mEventsToFire.Clear();
       // Make sure we release the kung fu death grip which is always
       // there when there are still events left to be fired
       NS_RELEASE_THIS();
     }
   }
 
+  // Remove from the cache after other parts of Shutdown(), so that Shutdown() procedures
+  // can find the doc or root accessible in the cache if they need it.
+  gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
+
   return NS_OK;
 }
 
 void nsDocAccessible::ShutdownChildDocuments(nsIDocShellTreeItem *aStart)
 {
   nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
   if (treeNode) {
     PRInt32 subDocuments;
@@ -761,60 +761,65 @@ NS_IMETHODIMP nsDocAccessible::FireDocLo
   if (!mDocument || !mWeakShell) {
     return NS_OK;  // Document has been shut down
   }
 
   PRBool isFinished = 
              (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
               aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
 
-  if (mIsContentLoaded == isFinished) {
+  mIsContentLoaded = isFinished;
+  if (isFinished) {
+    if (mIsLoadCompleteFired)
+      return NS_OK;
+    mIsLoadCompleteFired = PR_TRUE;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> treeItem =
+    nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
+  if (!treeItem) {
     return NS_OK;
   }
-  mIsContentLoaded = isFinished;
+  nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
+  treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
 
   if (isFinished) {
     // Need to wait until scrollable view is available
     AddScrollListener();
     nsCOMPtr<nsIAccessible> parent(nsAccessible::GetParent());
     nsCOMPtr<nsPIAccessible> privateAccessible(do_QueryInterface(parent));
     if (privateAccessible) {
       // Make the parent forget about the old document as a child
       privateAccessible->InvalidateChildren();
     }
-    // Use short timer before firing state change event for finished doc,
-    // because the window is made visible asynchronously
-    if (!mDocLoadTimer) {
-      mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
-    }
-    if (mDocLoadTimer) {
-      mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
-                                          nsITimer::TYPE_ONE_SHOT);
-    }
-  } else {
-    nsCOMPtr<nsIDocShellTreeItem> treeItem =
-      nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
-    if (!treeItem) {
-      return NS_OK;
+    if (sameTypeRoot != treeItem) {
+      // Fire show/hide events to indicate frame/iframe content is new, rather than
+      // doc load event which causes screen readers to act is if entire page is reloaded
+      InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
     }
-
-    nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
-    treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-    if (sameTypeRoot != treeItem) {
-      return NS_OK; 
+    // Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
+    if (gLastFocusedNode) {
+      nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
+        nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
+      if (focusedTreeItem) {
+        nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
+        focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
+        if (sameTypeRoot == sameTypeRootOfFocus) {
+          nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
+            new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY, PR_FALSE, PR_FALSE);
+          FireAccessibleEvent(accEvent);
+          FireAnchorJumpEvent();
+        }
+      }
     }
-
-    // Loading document: fire EVENT_STATE_CHANGE to set STATE_BUSY
-    nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
-      new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY,
-                                PR_FALSE, PR_TRUE);
-    FireAccessibleEvent(accEvent);
   }
-
-  nsAccUtils::FireAccEvent(aEventType, this);
+  if (sameTypeRoot == treeItem) {
+    // Not a frame or iframe
+    nsAccUtils::FireAccEvent(aEventType, this);
+  }
   return NS_OK;
 }
 
 void nsDocAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure)
 {
   nsDocAccessible *docAcc = reinterpret_cast<nsDocAccessible*>(aClosure);
 
   if (docAcc && docAcc->mScrollPositionChangedTicks &&
@@ -2062,60 +2067,8 @@ nsDocAccessible::FireShowHideEvents(nsID
     nsCOMPtr<nsIDOMNode> childNode = do_QueryInterface(content->GetChildAt(index));
     nsresult rv = FireShowHideEvents(childNode, PR_FALSE, aEventType,
                                      aDelay, aForceIsFromUserInput);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
-
-void nsDocAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
-{
-  // Doc has finished loading, fire "load finished" event
-  // By using short timer we can wait make the window visible, 
-  // which it does asynchronously. This avoids confusing the screen reader with a
-  // hidden window. Waiting also allows us to see of the document has focus,
-  // which is important because we only fire doc loaded events for focused documents.
-
-  nsDocAccessible *docAcc =
-    reinterpret_cast<nsDocAccessible*>(aClosure);
-  if (!docAcc) {
-    return;
-  }
-
-  // Fire doc finished event
-  nsCOMPtr<nsIDOMNode> docDomNode;
-  docAcc->GetDOMNode(getter_AddRefs(docDomNode));
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
-  if (doc) {
-    nsCOMPtr<nsISupports> container = doc->GetContainer();
-    nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
-    if (!docShellTreeItem) {
-      return;
-    }
-    nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
-    docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-    if (sameTypeRoot != docShellTreeItem) {
-      // A frame or iframe has finished loading new content
-      docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
-      return;
-    }
-
-    // Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
-    if (gLastFocusedNode) {
-      nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
-        nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
-      if (focusedTreeItem) {
-        nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
-        focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
-        if (sameTypeRoot == sameTypeRootOfFocus) {
-          nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
-            new nsAccStateChangeEvent(docAcc, nsIAccessibleStates::STATE_BUSY,
-                                      PR_FALSE, PR_FALSE);
-          docAcc->FireAccessibleEvent(accEvent);
-          docAcc->FireAnchorJumpEvent();
-        }
-      }
-    }
-  }
-}
-
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -209,22 +209,19 @@ class nsDocAccessible : public nsHyperTe
 
     nsAccessNodeHashtable mAccessNodeCache;
     void *mWnd;
     nsCOMPtr<nsIDocument> mDocument;
     nsCOMPtr<nsITimer> mScrollWatchTimer;
     nsCOMPtr<nsITimer> mFireEventTimer;
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
     PRPackedBool mIsContentLoaded;
+    PRPackedBool mIsLoadCompleteFired;
     nsCOMArray<nsIAccessibleEvent> mEventsToFire;
 
 protected:
     PRBool mIsAnchor;
     PRBool mIsAnchorJumped;
     static PRUint32 gLastFocusedAccessiblesState;
     static nsIAtom *gLastFocusedFrameType;
-
-private:
-    static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
-    nsCOMPtr<nsITimer> mDocLoadTimer;
 };
 
 #endif  
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -401,39 +401,21 @@ void nsRootAccessible::TryFireEarlyLoadE
     treeNode->GetChildCount(&subDocuments);
     if (subDocuments) {
       return;
     }
   }
   nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
   treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
   NS_ASSERTION(rootContentTreeItem, "No root content tree item");
-  if (!rootContentTreeItem) { // Not at root of content
-    return;
+  if (rootContentTreeItem == treeItem) {
+    // No frames or iframes, so we can fire the doc load finished event early
+    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
+                            eRemoveDupes);
   }
-  if (rootContentTreeItem != treeItem) {
-    nsCOMPtr<nsIAccessibleDocument> rootContentDocAccessible =
-      GetDocAccessibleFor(rootContentTreeItem);
-    nsCOMPtr<nsIAccessible> rootContentAccessible =
-      do_QueryInterface(rootContentDocAccessible);
-    if (!rootContentAccessible) {
-      return;
-    }
-    PRUint32 state, extState;
-    rootContentAccessible->GetFinalState(&state, &extState);
-    if ((state & nsIAccessibleStates::STATE_BUSY) ||
-        (extState & nsIAccessibleStates::EXT_STATE_DEFUNCT)) {
-      // Don't fire page load events on subdocuments for initial page load of entire page
-      return;
-    }
-  }
-
-  // No frames or iframes, so we can fire the doc load finished event early
-  FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
-                          eRemoveDupes);
 }
 
 PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
                                                   nsIDOMNode *aNode,
                                                   nsIDOMEvent *aFocusEvent,
                                                   PRBool aForceEvent,
                                                   PRBool aIsAsynch)
 {
@@ -627,19 +609,16 @@ nsresult nsRootAccessible::HandleEventWi
     // so that we don't destroy something still in use, like wizard page. 
     // And we only get cached document accessible to destroy, so that we don't
     // create it just to destroy it.
     nsCOMPtr<nsIDocument> doc(do_QueryInterface(aTargetNode));
     nsCOMPtr<nsIAccessibleDocument> accDoc = GetDocAccessibleFor(doc);
     nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
     if (privateAcc) {
       privateAcc->Shutdown();
-      // Remove from the cache after Shutdown(), so that Shutdown() procedures
-      // can find the doc or root accessible in the cache if they need it.
-      gGlobalDocAccessibleCache.Remove(static_cast<void*>(doc));
     }
     return NS_OK;
   }
 
   nsCOMPtr<nsIPresShell> eventShell = GetPresShellFor(aTargetNode);
   if (!eventShell) {
     return NS_OK;
   }
--- a/accessible/src/msaa/CAccessibleHyperlink.cpp
+++ b/accessible/src/msaa/CAccessibleHyperlink.cpp
@@ -116,27 +116,27 @@ CAccessibleHyperlink::get_anchorTarget(l
   VariantInit(aAnchorTarget);
 
   nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
   if (!acc)
     return E_FAIL;
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = acc->GetURI(aIndex, getter_AddRefs(uri));
-  if (NS_SUCCEEDED(rv))
+  if (NS_FAILED(rv) || !uri)
     return E_FAIL;
 
   nsCAutoString prePath;
   rv = uri->GetPrePath(prePath);
-  if (NS_SUCCEEDED(rv))
+  if (NS_FAILED(rv))
     return E_FAIL;
 
   nsCAutoString path;
   rv = uri->GetPath(path);
-  if (NS_SUCCEEDED(rv))
+  if (NS_FAILED(rv))
     return E_FAIL;
 
   nsAutoString stringURI;
   AppendUTF8toUTF16(prePath, stringURI);
   AppendUTF8toUTF16(path, stringURI);
 
   aAnchorTarget->vt = VT_BSTR;
   if (!::SysReAllocStringLen(&aAnchorTarget->bstrVal, stringURI.get(), stringURI.Length()))
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1389,16 +1389,19 @@ nsAccessibleWrap::get_uniqueID(long *uni
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_windowHandle(HWND *windowHandle)
 {
 __try {
+  *windowHandle = 0;
+  if (!mDOMNode)
+    return E_FAIL;
   void *handle = nsnull;
   nsresult rv = GetOwnerWindow(&handle);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   *windowHandle = reinterpret_cast<HWND>(handle);
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return S_OK;
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -157,21 +157,16 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
   }
 
   // Otherwise, the normal get_accChild() will do
   return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
-NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
-{
-  return nsDocAccessible::Shutdown();
-}
-
 NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
 {
   // Staying on the same page, jumping to a named anchor
   // Fire EVENT_SCROLLING_START on first leaf accessible -- because some
   // assistive technologies only cache the child numbers for leaf accessibles
   // the can only relate events back to their internal model if it's a leaf.
   // There is usually an accessible for the focus node, but if it's an empty text node
   // we have to move forward in the document to get one
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -82,13 +82,12 @@ public:
         /* [in] */ BSTR __RPC_FAR *commaSeparatedMediaTypes);
 
     // IAccessible
     // Override get_accChild so that it can get any child via the unique ID
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild( 
         /* [in] */ VARIANT varChild,
         /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
 
-    NS_IMETHOD Shutdown();
     NS_IMETHOD FireAnchorJumpEvent();
 };
 
 #endif
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -43,12 +43,15 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_bug368835.xul \
 		test_groupattrs.xul \
+		test_nsIAccessibleTable_1.html \
+		test_nsIAccessibleTable_2.html \
+		test_nsIAccessibleTable_3.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/test_bug368835.xul
+++ b/accessible/tests/mochitest/test_bug368835.xul
@@ -162,17 +162,17 @@
 
       SimpleTest.finish();
     }
 
     var gAccService = null;
 
     function doTest()
     {
-      // Check whether accessbility support is enabled.
+      // Check whether accessibility support is enabled.
       if (!("@mozilla.org/accessibleRetrieval;1" in Components.classes)) {
         SimpleTest.finish();
         return;
       }
 
       // Activate accessibility, otherwise events aren't fired.
       gAccService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
                     getService(Components.interfaces.nsIAccessibleRetrieval);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleTable_1.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+ <head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript">
+
+function doTest()
+{
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var table = document.getElementById("table");
+  var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                   getService(Components.interfaces.nsIAccessibleRetrieval);
+  var accTable   = accService.getAccessibleFor(table).
+                   QueryInterface(Components.interfaces.nsIAccessibleTable);
+  var caption = accTable.caption;
+  is(caption.firstChild.name, "Test Table", "wrong text inside caption");
+  const nsIAccessNode = Components.interfaces.nsIAccessible;
+
+  is(caption.children.queryElementAt(0, nsIAccessNode).name, "Test Table",
+     "wrong text inside caption");
+
+  is(accTable.summary, "this is a test table for nsIAccessibleTable",
+     "wrong summary on table");
+  is(accTable.columns, 4,"wrong number of columns");
+  is(accTable.rows, 3, "wrong number of rows");
+
+  var s = window.getSelection();
+  if (s.rangeCount > 0)
+    s.removeAllRanges();
+
+  var cell = document.getElementById("col2b");
+  var range = document.createRange();
+  range.selectNode(cell);
+  s.addRange(range);
+
+  is(accTable.selectedCellsCount, 1,"only one cell selected");
+  cell = document.getElementById("col2a");
+  range.selectNode(cell);
+  s.addRange(range);
+  cell = document.getElementById("col2c");
+  range.selectNode(cell);
+  s.addRange(range);
+  is(accTable.selectedColumnsCount, 1, "only one column selected");
+  cell = document.getElementById("row2a");
+  range.selectNode(cell);
+  s.addRange(range);
+  cell = document.getElementById("row2b");
+  range.selectNode(cell);
+  s.addRange(range);
+  cell = document.getElementById("row2c");
+  range.selectNode(cell);
+  s.addRange(range);
+
+  is(accTable.selectedRowsCount, 1, "no cells selected");
+
+  var rowheader;
+  var works;
+  works = true;
+  try {
+    rowheader  = accTable.rowHeader;
+  }
+  catch (e) {
+    works = false;
+  }
+  todo(works, "rowHeader should not throw");
+
+  var columnHeader;
+  works = true;
+  try {
+    columnHeader = accTable.columnHeader;
+    columnHeaderIndex =columnHeader.getIndexAt(0,2);
+    is(columnHeaderIndex, 2, "columnheaderindex is wrong");
+  }
+  catch (e) {
+    works = false;
+  }
+  todo(works, "columnHeader should not throw");
+
+  var columnDescription;
+  works = true;
+  try{
+    columnDescription = accTable.getColumnDescription(1);
+  }
+  catch (e) {
+    works = false;
+  }
+  todo(works, "columnDescription should not throw");
+
+  var rowDescription;
+  works = true;
+  try {
+    rowDescription = accTable.getRowDescription(1);
+  }
+  catch (e) {
+    works = false;
+  }
+  todo(works, "rowDescription should not throw");
+  SimpleTest.finish();
+}
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+  </script>
+ </head>
+ <body >
+
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <!-- Test Table -->
+  <br><br><b> Testing Table:</b><br><br>
+  <center>
+   <table id="table" border="1"
+          summary="this is a test table for nsIAccessibleTable" >
+    <caption>Test Table</caption>
+    <thead>
+     <tr>
+      <th></th>
+      <th>columnHeader_1</th>
+      <th id ="col2a">columnHeader_2</th>
+      <th>columnHeader_3</th>
+     </tr>
+    </thead>
+    <tr>
+     <th id="row2a">rowHeader_1</th>
+     <td id="row2b">row1_column1</td>
+     <td id ="col2b">row1_column2</td>
+     <td id="row2c">row1_column3</td>
+    </tr>
+    <tr>
+     <th>rowHeader_2</th>
+     <td>row2_column1</td>
+     <td id ="col2c">row2_column2</td>
+     <td>row2_column3</td>
+    </tr>
+   </table>
+  </center>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleTable_2.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+ <head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <title> nsIAccessibleTable Interface Test Case </title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript">
+
+function doTest()
+{
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var table = document.getElementById("table");
+  var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                   getService(Components.interfaces.nsIAccessibleRetrieval);
+
+  var accTable = accService.getAccessibleFor(table).
+                 QueryInterface(Components.interfaces.nsIAccessibleTable);
+
+  is(accTable.getIndexAt(2,4), 17, "wrong index returned");
+  is(accTable.getColumnAtIndex(18), 5,"got wrong column");
+  is(accTable.getRowAtIndex(10), 1, "wrong row");
+  is(accTable.getColumnExtentAt(2,2), 2, "colspan wrong");
+  is(accTable.getColumnExtentAt(0,3), 2, "colspan wrong");
+  is(accTable.getColumnExtentAt(3,5), 1, "colspan");
+  is(accTable.getRowExtentAt(0,7), 4, "rowspan wrong");
+  is(accTable.getRowExtentAt(2,7), 4,"rowspan wrong");
+  is(accTable.getColumnExtentAt(2,3), 1, "colspan wrong");
+  is(accTable.cellRefAt(2,1).firstChild.name, "c1", "wrong cell");
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+  </script>
+ </head>
+ <body>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <!-- Test Table -->
+  <br><br><b> Testing Table:</b><br><br>
+  <center>
+   <table cellpadding="2" cellspacing="2" border="1" width="50%" id="table">
+    <tbody>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="1" colspan="2"><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="4" colspan="1"><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td rowspan="2" colspan="2">c1</td>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="2" colspan="1"><br></td>
+      <td><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+     </tr>
+    </tbody>
+   </table>
+  </center>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleTable_3.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+ <head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <title> nsIAccessibleTable Interface Test Case </title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript">
+
+function doTest()
+{
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var table = document.getElementById("table");
+  var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                   getService(Components.interfaces.nsIAccessibleRetrieval);
+
+  var accTable = accService.getAccessibleFor(table).
+                 QueryInterface(Components.interfaces.nsIAccessibleTable);
+    
+  is(accTable.getSelectedCells({}).length, 0, "no cell selected");
+  for (var i = 0; i < 4; i++) {
+    accTable.selectRow(i);
+    for (var j = 0; j < 4; j++) {
+      if (i == j) {
+        ok(accTable.isRowSelected(i),"row not selected");
+      }
+      else {
+        todo(!accTable.isRowSelected(i),"row selected");
+      }
+    }
+  }
+  todo_is(accTable.selectedRowsCount, 1, "only one row should be selected");
+  todo_is(accTable.getSelectedRows({}).length, 1,
+         "only one row should be selected");
+
+  for (var i = 0; i < 4; i++) {
+    accTable.unselectRow(i);
+    ok(!accTable.isRowSelected(i), "row still selected");
+  }
+  todo_is(accTable.getSelectedCells({}).length, 0, "no cell selected");
+  todo_is(accTable.selectedCellsCount, 0, "no cell selected");
+  var s = window.getSelection();
+  if (s.rangeCount > 0)
+    s.removeAllRanges();
+
+  is(accTable.getSelectedCells({}).length, 0, "no cell selected");
+  is(accTable.selectedCellsCount, 0, "no cell selected");
+  for (var i = 0; i < 8; i++) {
+    accTable.selectColumn(i);
+    for (var j = 0; j < 8; j++) {
+      if (i ==j) {
+        ok(accTable.isColumnSelected(i),"column not selected");
+      }
+      else {
+        todo(!accTable.isColumnSelected(i),"column is selected");
+      }
+    }
+  }
+  todo_is(accTable.selectedColumnsCount, 1,
+          "only one column should be selected");
+  todo_is(accTable.getSelectedColumns({}).length, 1,
+          "only one column should be selected");
+  for (var i = 0; i < 8; i++) {
+    accTable.unselectColumn(i);
+    ok(!accTable.isColumnSelected(i),"column still selected");
+  }
+  is(accTable.selectedColumnsCount, 0, "no column should be selected");
+  ok(!accTable.isProbablyForLayout(), "table is not for layout");
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+  </script>
+ </head>
+ <body>
+
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+
+  <!-- Test Table -->
+  <br><br><b> Testing Table:</b><br><br>
+  <center>
+   <table cellpadding="2" cellspacing="2" border="1" width="50%" id="table">
+    <tbody>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="1" colspan="2"><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="4" colspan="1"><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td rowspan="2" colspan="2">c1</td>
+      <td><br></td>
+      <td><br></td>
+      <td rowspan="2" colspan="1"><br></td>
+      <td><br></td>
+     </tr>
+     <tr>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+      <td><br></td>
+     </tr>
+    </tbody>
+   </table>
+  </center>
+ </body>
+</html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -192,29 +192,31 @@ pref("browser.startup.page",            
 pref("browser.startup.homepage",            "resource:/browserconfig.properties");
 
 pref("browser.cache.disk.capacity",         50000);
 pref("browser.enable_automatic_image_resizing", true);
 pref("browser.chrome.site_icons", true);
 pref("browser.chrome.favicons", true);
 pref("browser.formfill.enable", true);
 pref("browser.warnOnQuit", true);
+pref("browser.warnOnRestart", true);
 
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.clickSelectsAll", false);
 #else
 pref("browser.urlbar.clickSelectsAll", true);
 #endif
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.doubleClickSelectsAll", true);
 #else
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 pref("browser.urlbar.autoFill", false);
 pref("browser.urlbar.matchOnlyTyped", false);
+pref("browser.urlbar.filter.javascript", true);
 
 // the maximum number of results to show in autocomplete when doing richResults
 pref("browser.urlbar.maxRichResults", 25);
 // Size of "chunks" affects the number of places to process between each search
 // timeout (ms). Too big and the UI will be unresponsive; too small and we'll
 // be waiting on the timeout too often without many results.
 pref("browser.urlbar.search.chunkSize", 1000);
 pref("browser.urlbar.search.timeout", 50);
@@ -359,17 +361,17 @@ pref("privacy.item.siteprefs",   false);
 pref("privacy.item.sessions",    true);
 pref("privacy.item.offlineApps", false);
 
 pref("privacy.sanitize.sanitizeOnShutdown", false);
 pref("privacy.sanitize.promptOnSanitize", true);
 
 pref("network.proxy.share_proxy_settings",  false); // use the same proxy settings for all protocols
 
-pref("network.cookie.cookieBehavior",       1); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
+pref("network.cookie.cookieBehavior", 0); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
 
 // l12n and i18n
 pref("intl.accept_languages", "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.static", "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.more1",  "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.more2",  "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.more3",  "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.more4",  "chrome://global/locale/intl.properties");
@@ -566,26 +568,26 @@ pref("gecko.handlerService.allowRegister
 #ifdef MOZ_SAFE_BROWSING
 // Safe browsing does nothing unless this pref is set
 pref("browser.safebrowsing.enabled", true);
 
 // Prevent loading of pages identified as malware
 pref("browser.safebrowsing.malware.enabled", true);
 
 // Non-enhanced mode (local url lists) URL list to check for updates
-pref("browser.safebrowsing.provider.0.updateURL", "http://sb.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.1");
+pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.1");
 
 pref("browser.safebrowsing.dataProvider", 0);
 
 // Does the provider name need to be localizable?
 pref("browser.safebrowsing.provider.0.name", "Google");
-pref("browser.safebrowsing.provider.0.lookupURL", "http://sb.google.com/safebrowsing/lookup?sourceid=firefox-antiphish&features=TrustRank&client={moz:client}&appver={moz:version}&");
-pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/getkey?client={moz:client}&");
-pref("browser.safebrowsing.provider.0.reportURL", "http://sb.google.com/safebrowsing/report?");
-pref("browser.safebrowsing.provider.0.gethashURL", "http://sb.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.1");
+pref("browser.safebrowsing.provider.0.lookupURL", "http://safebrowsing.clients.google.com/safebrowsing/lookup?sourceid=firefox-antiphish&features=TrustRank&client={moz:client}&appver={moz:version}&");
+pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.1");
+pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
+pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.1");
 
 // privacy policy -- Both url and fallbackurl must exist, although they may
 // point to the same file.  fallbackurl must be a chrome url
 pref("browser.safebrowsing.provider.0.privacy.url", "http://www.google.com/tools/firefox/firefox_privacy.html?hl=%LOCALE%");
 pref("browser.safebrowsing.provider.0.privacy.fallbackurl", "chrome://browser/content/preferences/phishEULA.xhtml");
 
 // HTML report pages
 pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
@@ -593,28 +595,31 @@ pref("browser.safebrowsing.provider.0.re
 pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
 
 // FAQ URL
 pref("browser.safebrowsing.warning.infoURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
 
 // Name of the about: page contributed by safebrowsing to handle display of error
 // pages on phishing/malware hits.  (bug 399233)
 pref("urlclassifier.alternate_error_page", "blocked");
+
+// The number of random entries to send with a gethash request.
+pref("urlclassifier.gethashnoise", 4);
 #endif
 
 // defaults to true
 pref("browser.EULA.2.accepted", true);
 
 // if we rev the EULA again, we should bump this so users agree to the new EULA
 pref("browser.EULA.version", 2);
 
 pref("browser.sessionstore.enabled", true);
 pref("browser.sessionstore.resume_from_crash", true);
 pref("browser.sessionstore.resume_session_once", false);
- 
+
 // minimal interval between two save operations in milliseconds
 pref("browser.sessionstore.interval", 10000);
 // maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
 // (NB: POSTDATA will be saved either entirely or not at all)
 pref("browser.sessionstore.postdata", 0);
 // on which sites to save text data, POSTDATA and cookies
 // 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
 pref("browser.sessionstore.privacy_level", 1);
@@ -632,16 +637,20 @@ pref("browser.places.importBookmarksHTML
 // if false, will add the "Smart Bookmarks" folder to the personal toolbar
 pref("browser.places.createdSmartBookmarks", false);
 
 // If true, will migrate uri post-data annotations to
 // bookmark post-data annotations (bug 398914)
 // XXX to be removed after beta 2 (bug 391419)
 pref("browser.places.migratePostDataAnnotations", true);
 
+// If true, will update the Smart Bookmarks uri for
+// recent tags (bug 385245). Useful just for FX3 beta users.
+pref("browser.places.updateRecentTagsUri", true);
+
 // the (maximum) number of the recent visits to sample
 // when calculating frecency
 pref("places.frecency.numVisits", 10);
 
 // Number of records to update frecency for when idle.
 pref("places.frecency.numCalcOnIdle", 50);
 
 // Number of records to update frecency for when migrating from
@@ -694,13 +703,16 @@ pref("browser.identity.ssl_domain_displa
 
 // True if the user should be prompted when a web application supports
 // offline apps.
 pref("browser.offline-apps.notify", true);
 
 // if true, use full page zoom instead of text zoom
 pref("browser.zoom.full", true);
 
+// Whether or not to save and restore zoom levels on a per-site basis.
+pref("browser.zoom.siteSpecific", true);
+
 // replace newlines with spaces when pasting into <input type="text"> fields
 pref("editor.singleLine.pasteNewlines", 2);
 
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -179,46 +179,55 @@
                 accesskey="&keywordfield.accesskey;"
                 oncommand="AddKeywordForSearchField();"/>
       <menuitem id="context-searchselect"
                 accesskey="&search.accesskey;"
                 oncommand="BrowserSearch.loadSearch(getBrowserSelection(), true);"/>
       <menuseparator id="frame-sep"/>
       <menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
         <menupopup>
-          <menuitem label="&showOnlyThisFrameCmd.label;"
+          <menuitem id="context-showonlythisframe"
+                    label="&showOnlyThisFrameCmd.label;"
                     accesskey="&showOnlyThisFrameCmd.accesskey;"
                     oncommand="gContextMenu.showOnlyThisFrame();"/>
-          <menuitem label="&openFrameCmd.label;"
+          <menuitem id="context-openframe"
+                    label="&openFrameCmd.label;"
                     accesskey="&openFrameCmd.accesskey;"
                     oncommand="gContextMenu.openFrame();"/>
-          <menuitem label="&openFrameCmdInTab.label;"
+          <menuitem id="context-openframeintab"
+                    label="&openFrameCmdInTab.label;"
                     accesskey="&openFrameCmdInTab.accesskey;"
                     oncommand="gContextMenu.openFrameInTab();"/>
           <menuseparator/>
-          <menuitem label="&reloadFrameCmd.label;"
+          <menuitem id="context-reloadframe"
+                    label="&reloadFrameCmd.label;"
                     accesskey="&reloadFrameCmd.accesskey;"
                     oncommand="gContextMenu.reloadFrame();"/>
           <menuseparator/>
-          <menuitem label="&bookmarkThisFrameCmd.label;"
+          <menuitem id="context-bookmarkframe"
+                    label="&bookmarkThisFrameCmd.label;"
                     accesskey="&bookmarkThisFrameCmd.accesskey;"
                     oncommand="gContextMenu.addBookmarkForFrame();"/>
-          <menuitem label="&saveFrameCmd.label;"
+          <menuitem id="context-saveframe"
+                    label="&saveFrameCmd.label;"
                     accesskey="&saveFrameCmd.accesskey;"
                     oncommand="saveDocument(gContextMenu.target.ownerDocument);"/>
           <menuseparator/>
-          <menuitem label="&printFrameCmd.label;"
+          <menuitem id="context-printframe"
+                    label="&printFrameCmd.label;"
                     accesskey="&printFrameCmd.accesskey;"
                     oncommand="gContextMenu.printFrame();"/>
           <menuseparator/>
-          <menuitem label="&viewFrameSourceCmd.label;"
+          <menuitem id="context-viewframesource"
+                    label="&viewFrameSourceCmd.label;"
                     accesskey="&viewFrameSourceCmd.accesskey;"
                     oncommand="gContextMenu.viewFrameSource();"
                     observes="isFrameImage"/>
-          <menuitem label="&viewFrameInfoCmd.label;"
+          <menuitem id="context-viewframeinfo"
+                    label="&viewFrameInfoCmd.label;"
                     accesskey="&viewFrameInfoCmd.accesskey;"
                     oncommand="gContextMenu.viewFrameInfo();"/>
         </menupopup>
       </menu>
       <menuseparator id="context-sep-properties"/>
       <menuitem id="context-viewpartialsource-selection"
                 label="&viewPartialSourceForSelectionCmd.label;"
                 accesskey="&viewPartialSourceCmd.accesskey;"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -577,22 +577,22 @@ var BookmarksEventHandler = {
    */
   onClick: function BT_onClick(aEvent) {
     // Only handle middle-clicks.
     if (aEvent.button != 1)
       return;
 
     var target = aEvent.originalTarget;
     var view = PlacesUtils.getViewForNode(target);
-    if (PlacesUtils.nodeIsFolder(view.selectedNode)) {
+    if (target.node && PlacesUtils.nodeIsFolder(target.node)) {
       // Don't open the root folder in tabs when the empty area on the toolbar
       // is middle-clicked or when a non-bookmark item except for Open in Tabs)
       // in a bookmarks menupopup is middle-clicked.
-      if (!view.controller.rootNodeIsSelected())
-        view.controller.openSelectionInTabs(aEvent);
+      if (target.localName == "menu" || target.localName == "toolbarbutton")
+        PlacesUtils.openContainerNodeInTabs(target.node, aEvent);
     }
     else
       this.onCommand(aEvent);
 
     // If this event bubbled up from a menu or menuitem,
     // close the menus.
     if (target.localName == "menu" ||
         target.localName == "menuitem") {
@@ -619,21 +619,18 @@ var BookmarksEventHandler = {
    * Handler for command event for an item in the bookmarks toolbar.
    * Menus and submenus from the folder buttons bubble up to this handler.
    * Opens the item.
    * @param aEvent 
    *        DOMEvent for the command
    */
   onCommand: function BM_onCommand(aEvent) {
     var target = aEvent.originalTarget;
-    if (target.node) {
-      PlacesUtils.getViewForNode(target)
-                 .controller
-                 .openSelectedNodeWithEvent(aEvent);
-    }
+    if (target.node)
+      PlacesUtils.openNodeWithEvent(target.node, aEvent);
   },
 
   /**
    * Handler for popupshowing event for an item in bookmarks toolbar or menu.
    * If the item isn't the main bookmarks menu, add an "Open All in Tabs"
    * menuitem to the bottom of the popup.
    * @param event 
    *        DOMEvent for popupshowing
@@ -1022,17 +1019,17 @@ var PlacesStarButton = {
 /**
  * Various migration tasks.
  */
 function placesMigrationTasks() {
   // bug 398914 - move all post-data annotations from URIs to bookmarks
   // XXX - REMOVE ME FOR BETA 3 (bug 391419)
   if (gPrefService.getBoolPref("browser.places.migratePostDataAnnotations")) {
     const annosvc = PlacesUtils.annotations;
-    const bmsvc = PlacesUtils.bookmarks;
+    var bmsvc = PlacesUtils.bookmarks;
     const oldPostDataAnno = "URIProperties/POSTData";
     var pages = annosvc.getPagesWithAnnotation(oldPostDataAnno, {});
     for (let i = 0; i < pages.length; i++) {
       try {
         let uri = pages[i];
         var postData = annosvc.getPageAnnotation(uri, oldPostDataAnno);
         // We can't know which URI+keyword combo this postdata was for, but
         // it's very likely that if this URI is bookmarked and has a keyword
@@ -1046,9 +1043,35 @@ function placesMigrationTasks() {
             annosvc.setItemAnnotation(bookmarks[i], POST_DATA_ANNO, postData, 0, annosvc.EXPIRE_NEVER); 
         }
         // Remove the old annotation.
         annosvc.removePageAnnotation(uri, oldPostDataAnno);
       } catch(ex) {}
     }
     gPrefService.setBoolPref("browser.places.migratePostDataAnnotations", false);
   }
+
+  if (gPrefService.getBoolPref("browser.places.updateRecentTagsUri")) {
+    var bmsvc = PlacesUtils.bookmarks;
+    var tagsFolder = bmsvc.tagsFolder;
+    var oldUriSpec = "place:folder=" + tagsFolder + "&group=3&queryType=1"+
+                     "&applyOptionsToContainers=1&sort=12&maxResults=10";
+
+    var maxResults = 10;
+    var newUriSpec = "place:type=" + 
+                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
+                     "&sort=" + 
+                     Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
+                     "&maxResults=" + maxResults;
+                     
+    var ios = Cc["@mozilla.org/network/io-service;1"].
+              getService(Ci.nsIIOService);
+
+    var oldUri = ios.newURI(oldUriSpec, null, null);
+    var newUri = ios.newURI(newUriSpec, null, null);
+
+    let bookmarks = bmsvc.getBookmarkIdsForURI( oldUri, {});
+    for (let i = 0; i < bookmarks.length; i++) {
+      bmsvc.changeBookmarkURI( bookmarks[i], newUri);
+    }
+    gPrefService.setBoolPref("browser.places.updateRecentTagsUri", false);
+  }
 }
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -187,16 +187,19 @@
 # "E" is. People mourning the loss of Ctrl+K for emacs compat can switch their GTK
 # system setting to use emacs emulation, and we should respect it. Focus-Search-Box
 # is a fundamental keybinding and we are maintaining a XP binding so that it is easy
 # for people to switch to Linux.
 #
 # Do *not* tamper with these values without talking to ben@mozilla.org
 #
     <key id="key_search" key="&searchFocus.commandkey;" command="Tools:Search" modifiers="accel"/>
+#ifdef XP_MACOSX
+    <key id="key_search2" key="&findOnCmd.commandkey;" command="Tools:Search" modifiers="accel,alt"/>
+#endif
 #ifdef XP_WIN
     <key id="key_search2" key="&searchFocus.commandkey2;" command="Tools:Search" modifiers="accel"/>
 #endif
 #ifdef XP_GNOME
     <key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/>
     <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #else
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
--- a/browser/base/content/browser-textZoom.js
+++ b/browser/base/content/browser-textZoom.js
@@ -74,23 +74,34 @@ var FullZoom = {
 
   // Content Pref Service
   get _cps FullZoom_get__cps() {
     delete this._cps;
     return this._cps = Cc["@mozilla.org/content-pref/service;1"].
                        getService(Ci.nsIContentPrefService);
   },
 
+  get _prefBranch FullZoom_get__prefBranch() {
+    delete this._prefBranch;
+    return this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
+                              getService(Ci.nsIPrefBranch2);
+  },
+
+  // browser.zoom.siteSpecific preference cache
+  siteSpecific: undefined,
+
 
   //**************************************************************************//
   // nsISupports
 
   // We can't use the Ci shortcut here because it isn't defined yet.
   interfaces: [Components.interfaces.nsIDOMEventListener,
+               Components.interfaces.nsIObserver,
                Components.interfaces.nsIContentPrefObserver,
+               Components.interfaces.nsISupportsWeakReference,
                Components.interfaces.nsISupports],
 
   QueryInterface: function FullZoom_QueryInterface(aIID) {
     if (!this.interfaces.some(function (v) aIID.equals(v)))
       throw Cr.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
@@ -99,19 +110,26 @@ var FullZoom = {
   // Initialization & Destruction
 
   init: function FullZoom_init() {
     // Listen for scrollwheel events so we can save scrollwheel-based changes.
     window.addEventListener("DOMMouseScroll", this, false);
 
     // Register ourselves with the service so we know when our pref changes.
     this._cps.addObserver(this.name, this);
+
+    // Listen for changes to the browser.zoom.siteSpecific preference so we can
+    // enable/disable per-site saving and restoring of zoom levels accordingly.
+    this.siteSpecific =
+      this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
+    this._prefBranch.addObserver("browser.zoom.siteSpecific", this, true);
   },
 
   destroy: function FullZoom_destroy() {
+    this._prefBranch.removeObserver("browser.zoom.siteSpecific", this);
     this._cps.removeObserver(this.name, this);
     window.removeEventListener("DOMMouseScroll", this, false);
     delete this._cps;
   },
 
 
   //**************************************************************************//
   // Event Handlers
@@ -159,16 +177,31 @@ var FullZoom = {
     // make sure to observe them so we can update the cache when they change.
 
     // We have to call _applySettingToPref in a timeout because we handle
     // the event before the event state manager has a chance to apply the zoom
     // during nsEventStateManager::PostHandleEvent.
     window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
   },
 
+  // nsIObserver
+
+  observe: function (aSubject, aTopic, aData) {
+    switch(aTopic) {
+      case "nsPref:changed":
+        switch(aData) {
+          case "browser.zoom.siteSpecific":
+            this.siteSpecific =
+              this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
+            break;
+        }
+        break;
+    }
+  },
+
   // nsIContentPrefObserver
 
   onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
     if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
       this._applyPrefToSetting(aValue);
     else if (aGroup == null) {
       this.globalValue = this._ensureValid(aValue);
 
@@ -252,32 +285,32 @@ var FullZoom = {
    * and perhaps the same is true for full zoom
    * (although DocumentViewerImpl::SetFullZoom doesn't mention it).
    *
    * So when we apply new zoom values to the browser, we simply set the zoom.
    * We don't check first to see if the new value is the same as the current
    * one.
    **/
   _applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue) {
-    if (gInPrintPreviewMode)
+    if (!this.siteSpecific || gInPrintPreviewMode)
       return;
 
     try {
       if (typeof aValue != "undefined")
         ZoomManager.zoom = this._ensureValid(aValue);
       else if (typeof this.globalValue != "undefined")
         ZoomManager.zoom = this.globalValue;
       else
         ZoomManager.zoom = 1;
     }
     catch(ex) {}
   },
 
   _applySettingToPref: function FullZoom__applySettingToPref() {
-    if (gInPrintPreviewMode)
+    if (!this.siteSpecific || gInPrintPreviewMode)
       return;
 
     var zoomLevel = ZoomManager.zoom;
     this._cps.setPref(gBrowser.currentURI, this.name, zoomLevel);
   },
 
   _removePref: function FullZoom__removePref() {
     this._cps.removePref(gBrowser.currentURI, this.name);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -18,16 +18,21 @@ toolbar[printpreview="true"] {
 #PopupAutoComplete {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
 }
 
 #PopupAutoCompleteRichResult {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
 }
 
+#urlbar-throbber:not([busy="true"]),
+#urlbar-throbber[busy="true"] + #page-proxy-favicon {
+  display: none;
+} 
+
 /* ::::: Unified Back-/Forward Button ::::: */
 #back-forward-dropmarker > image ,
 #back-forward-dropmarker > label {
   display: none;
 }
 .unified-nav-current {
   font-weight: bold;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -70,19 +70,17 @@ const MAX_HISTORY_MENU_ITEMS = 15;
 const GLUE_CID = "@mozilla.org/browser/browserglue;1";
 
 var gURIFixup = null;
 var gCharsetMenu = null;
 var gLastBrowserCharset = null;
 var gPrevCharset = null;
 var gURLBar = null;
 var gFindBar = null;
-var gProxyButton = null;
 var gProxyFavIcon = null;
-var gProxyDeck = null;
 var gNavigatorBundle = null;
 var gIsLoadingBlank = false;
 var gLastValidURLStr = "";
 var gMustLoadSidebar = false;
 var gProgressMeterPanel = null;
 var gProgressCollapseTimer = null;
 var gPrefService = null;
 var appCore = null;
@@ -1963,29 +1961,30 @@ function URLBarSetURI(aURI) {
       state = "valid";
     }
   }
 
   gURLBar.value = value;
   SetPageProxyState(state);
 }
 
-// If "ESC" is pressed in the url bar, we replace the urlbar's value with the url of the page
-// and highlight it, unless it is empty.
+// Replace the urlbar's value with the url of the page.
 function handleURLBarRevert() {
   var throbberElement = document.getElementById("navigator-throbber");
   var isScrolling = gURLBar.popupOpen;
 
   gBrowser.userTypedValue = null;
 
   // don't revert to last valid url unless page is NOT loading
   // and user is NOT key-scrolling through autocomplete list
   if ((!throbberElement || !throbberElement.hasAttribute("busy")) && !isScrolling) {
     URLBarSetURI();
-    if (gURLBar.value)
+
+    // If the value isn't empty and the urlbar has focus, select the value.
+    if (gURLBar.value && gURLBar.hasAttribute("focused"))
       gURLBar.select();
   }
 
   // tell widget to revert to last typed text only if the user
   // was scrolling when they hit escape
   return !isScrolling;
 }
 
@@ -2102,36 +2101,54 @@ function UpdateUrlbarSearchSplitterState
       splitter.setAttribute("resizeafter", "flex");
       splitter.className = "chromeclass-toolbar-additional";
     }
     urlbar.parentNode.insertBefore(splitter, ibefore);
   } else if (splitter)
     splitter.parentNode.removeChild(splitter);
 }
 
+var LocationBarHelpers = {
+  _timeoutID: null,
+
+  _searchBegin: function LocBar_searchBegin() {
+    function delayedBegin(self) {
+      self._timeoutID = null;
+      document.getElementById("urlbar-throbber").setAttribute("busy", "true");
+    }
+
+    this._timeoutID = setTimeout(delayedBegin, 500, this);
+  },
+
+  _searchComplete: function LocBar_searchComplete() {
+    // Did we finish the search before delayedBegin was invoked?
+    if (this._timeoutID) {
+      clearTimeout(this._timeoutID);
+      this._timeoutID = null;
+    }
+    document.getElementById("urlbar-throbber").removeAttribute("busy");
+  }
+};
+
 function UpdatePageProxyState()
 {
   if (gURLBar && gURLBar.value != gLastValidURLStr)
     SetPageProxyState("invalid");
 }
 
 function SetPageProxyState(aState)
 {
   if (!gURLBar)
     return;
 
-  if (!gProxyButton)
-    gProxyButton = document.getElementById("page-proxy-button");
   if (!gProxyFavIcon)
     gProxyFavIcon = document.getElementById("page-proxy-favicon");
-  if (!gProxyDeck)
-    gProxyDeck = document.getElementById("page-proxy-deck");
 
   gURLBar.setAttribute("pageproxystate", aState);
-  gProxyButton.setAttribute("pageproxystate", aState);
+  gProxyFavIcon.setAttribute("pageproxystate", aState);
 
   // the page proxy state is set to valid via OnLocationChange, which
   // gets called when we switch tabs.
   if (aState == "valid") {
     gLastValidURLStr = gURLBar.value;
     gURLBar.addEventListener("input", UpdatePageProxyState, false);
 
     PageProxySetIcon(gBrowser.mCurrentBrowser.mIconURL);
@@ -2145,31 +2162,27 @@ function PageProxySetIcon (aURL)
 {
   if (!gProxyFavIcon)
     return;
 
   if (!aURL)
     PageProxyClearIcon();
   else if (gProxyFavIcon.getAttribute("src") != aURL)
     gProxyFavIcon.setAttribute("src", aURL);
-  else if (gProxyDeck.selectedIndex != 1)
-    gProxyDeck.selectedIndex = 1;
 }
 
 function PageProxyClearIcon ()
 {
-  if (gProxyDeck.selectedIndex != 0)
-    gProxyDeck.selectedIndex = 0;
-  if (gProxyFavIcon.hasAttribute("src"))
-    gProxyFavIcon.removeAttribute("src");
-}
+  gProxyFavIcon.removeAttribute("src");
+}
+
 
 function PageProxyDragGesture(aEvent)
 {
-  if (gProxyButton.getAttribute("pageproxystate") == "valid") {
+  if (gProxyFavIcon.getAttribute("pageproxystate") == "valid") {
     nsDragAndDrop.startDrag(aEvent, proxyIconDNDObserver);
     return true;
   }
   return false;
 }
 
 function PageProxyClickHandler(aEvent)
 {
@@ -2964,30 +2977,30 @@ function FillHistoryMenu(aParent) {
     item.setAttribute("label", entry.title || entry.URI.spec);
     item.setAttribute("index", j);
 
     if (j != index) {
       try {
         let iconURL = Cc["@mozilla.org/browser/favicon-service;1"]
                          .getService(Ci.nsIFaviconService)
                          .getFaviconForPage(entry.URI).spec;
-        item.setAttribute("image", iconURL);
+        item.style.listStyleImage = "url(" + iconURL + ")";
       } catch (ex) {}
     }
 
     if (j < index) {
-      item.className = "unified-nav-back";
+      item.className = "unified-nav-back menuitem-iconic";
       item.setAttribute("tooltiptext", tooltipBack);
     } else if (j == index) {
       item.setAttribute("type", "radio");
       item.setAttribute("checked", "true");
       item.className = "unified-nav-current";
       item.setAttribute("tooltiptext", tooltipCurrent);
     } else {
-      item.className = "unified-nav-forward";
+      item.className = "unified-nav-forward menuitem-iconic";
       item.setAttribute("tooltiptext", tooltipForward);
     }
 
     aParent.appendChild(item);
   }
   return true;
 }
 
@@ -3117,29 +3130,35 @@ function BrowserToolboxCustomizeDone(aTo
 #ifdef TOOLBAR_CUSTOMIZATION_SHEET
   document.getElementById("customizeToolbarSheetIFrame").hidden = true;
   document.getElementById("customizeToolbarSheetPopup").hidePopup();
 #endif
 
   // Update global UI elements that may have been added or removed
   if (aToolboxChanged) {
     gURLBar = document.getElementById("urlbar");
-    gProxyButton = document.getElementById("page-proxy-button");
     gProxyFavIcon = document.getElementById("page-proxy-favicon");
-    gProxyDeck = document.getElementById("page-proxy-deck");
     gHomeButton.updateTooltip();
     gIdentityHandler._cacheElements();
     window.XULBrowserWindow.init();
 
     var backForwardDropmarker = document.getElementById("back-forward-dropmarker");
     if (backForwardDropmarker)
       backForwardDropmarker.disabled =
         document.getElementById('Browser:Back').hasAttribute('disabled') &&
         document.getElementById('Browser:Forward').hasAttribute('disabled');
 
+    // support downgrading to Firefox 2.0
+    var navBar = document.getElementById("nav-bar");
+    navBar.setAttribute("currentset",
+                        navBar.getAttribute("currentset")
+                              .replace("unified-back-forward-button",
+                                "unified-back-forward-button,back-button,forward-button"));
+    document.persist(navBar.id, "currentset");
+
 #ifndef XP_MACOSX
     updateEditUIVisibility();
 #endif
   }
 
   UpdateUrlbarSearchSplitterState();
 
   gHomeButton.updatePersonalToolbarStyle();
@@ -4975,22 +4994,28 @@ var BrowserOffline = {
   }
 };
 
 var OfflineApps = {
   /////////////////////////////////////////////////////////////////////////////
   // OfflineApps Public Methods
   init: function ()
   {
-    // XXX: empty init left as a placeholder for patch in bug 397417
+    var obs = Cc["@mozilla.org/observer-service;1"].
+              getService(Ci.nsIObserverService);
+    obs.addObserver(this, "dom-storage-warn-quota-exceeded", false);
+    obs.addObserver(this, "offline-cache-update-completed", false);
   },
 
   uninit: function ()
   {
-    // XXX: empty uninit left as a placeholder for patch in bug 397417
+    var obs = Cc["@mozilla.org/observer-service;1"].
+              getService(Ci.nsIObserverService);
+    obs.removeObserver(this, "dom-storage-warn-quota-exceeded");
+    obs.removeObserver(this, "offline-cache-update-completed");
   },
 
   /////////////////////////////////////////////////////////////////////////////
   // OfflineApps Implementation Methods
 
   // XXX: _getBrowserWindowForContentWindow and _getBrowserForContentWindow
   // were taken from browser/components/feeds/src/WebContentConverter.
   _getBrowserWindowForContentWindow: function(aContentWindow) {
@@ -5008,16 +5033,102 @@ var OfflineApps = {
     aContentWindow = aContentWindow.top;
     var browsers = aBrowserWindow.getBrowser().browsers;
     for (var i = 0; i < browsers.length; ++i) {
       if (browsers[i].contentWindow == aContentWindow)
         return browsers[i];
     }
   },
 
+  _getManifestURI: function(aWindow) {
+    var attr = aWindow.document.documentElement.getAttribute("manifest");
+    if (!attr) return null;
+
+    try {
+      var ios = Cc["@mozilla.org/network/io-service;1"].
+                getService(Ci.nsIIOService);
+
+      var contentURI = ios.newURI(aWindow.location.href, null, null);
+      return ios.newURI(attr, aWindow.document.characterSet, contentURI);
+    } catch (e) {
+      return null;
+    }
+  },
+
+  // A cache update isn't tied to a specific window.  Try to find
+  // the best browser in which to warn the user about space usage
+  _getBrowserForCacheUpdate: function(aCacheUpdate) {
+    // Prefer the current browser
+    var uri = this._getManifestURI(gBrowser.mCurrentBrowser.contentWindow);
+    if (uri && uri.equals(aCacheUpdate.manifestURI)) {
+      return gBrowser.mCurrentBrowser;
+    }
+
+    var browsers = getBrowser().browsers;
+    for (var i = 0; i < browsers.length; ++i) {
+      uri = this._getManifestURI(browsers[i].contentWindow);
+      if (uri && uri.equals(aCacheUpdate.manifestURI)) {
+        return browsers[i];
+      }
+    }
+
+    return null;
+  },
+
+  _warnUsage: function(aBrowser, aURI) {
+    if (!aBrowser)
+      return;
+
+    var notificationBox = gBrowser.getNotificationBox(aBrowser);
+    var notification = notificationBox.getNotificationWithValue("offline-app-usage");
+    if (!notification) {
+      var bundle_browser = document.getElementById("bundle_browser");
+
+      var buttons = [{
+          label: bundle_browser.getString("offlineApps.manageUsage"),
+          accessKey: bundle_browser.getString("offlineApps.manageUsageAccessKey"),
+          callback: OfflineApps.manage
+        }];
+
+      var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
+      const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
+      var message = bundle_browser.getFormattedString("offlineApps.usage",
+                                                      [ aURI.host,
+                                                        warnQuota / 1024 ]);
+
+      notificationBox.appendNotification(message, "offline-app-usage",
+                                         "chrome://browser/skin/Info.png",
+                                         priority, buttons);
+    }
+
+    // Now that we've warned once, prevent the warning from showing up
+    // again.
+    var pm = Cc["@mozilla.org/permissionmanager;1"].
+             getService(Ci.nsIPermissionManager);
+    pm.add(aURI, "offline-app",
+           Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
+  },
+
+  _checkUsage: function(aURI) {
+    var pm = Cc["@mozilla.org/permissionmanager;1"].
+             getService(Ci.nsIPermissionManager);
+
+    // if the user has already allowed excessive usage, don't bother checking
+    if (pm.testExactPermission(aURI, "offline-app") !=
+        Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN) {
+      var usage = getOfflineAppUsage(aURI.asciiHost);
+      var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
+      if (usage >= warnQuota * 1024) {
+        return true;
+      }
+    }
+
+    return false;
+  },
+
   offlineAppRequested: function(aContentWindow) {
     if (!gPrefService.getBoolPref("browser.offline-apps.notify")) {
       return;
     }
 
     var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
     var browser = this._getBrowserForContentWindow(browserWindow,
                                                    aContentWindow);
@@ -5082,31 +5193,66 @@ var OfflineApps = {
 
   disallowSite: function() {
     var currentURI = gBrowser.selectedBrowser.webNavigation.currentURI;
     var pm = Cc["@mozilla.org/permissionmanager;1"].
              getService(Ci.nsIPermissionManager);
     pm.add(currentURI, "offline-app", Ci.nsIPermissionManager.DENY_ACTION);
   },
 
+  manage: function() {
+    openAdvancedPreferences("networkTab");
+  },
+
   _startFetching: function() {
     var manifest = content.document.documentElement.getAttribute("manifest");
     if (!manifest)
       return;
 
     var ios = Cc["@mozilla.org/network/io-service;1"].
               getService(Ci.nsIIOService);
 
     var contentURI = ios.newURI(content.location.href, null, null);
     var manifestURI = ios.newURI(manifest, content.document.characterSet,
                                  contentURI);
 
     var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
                         getService(Ci.nsIOfflineCacheUpdateService);
     updateService.scheduleUpdate(manifestURI, contentURI);
+  },
+
+  /////////////////////////////////////////////////////////////////////////////
+  // nsIObserver
+  observe: function (aSubject, aTopic, aState)
+  {
+    if (aTopic == "dom-storage-warn-quota-exceeded") {
+      if (aSubject) {
+        var uri = Cc["@mozilla.org/network/io-service;1"].
+                  getService(Ci.nsIIOService).
+                  newURI(aSubject.location.href, null, null);
+
+        if (OfflineApps._checkUsage(uri)) {
+          var browserWindow =
+            this._getBrowserWindowForContentWindow(aSubject);
+          var browser = this._getBrowserForContentWindow(browserWindow,
+                                                         aSubject);
+          OfflineApps._warnUsage(browser, uri);
+        }
+      }
+    } else if (aTopic == "offline-cache-update-completed") {
+      var cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
+
+      var uri = cacheUpdate.manifestURI;
+      if (OfflineApps._checkUsage(uri)) {
+        var browser = this._getBrowserForCacheUpdate(cacheUpdate);
+        if (browser) {
+          OfflineApps._warnUsage(browser, cacheUpdate.manifestURI);
+        }
+      }
+    }
   }
 };
 
 function WindowIsClosing()
 {
   var browser = getBrowser();
   var cn = browser.tabContainer.childNodes;
   var numtabs = cn.length;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -85,16 +85,17 @@
 <script type="application/javascript" src="chrome://browser/content/places/editBookmarkOverlay.js"/>
 
 # All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the 
 # browser-sets.inc file for sharing with hiddenWindow.xul.
 #include browser-sets.inc
 
   <popupset id="mainPopupSet">
     <menupopup id="backForwardMenu"
+               chromedir="&locale.dir;"
                onpopupshowing="return FillHistoryMenu(event.target);"
                oncommand="gotoHistoryIndex(event);"
                onclick="checkForMiddleClick(this, event);"/>
     <tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
 
     <!-- for search and content formfill/pw manager -->
     <panel type="autocomplete" chromedir="&locale.dir;" id="PopupAutoComplete" noautofocus="true" hidden="true"/>
 
@@ -256,16 +257,17 @@
                        tooltiptext="&forwardButton.tooltip;">
           <observes element="Browser:Forward" attribute="disabled"/>
         </toolbarbutton>
         <toolbarbutton id="back-forward-dropmarker" type="menu" chromedir="&locale.dir;"
                        disabled="true">
           <!-- bug 415444: event.stopPropagation is here for the cloned version of
                this menupopup -->
           <menupopup context=""
+                     chromedir="&locale.dir;"
                      position="after_start"
                      onpopupshowing="return FillHistoryMenu(event.target);"
                      oncommand="gotoHistoryIndex(event); event.stopPropagation();"
                      onclick="checkForMiddleClick(this, event);"/>
         </toolbarbutton>
       </toolbaritem>
 
       <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
@@ -300,38 +302,36 @@
                  enablehistory="true"
                  timeout="100"
                  maxrows="10"
                  newlines="stripsurroundingwhitespace"
                  oninput="URLBarOnInput(event);"
                  ontextentered="return handleURLBarCommand(param);"
                  ontextreverted="return handleURLBarRevert();"
                  pageproxystate="invalid"
+                 onsearchbegin="LocationBarHelpers._searchBegin();"
+                 onsearchcomplete="LocationBarHelpers._searchComplete();"
                  onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
                  onblur="document.getElementById('identity-box').style.MozUserFocus = 'ignore';">
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                onclick="getIdentityHandler().handleIdentityButtonEvent(event);"
                onkeypress="getIdentityHandler().handleIdentityButtonEvent(event);">
             <hbox align="center">
-              <deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
-                <image id="page-proxy-button"
-                       ondraggesture="PageProxyDragGesture(event);"
-                       tooltiptext="&proxyIcon.tooltip;"/>
+              <stack id="page-proxy-stack"
+                     onclick="PageProxyClickHandler(event);"
+                     tooltiptext="&proxyIcon.tooltip;">
+                <image id="urlbar-throbber" busy="false"/>
                 <image id="page-proxy-favicon" validate="never"
                        ondraggesture="PageProxyDragGesture(event);"
-                       onload="this.parentNode.selectedIndex = 1;
-                               event.stopPropagation();"
-                       onerror="this.removeAttribute('src');
-                                this.parentNode.selectedIndex = 0;"
-                       tooltiptext="&proxyIcon.tooltip;"/>
-              </deck>
+                       onerror="this.removeAttribute('src');"/>
+              </stack>
               <label id="identity-icon-label"/>
             </hbox>
           </box>
           <hbox id="urlbar-icons">
             <button type="menu"
                     style="-moz-user-focus: none"
                     class="plain urlbar-icon"
                     id="feed-button"
--- a/browser/base/content/credits.xhtml
+++ b/browser/base/content/credits.xhtml
@@ -105,16 +105,17 @@
       .creditsGroup {
         margin-bottom: 1px;
         text-align: center;
       }
 
       .footnote {
         font-size: x-small;
         text-align: justify;
+        line-height: 110%;
       }
 
       h2.title {
         margin-top: 200px;
         margin-bottom: 60px;
         text-align: center;
       }
 
@@ -463,20 +464,18 @@
           &license.part2;
           <a href="" link="about:license" onclick="visitLink(event);">about:license</a>
           &license.part3;</p>
 
         <p class="footnote">
           Mozilla Firefox&reg; and the Firefox logo are registered trademarks of the
           Mozilla Foundation. You are not granted rights or licenses to the trademarks
           of the Mozilla Foundation or any party, including without limitation the
-          Firefox name or logo.</p>
-
-        <p class="footnote">
-          Gecko&reg; is a registered trademark of Netscape Communications Corporation.</p>
+          Firefox name or logo. Gecko&reg; is a registered trademark of Netscape
+          Communications Corporation.</p>
 
         <p class="footnote">
           U.S. GOVERNMENT END USERS. The Software is a &ldquo;commercial item,&rdquo;
           as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of
           &ldquo;commercial computer software&rdquo; and &ldquo;commercial computer software
           documentation,&rdquo; as such terms are used in 48 C.F.R. 12.212 (Sept. 1995).
           Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through
           227.7202-4 (June 1995), all U.S. Government End Users acquire the
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -357,17 +357,18 @@ nsContextMenu.prototype = {
   initMetadataItems: function() {
     // Show if user clicked on something which has metadata.
     this.showItem("context-metadata", this.onMetaDataItem);
   },
 
   // Set various context menu attributes based on the state of the world.
   setTarget: function (aNode, aRangeParent, aRangeOffset) {
     const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-    if (aNode.namespaceURI == xulNS) {
+    if (aNode.namespaceURI == xulNS ||
+        this.isTargetAFormControl(aNode)) {
       this.shouldDisplay = false;
       return;
     }
 
     // Initialize contextual info.
     this.onImage           = false;
     this.onLoadedImage     = false;
     this.onCompletedImage  = false;
@@ -1088,16 +1089,28 @@ nsContextMenu.prototype = {
     return "contextMenu.target     = " + this.target + "\n" +
            "contextMenu.onImage    = " + this.onImage + "\n" +
            "contextMenu.onLink     = " + this.onLink + "\n" +
            "contextMenu.link       = " + this.link + "\n" +
            "contextMenu.inFrame    = " + this.inFrame + "\n" +
            "contextMenu.hasBGImage = " + this.hasBGImage + "\n";
   },
 
+  // Returns true if aNode is a from control (except text boxes).
+  // This is used to disable the context menu for form controls.
+  isTargetAFormControl: function(aNode) {
+    if (aNode instanceof HTMLInputElement)
+      return (aNode.type != "text" && aNode.type != "password");
+
+    return (aNode instanceof HTMLButtonElement) ||
+           (aNode instanceof HTMLSelectElement) ||
+           (aNode instanceof HTMLOptionElement) ||
+           (aNode instanceof HTMLOptGroupElement);
+  },
+
   isTargetATextBox: function(node) {
     if (node instanceof HTMLInputElement)
       return (node.type == "text" || node.type == "password")
 
     return (node instanceof HTMLTextAreaElement);
   },
 
   isTargetAKeywordField: function(aNode) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -72,43 +72,46 @@
         <xul:hbox class="tabbrowser-strip" collapsed="true" tooltip="_child" context="_child"
                   anonid="strip"
                   ondraggesture="nsDragAndDrop.startDrag(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragover="nsDragAndDrop.dragOver(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragdrop="nsDragAndDrop.drop(event, this.parentNode.parentNode); event.stopPropagation();"
                   ondragexit="nsDragAndDrop.dragExit(event, this.parentNode.parentNode); event.stopPropagation();">
           <xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
           <xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
-            <xul:menuitem label="&newTab.label;" accesskey="&newTab.accesskey;"
+            <xul:menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
                           xbl:inherits="oncommand=onnewtab"/>
             <xul:menuseparator/>
-            <xul:menuitem label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
+            <xul:menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                           oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
                                      tabbrowser.reloadTab(tabbrowser.mContextTab);"/>
-            <xul:menuitem label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
+            <xul:menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
                           tbattr="tabbrowser-multiple"
                           oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
                                      tabbrowser.reloadAllTabs(tabbrowser.mContextTab);"/>
-            <xul:menuitem label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
+            <xul:menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
                           tbattr="tabbrowser-multiple"
                           oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
                                      tabbrowser.removeAllTabsBut(tabbrowser.mContextTab);"/>
             <xul:menuseparator/>
-            <xul:menuitem label="&bookmarkThisTab.label;"
+            <xul:menuitem id="context_bookmarkTab"
+                          label="&bookmarkThisTab.label;"
                           accesskey="&bookmarkThisTab.accesskey;"
                           oncommand="BookmarkThisTab();"/>
-            <xul:menuitem label="&bookmarkAllTabs.label;"
+            <xul:menuitem id="context_bookmarkAllTabs"
+                          label="&bookmarkAllTabs.label;"
                           accesskey="&bookmarkAllTabs.accesskey;"
                           command="Browser:BookmarkAllTabs"/>
-            <xul:menuitem label="&undoCloseTab.label;"
+            <xul:menuitem id="context_undoCloseTab"
+                          label="&undoCloseTab.label;"
                           accesskey="&undoCloseTab.accesskey;"
                           command="History:UndoCloseTab"
                           anonid="undoCloseTabMenuItem"/>
             <xul:menuseparator/>
-            <xul:menuitem label="&closeTab.label;" accesskey="&closeTab.accesskey;"
+            <xul:menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
                           oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
                                      tabbrowser.removeTab(tabbrowser.mContextTab);"/>
           </xul:menupopup>
 
           <xul:tabs class="tabbrowser-tabs" flex="1"
                     anonid="tabcontainer"
                     setfocus="false"
                     onclick="this.parentNode.parentNode.parentNode.onTabClick(event);"
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -379,20 +379,38 @@ function openPreferences(paneID)
                      .getService(Components.interfaces.nsIWindowMediator);
   var win = wm.getMostRecentWindow("Browser:Preferences");
   if (win) {
     win.focus();
     if (paneID) {
       var pane = win.document.getElementById(paneID);
       win.document.documentElement.showPane(pane);
     }
+    return win;
   }
-  else
-    openDialog("chrome://browser/content/preferences/preferences.xul",
-               "Preferences", features, paneID);
+
+  return openDialog("chrome://browser/content/preferences/preferences.xul",
+                    "Preferences", features, paneID);
+}
+
+function openAdvancedPreferences(tabID)
+{
+  var win = openPreferences("paneAdvanced");
+  if (win) {
+    var selectTab = function() {
+      var tabs = win.document.getElementById("advancedPrefs");
+      tabs.selectedTab = win.document.getElementById(tabID);
+    }
+
+    if (win.document.getElementById("advancedPrefs")) {
+      selectTab();
+    } else {
+      win.addEventListener("load", selectTab, false);
+    }
+  }
 }
 
 /**
  * Opens the release notes page for this version of the application.
  * @param   event
  *          The DOM Event that caused this function to be called, used to
  *          determine where the release notes page should be displayed based
  *          on modifiers (e.g. Ctrl = new tab)
@@ -632,8 +650,26 @@ function isValidFeed(aData, aPrincipal, 
     }
   }
 
   if (type)
     aData.type = type;
 
   return aIsFeed;
 }
+
+function getOfflineAppUsage(host)
+{
+  var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
+                     getService(Components.interfaces.nsICacheService);
+  var cacheSession = cacheService.createSession("HTTP-offline",
+                                                Components.interfaces.nsICache.STORE_OFFLINE,
+                                                true).
+                     QueryInterface(Components.interfaces.nsIOfflineCacheSession);
+  var usage = cacheSession.getDomainUsage(host);
+
+  var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
+                       getService(Components.interfaces.nsIDOMStorageManager);
+  usage += storageManager.getUsage(host);
+
+  return usage;
+}
+
--- a/browser/components/build/Makefile.in
+++ b/browser/components/build/Makefile.in
@@ -59,22 +59,16 @@ SHARED_LIBRARY_LIBS = \
   ../places/src/$(LIB_PREFIX)browserplaces_s.$(LIB_SUFFIX) \
 	$(NULL)
 
 ifneq (,$(filter windows mac cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
 SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX) \
 	$(NULL)
 endif
 
-ifdef MOZ_SAFE_BROWSING
-REQUIRES += safebrowsing
-LOCAL_INCLUDES += -I$(srcdir)/../safebrowsing/src
-SHARED_LIBRARY_LIBS += ../safebrowsing/src/$(LIB_PREFIX)safebrowsing_s.$(LIB_SUFFIX)
-endif
-
 EXTRA_DSO_LDOPTS += \
 	$(call EXPAND_LIBNAME_PATH,unicharutil_external_s,$(LIBXUL_DIST)/lib) \
 	$(LIBXUL_DIST)/lib/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX) \
 	$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
 	$(MOZ_COMPONENT_LIBS) \
 	$(NULL)
 
 # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
--- a/browser/components/build/nsBrowserCompsCID.h
+++ b/browser/components/build/nsBrowserCompsCID.h
@@ -86,20 +86,14 @@
 { 0x6893e69, 0x71d8, 0x4b23, { 0x81, 0xeb, 0x80, 0x31, 0x4d, 0xaf, 0x3e, 0x66 } }
 
 #define NS_FEEDSNIFFER_CONTRACTID \
   "@mozilla.org/browser/feeds/sniffer;1"
 
 #define NS_ABOUTFEEDS_CID \
 { 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
 
-#define NS_DOCNAVSTARTPROGRESSLISTENER_CID \
-{ 0x7baf8179, 0xa4fd, 0x4bc0, { 0xbe, 0x43, 0xa9, 0xb1, 0x22, 0xc5, 0xde, 0xb6 } }
-
-#define NS_DOCNAVSTARTPROGRESSLISTENER_CONTRACTID \
-  "@mozilla.org/browser/safebrowsing/navstartlistener;1"
-
 // 6fb0c970-e1b1-11db-8314-0800200c9a66
 #define NS_PLACESIMPORTEXPORTSERVICE_CID \
 { 0x6fb0c970, 0xe1b1, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
 
 #define NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID \
   "@mozilla.org/browser/places/import-export-service;1"
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -64,19 +64,16 @@
 #include "nsMacIEProfileMigrator.h"
 #include "nsCaminoProfileMigrator.h"
 #include "nsICabProfileMigrator.h"
 #endif
 #include "rdf.h"
 #include "nsFeedSniffer.h"
 #include "nsAboutFeeds.h"
 #include "nsIAboutModule.h"
-#ifdef MOZ_SAFE_BROWSING
-#include "nsDocNavStartProgressListener.h"
-#endif
 
 /////////////////////////////////////////////////////////////////////////////
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsPlacesImportExportService)
 #ifdef XP_WIN
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
@@ -97,19 +94,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfi
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsOmniWebProfileMigrator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacIEProfileMigrator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsCaminoProfileMigrator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsICabProfileMigrator)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
-#ifdef MOZ_SAFE_BROWSING
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsDocNavStartProgressListener)
-#endif
 
 /////////////////////////////////////////////////////////////////////////////
 
 static const nsModuleComponentInfo components[] =
 {
 #if defined(XP_WIN)
   { "Browser Shell Service",
     NS_SHELLSERVICE_CID,
@@ -137,23 +131,16 @@ static const nsModuleComponentInfo compo
     nsFeedSniffer::Register },
 
   { "about:feeds Page",
     NS_ABOUTFEEDS_CID,
     NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds",
     nsAboutFeeds::Create
   },
 
-#ifdef MOZ_SAFE_BROWSING
-  { "Safe browsing document nav start progress listener",
-    NS_DOCNAVSTARTPROGRESSLISTENER_CID,
-    NS_DOCNAVSTARTPROGRESSLISTENER_CONTRACTID,
-    nsDocNavStartProgressListenerConstructor },
-#endif
-
   { "Profile Migrator",
     NS_FIREFOX_PROFILEMIGRATOR_CID,
     NS_PROFILEMIGRATOR_CONTRACTID,
     nsProfileMigratorConstructor },
 
 #if defined(XP_WIN) && !defined(__MINGW32__)
   { "Internet Explorer (Windows) Profile Migrator",
     NS_WINIEPROFILEMIGRATOR_CID,
--- a/browser/components/feeds/public/nsIWebContentConverterRegistrar.idl
+++ b/browser/components/feeds/public/nsIWebContentConverterRegistrar.idl
@@ -30,18 +30,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsISupports.idl"
 #include "nsIMIMEInfo.idl"
+#include "nsIWebContentHandlerRegistrar.idl"
 
 interface nsIRequest;
 
 [scriptable, uuid(eb361098-5158-4b21-8f98-50b445f1f0b2)]
 interface nsIWebContentHandlerInfo : nsIHandlerApp
 {
   /**
    * The content type handled by the handler
@@ -59,18 +59,18 @@ interface nsIWebContentHandlerInfo : nsI
    * @param   uri
    *          The URI of the document being loaded
    * @returns The URI of the service with the loading document URI encoded in 
    *          it.
    */
   AString getHandlerURI(in AString uri);
 };
 
-[scriptable, uuid(632b16a8-5c6b-4dc5-a8db-01771af7a79d)]
-interface nsIWebContentConverterService : nsISupports
+[scriptable, uuid(de7cc06e-e778-45cb-b7db-7a114e1e75b1)]
+interface nsIWebContentConverterService : nsIWebContentHandlerRegistrar
 {
   /**
    * Specifies the handler to be used to automatically handle all links of a
    * certain content type from now on. 
    * @param   contentType
    *          The content type to automatically load with the specified handler
    * @param   handler
    *          A web service handler. If this is null, no automatic action is
@@ -124,40 +124,16 @@ interface nsIWebContentConverterService 
    * @param   contentType
    *          The content type to remove a service handler for
    * @param   uri
    *          The uri of the service handler to remove
    */
   void removeContentHandler(in AString contentType, in AString uri);
 
   /**
-   * Registers a protocol handler for a web service
-   * @param   protocol
-   *          The protocol scheme to register a service handler for
-   * @param   uri
-   *          The uri of the service handler to register
-   * @param   title
-   *          The human readable title of the service
-   */
-  void registerProtocolHandler(in AString scheme, in AString uri, 
-                               in AString title);
-
-  /**
-   * Registers a content handler for a web service
-   * @param   contentType
-   *          The content type to register a service handler for
-   * @param   uri
-   *          The uri of the service handler to register
-   * @param   title
-   *          The human readable title of the service
-   */
-  void registerContentHandler(in AString contentType, in AString uri,
-                              in AString title);
-
-  /**
    * Gets the list of content handlers for a particular type.
    * @param   contentType
    *          The content type to get handlers for
    * @returns An array of nsIWebContentHandlerInfo objects
    */
   void getContentHandlers(in AString contentType, out unsigned long count,
                           [retval,array,size_is(count)] out nsIWebContentHandlerInfo handlers);
 
--- a/browser/components/feeds/src/WebContentConverter.js
+++ b/browser/components/feeds/src/WebContentConverter.js
@@ -493,37 +493,40 @@ WebContentConverterRegistrar.prototype =
                                        notificationValue,
                                        notificationIcon,
                                        notificationBox.PRIORITY_INFO_LOW,
                                        buttons);
   },
 
   /**
    * See nsIWebContentHandlerRegistrar
-   * This is the web front end into the registration system, so a prompt to 
-   * confirm the registration is provided, and the result is saved to 
-   * preferences.
+   * If a DOM window is provided, then the request came from content, so we
+   * prompt the user to confirm the registration.
    */
   registerContentHandler: 
   function WCCR_registerContentHandler(aContentType, aURIString, aTitle, aContentWindow) {
     LOG("registerContentHandler(" + aContentType + "," + aURIString + "," + aTitle + ")");
 
     // We only support feed types at present.
     // XXX this should be a "security exception" according to spec, but that
     // isn't defined yet.
     var contentType = this._resolveContentType(aContentType);
     if (contentType != TYPE_MAYBE_FEED)
       return;
 
-    var uri = this._checkAndGetURI(aURIString, aContentWindow);
-
-    var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
-    var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
-    var notificationBox = browserWindow.getBrowser().getNotificationBox(browserElement);
-    this._appendFeedReaderNotification(uri, aTitle, notificationBox);
+    if (aContentWindow) {
+      var uri = this._checkAndGetURI(aURIString, aContentWindow);
+  
+      var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
+      var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
+      var notificationBox = browserWindow.getBrowser().getNotificationBox(browserElement);
+      this._appendFeedReaderNotification(uri, aTitle, notificationBox);
+    }
+    else
+      this._registerContentHandler(contentType, aURIString, aTitle);
   },
 
   /**
    * Returns the browser chrome window in which the content window is in
    */
   _getBrowserWindowForContentWindow:
   function WCCR__getBrowserWindowForContentWindow(aContentWindow) {
     return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -603,35 +606,18 @@ WebContentConverterRegistrar.prototype =
         /* static */
         callback:
         function WCCR__addFeedReaderButtonCallback(aNotification, aButtonInfo) {
           var uri = aButtonInfo.feedReaderInfo.uri;
           var name = aButtonInfo.feedReaderInfo.name;
           var outer = aButtonInfo._outer;
 
           // The reader could have been added from another window mean while
-          if (!outer.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uri)) {
+          if (!outer.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uri))
             outer._registerContentHandler(TYPE_MAYBE_FEED, uri, name);
-            outer._saveContentHandlerToPrefs(TYPE_MAYBE_FEED, uri, name);
-
-            // Make the new handler the last-selected reader in the preview page
-            // and make sure the preview page is shown the next time a feed is visited
-            var pb = Cc["@mozilla.org/preferences-service;1"].
-                     getService(Ci.nsIPrefService).getBranch(null);
-            pb.setCharPref(PREF_SELECTED_READER, "web");
-
-            var supportsString = 
-              Cc["@mozilla.org/supports-string;1"].
-              createInstance(Ci.nsISupportsString);
-              supportsString.data = uri;
-            pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
-                               supportsString);
-            pb.setCharPref(PREF_SELECTED_ACTION, "ask");
-            outer._setAutoHandler(TYPE_MAYBE_FEED, null);
-          }
 
           // avoid reference cycles
           aButtonInfo._outer = null;
 
           return false;
         }
       };
       buttons = [addButton];
@@ -722,27 +708,60 @@ WebContentConverterRegistrar.prototype =
    *          contentType and *\/*.
    */
   _getConverterContractID: function WCCR__getConverterContractID(contentType) {
     const template = "@mozilla.org/streamconv;1?from=%s&to=*/*";
     return template.replace(/%s/, contentType);
   },
   
   /**
+   * Register a web service handler for a content type.
+   * 
+   * @param   contentType
+   *          the content type being handled
+   * @param   uri
+   *          the URI of the web service
+   * @param   title
+   *          the human readable name of the web service
+   */
+  _registerContentHandler:
+  function WCCR__registerContentHandler(contentType, uri, title) {
+    this._updateContentTypeHandlerMap(contentType, uri, title);
+    this._saveContentHandlerToPrefs(contentType, uri, title);
+
+    if (contentType == TYPE_MAYBE_FEED) {
+      // Make the new handler the last-selected reader in the preview page
+      // and make sure the preview page is shown the next time a feed is visited
+      var pb = Cc["@mozilla.org/preferences-service;1"].
+               getService(Ci.nsIPrefService).getBranch(null);
+      pb.setCharPref(PREF_SELECTED_READER, "web");
+  
+      var supportsString = 
+        Cc["@mozilla.org/supports-string;1"].
+        createInstance(Ci.nsISupportsString);
+        supportsString.data = uri;
+      pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
+                         supportsString);
+      pb.setCharPref(PREF_SELECTED_ACTION, "ask");
+      this._setAutoHandler(TYPE_MAYBE_FEED, null);
+    }
+  },
+
+  /**
    * Update the content type -> handler map. This mapping is not persisted, use
    * registerContentHandler or _saveContentHandlerToPrefs for that purpose.
    * @param   contentType
    *          The content Type being handled
    * @param   uri
    *          The uri of the web service
    * @param   title
    *          The human readable name of the web service
    */
-  _registerContentHandler: 
-  function WCCR__registerContentHandler(contentType, uri, title) {
+  _updateContentTypeHandlerMap: 
+  function WCCR__updateContentTypeHandlerMap(contentType, uri, title) {
     if (!(contentType in this._contentTypes))
       this._contentTypes[contentType] = [];
 
     // Avoid adding duplicates
     if (this._typeIsRegistered(contentType, uri)) 
       return;
     
     this._contentTypes[contentType].push(new ServiceInfo(contentType, uri, title));
@@ -800,17 +819,17 @@ WebContentConverterRegistrar.prototype =
     if (vals.length == 0)
       return;
 
     try {
       var type = branch.getCharPref("type");
       var uri = branch.getComplexValue("uri", Ci.nsIPrefLocalizedString).data;
       var title = branch.getComplexValue("title",
                                          Ci.nsIPrefLocalizedString).data;
-      this._registerContentHandler(type, uri, title);
+      this._updateContentTypeHandlerMap(type, uri, title);
     }
     catch(ex) {
       // do nothing, the next branch might have values
     }
   },
 
   /**
    * Load the auto handler, content handler and protocol tables from 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -232,17 +232,19 @@ BrowserGlue.prototype = {
     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
                      getService(Ci.nsIPrefBranch);
     var showPrompt = true;
     try {
       if (prefBranch.getIntPref("browser.startup.page") == 3 ||
           prefBranch.getBoolPref("browser.sessionstore.resume_session_once"))
         showPrompt = false;
       else
-        showPrompt = prefBranch.getBoolPref("browser.warnOnQuit");
+        showPrompt = aQuitType == "restart" ?
+                     prefBranch.getBoolPref("browser.warnOnRestart") :
+                     prefBranch.getBoolPref("browser.warnOnQuit");
     } catch (ex) {}
 
     var buttonChoice = 0;
     if (showPrompt) {
       var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
                           getService(Ci.nsIStringBundleService);
       var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
       var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
@@ -292,20 +294,25 @@ BrowserGlue.prototype = {
           prefBranch.setBoolPref("browser.warnOnQuit", false);
         break;
       case 1:
         aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
         aCancelQuit.data = true;
         break;
       case 0:
         this._saveSession = true;
-        // could also set browser.warnOnQuit to false here,
-        // but not setting it is a little safer.
-        if (neverAsk.value)
-          prefBranch.setIntPref("browser.startup.page", 3);
+        if (neverAsk.value) {
+          if (aQuitType == "restart")
+            prefBranch.setBoolPref("browser.warnOnRestart", false);
+          else {
+            // could also set browser.warnOnQuit to false here,
+            // but not setting it is a little safer.
+            prefBranch.setIntPref("browser.startup.page", 3);
+          }
+        }
         break;
       }
     }
   },
 
   // returns the (cached) Sanitizer constructor
   get Sanitizer() 
   {
@@ -527,17 +534,16 @@ BrowserGlue.prototype = {
         var recentlyBookmarkedTitle =
           this._placesBundle.GetStringFromName("recentlyBookmarkedTitle");
         var recentTagsTitle =
           this._placesBundle.GetStringFromName("recentTagsTitle");
 
         var bookmarksMenuFolder = bmsvc.bookmarksMenuFolder;
         var unfiledBookmarksFolder = bmsvc.unfiledBookmarksFolder;
         var toolbarFolder = bmsvc.toolbarFolder;
-        var tagsFolder = bmsvc.tagsFolder;
         var defaultIndex = bmsvc.DEFAULT_INDEX;
 
         // index = 0, make it the first folder
         var placesFolder = bmsvc.createFolder(toolbarFolder, smartBookmarksFolderTitle,
                                               0);
 
         // XXX should this be a pref?  see bug #399268
         var maxResults = 10;
@@ -562,24 +568,21 @@ BrowserGlue.prototype = {
               "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
               "&maxResults=" + maxResults +
               "&excludeQueries=1"),
               defaultIndex, recentlyBookmarkedTitle);
 
         var sep =  bmsvc.insertSeparator(placesFolder, defaultIndex);
 
         var recentTagsItem = bmsvc.insertBookmark(placesFolder,
-          this._uri("place:folder=" + tagsFolder +
-              "&group=" + Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER +
-              "&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-              "&applyOptionsToContainers=1" +
-              "&sort=" +
-              Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
+          this._uri("place:"+
+              "type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
+              "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
               "&maxResults=" + maxResults),
-              defaultIndex, recentTagsTitle);
+          defaultIndex, recentTagsTitle);
       }
     };
 
     try {
       bmsvc.runInBatchMode(callback, null);
     }
     catch(ex) {
       Components.utils.reportError(ex);
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksPanel.xul
@@ -67,18 +67,18 @@
              type="timed" timeout="500"
              oncommand="searchBookmarks(this.value);"/>
   </hbox>
 
   <tree id="bookmarks-view" class="sidebar-placesTree" type="places"
         flex="1"
         hidecolumnpicker="true"
         context="placesContext"
-        onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
-        onclick="SidebarUtils.handleClick(this, event);"
+        onkeypress="SidebarUtils.handleTreeKeyPress(event);"
+        onclick="SidebarUtils.handleTreeClick(this, event);"
         onmousemove="SidebarUtils.handleTreeMouseMove(event);"
         onmouseout="SidebarUtils.clearURLFromStatusBar();">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
     <treechildren id="bookmarks-view-children" view="bookmarks-view" class="sidebar-placesTreechildren" flex="1"/>
   </tree>
 </page>
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -123,55 +123,45 @@ PlacesController.prototype = {
           if (container.childCount > 0);
             return true;
         }
       }
       return false;
     case "placesCmd_open":
     case "placesCmd_open:window":
     case "placesCmd_open:tab":
-      return this._view.selectedURINode;
+      var selectedNode = this._view.selectedNode;
+      return selectedNode && PlacesUtils.nodeIsURI(selectedNode);
     case "placesCmd_new:folder":
     case "placesCmd_new:livemark":
       return this._canInsert();
     case "placesCmd_new:bookmark":
       return this._canInsert();
     case "placesCmd_new:separator":
       return this._canInsert() &&
              !asQuery(this._view.getResult().root).queryOptions.excludeItems &&
              this._view.getResult().sortingMode ==
                  Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
     case "placesCmd_show:info":
-      if (this._view.hasSingleSelection) {
-        var selectedNode = this._view.selectedNode;
+      var selectedNode = this._view.selectedNode;
+      if (selectedNode) {
         if (PlacesUtils.nodeIsFolder(selectedNode) ||
             (PlacesUtils.nodeIsBookmark(selectedNode) &&
             !PlacesUtils.nodeIsLivemarkItem(selectedNode)))
           return true;
       }
       return false;
     case "placesCmd_reloadMicrosummary":
-      if (this._view.hasSingleSelection) {
-        var selectedNode = this._view.selectedNode;
-        if (PlacesUtils.nodeIsBookmark(selectedNode)) {
-          var mss = PlacesUtils.microsummaries;
-          if (mss.hasMicrosummary(selectedNode.itemId))
-            return true;
-        }
-      }
-      return false;
+      var selectedNode = this._view.selectedNode;
+      return selectedNode && PlacesUtils.nodeIsBookmark(selectedNode) &&
+             PlacesUtils.microsummaries.hasMicrosummary(selectedNode.itemId);
     case "placesCmd_reload":
-      if (this._view.hasSingleSelection) {
-        var selectedNode = this._view.selectedNode;
-
-        // Livemark containers
-        if (PlacesUtils.nodeIsLivemarkContainer(selectedNode))
-          return true;
-      }
-      return false;
+      // Livemark containers
+      var selectedNode = this._view.selectedNode;
+      return selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode);
     case "placesCmd_sortBy:name":
       var selectedNode = this._view.selectedNode;
       return selectedNode &&
              PlacesUtils.nodeIsFolder(selectedNode) &&
              !PlacesUtils.nodeIsReadOnly(selectedNode) &&
              this._view.getResult().sortingMode ==
                  Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
     default:
@@ -218,23 +208,23 @@ PlacesController.prototype = {
       break;
     case "cmd_delete":
       this.remove("Remove Selection");
       break;
     case "cmd_selectAll":
       this.selectAll();
       break;
     case "placesCmd_open":
-      this.openSelectedNodeIn("current");
+      PlacesUtils.openNodeIn(this._view.selectedNode, "current");
       break;
     case "placesCmd_open:window":
-      this.openSelectedNodeIn("window");
+      PlacesUtils.openNodeIn(this._view.selectedNode, "window");
       break;
     case "placesCmd_open:tab":
-      this.openSelectedNodeIn("tab");
+      PlacesUtils.openNodeIn(this._view.selectedNode, "tab");
       break;
     case "placesCmd_new:folder":
       this.newItem("folder");
       break;
     case "placesCmd_new:bookmark":
       this.newItem("bookmark");
       break;
     case "placesCmd_new:livemark":
@@ -272,19 +262,16 @@ PlacesController.prototype = {
    * removable item.
    * @param aIsMoveCommand
    *        True if thecommand for which this method is called only moves the
    *        selected items to another container, false otherwise.
    * @returns true if the there's a selection which has no nodes that cannot be removed,
    *          false otherwise.
    */
   _hasRemovableSelection: function PC__hasRemovableSelection(aIsMoveCommand) {
-    if (!this._view.hasSelection)
-      return false;
-
     var nodes = this._view.getSelectionNodes();
     var root = this._view.getResultNode();
 
     for (var i = 0; i < nodes.length; ++i) {
       // Disallow removing the view's root node
       if (nodes[i] == root)
         return false;
 
@@ -323,24 +310,23 @@ PlacesController.prototype = {
   _canInsert: function PC__canInsert() {
     return this._view.insertionPoint != null;
   },
 
   /**
    * Determines whether or not the root node for the view is selected
    */
   rootNodeIsSelected: function PC_rootNodeIsSelected() {
-    if (this._view.hasSelection) {
-      var nodes = this._view.getSelectionNodes();
-      var root = this._view.getResultNode();
-      for (var i = 0; i < nodes.length; ++i) {
-        if (nodes[i] == root)
-          return true;      
-      }
+    var nodes = this._view.getSelectionNodes();
+    var root = this._view.getResultNode();
+    for (var i = 0; i < nodes.length; ++i) {
+      if (nodes[i] == root)
+        return true;      
     }
+
     return false;
   },
 
   /**
    * Looks at the data on the clipboard to see if it is paste-able. 
    * Paste-able data is:
    *   - in a format that the view can receive
    * @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
@@ -406,45 +392,51 @@ PlacesController.prototype = {
    *          node are set on its corresponding object as properties.
    * Notes:
    *   1) This can be slow, so don't call it anywhere performance critical!
    *   2) A single-object array corresponding the root node is returned if
    *      there's no selection.
    */
   _buildSelectionMetadata: function PC__buildSelectionMetadata() {
     var metadata = [];
-    var nodes = [];
     var root = this._view.getResult().root;
-    if (this._view.hasSelection)
-      nodes = this._view.getSelectionNodes();
-    else // See the second note above
-      nodes = [root];
+    var nodes = this._view.getSelectionNodes();
+    if (nodes.length == 0)
+      nodes.push(root); // See the second note above
 
     for (var i=0; i < nodes.length; i++) {
       var nodeData = {};
       var node = nodes[i];
       var nodeType = node.type;
       var uri = null;
 
       // We don't use the nodeIs* methods here to avoid going through the type
       // property way too often
       switch(nodeType) {
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY:
           nodeData["query"] = true;
+          if (node.parent) {
+            switch (asQuery(node.parent).queryOptions.resultType) {
+              case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
+                nodeData["host"] = true;
+                break;
+              case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
+              case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
+                nodeData["day"] = true;
+                break;
+            }
+          }
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER:
           nodeData["dynamiccontainer"] = true;
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER:
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT:
           nodeData["folder"] = true;
           break;
-        case Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST:
-          nodeData["host"] = true;
-          break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
           nodeData["separator"] = true;
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT:
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT:
           nodeData["link"] = true;
           uri = PlacesUtils._uri(node.uri);
@@ -453,18 +445,16 @@ PlacesController.prototype = {
             var mss = PlacesUtils.microsummaries;
             if (mss.hasMicrosummary(node.itemId))
               nodeData["microsummary"] = true;
             else if (node.parent &&
                      PlacesUtils.nodeIsLivemarkContainer(node.parent))
               nodeData["livemarkChild"] = true;
           }
           break;
-        case Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY:
-          nodeData["day"] = true;
       }
 
       // Mutability is whether or not a container can have selected items
       // inserted or reordered. It does _not_ dictate whether or not the 
       // container can have items removed from it, since some containers that
       // aren't  reorderable can have items removed from them, e.g. a history
       // list. 
       if (!PlacesUtils.nodeIsReadOnly(node) &&
@@ -624,59 +614,16 @@ PlacesController.prototype = {
   /**
    * Select all links in the current view. 
    */
   selectAll: function PC_selectAll() {
     this._view.selectAll();
   },
 
   /**
-   * Loads the selected node's URL in the appropriate tab or window or as a web
-   * panel given the user's preference specified by modifier keys tracked by a
-   * DOM mouse/key event.
-   * @param   aEvent
-   *          The DOM mouse/key event with modifier keys set that track the
-   *          user's preferred destination window or tab.
-   */
-  openSelectedNodeWithEvent: function PC_openSelectedNodeWithEvent(aEvent) {
-    this.openSelectedNodeIn(whereToOpenLink(aEvent));
-  },
-
-  /**
-   * Loads the selected node's URL in the appropriate tab or window or as a
-   * web panel.
-   * see also openUILinkIn
-   */
-  openSelectedNodeIn: function PC_openSelectedNodeIn(aWhere) {
-    var node = this._view.selectedURINode;
-    if (node && PlacesUtils.checkURLSecurity(node)) {
-      var isBookmark = PlacesUtils.nodeIsBookmark(node);
-
-      if (isBookmark)
-        PlacesUtils.markPageAsFollowedBookmark(node.uri);
-      else
-        PlacesUtils.markPageAsTyped(node.uri);
-
-      // Check whether the node is a bookmark which should be opened as
-      // a web panel
-      if (aWhere == "current" && isBookmark) {
-        if (PlacesUtils.annotations
-                       .itemHasAnnotation(node.itemId, LOAD_IN_SIDEBAR_ANNO)) {
-          var w = getTopWin();
-          if (w) {
-            w.openWebPanel(node.title, node.uri);
-            return;
-          }
-        }
-      }
-      openUILinkIn(node.uri, aWhere);
-    }
-  },
-
-  /**
    * Opens the bookmark properties for the selected URI Node.
    */
   showBookmarkPropertiesForSelection: 
   function PC_showBookmarkPropertiesForSelection() {
     var node = this._view.selectedNode;
     if (!node)
       return;
 
@@ -694,21 +641,19 @@ PlacesController.prototype = {
     NS_ASSERT((typeof(value) == "object") && !(value instanceof String), 
            "This method should be passed a URI as a nsIURI object, not as a string.");
   },
 
   /**
    * Reloads the selected livemark if any.
    */
   reloadSelectedLivemark: function PC_reloadSelectedLivemark() {
-    if (this._view.hasSingleSelection) {
-      var selectedNode = this._view.selectedNode;
-      if (PlacesUtils.nodeIsLivemarkContainer(selectedNode))
-        PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
-    }
+    var selectedNode = this._view.selectedNode;
+    if (selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode))
+      PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
   },
 
   /**
    * Reload the microsummary associated with the selection
    */
   reloadSelectedMicrosummary: function PC_reloadSelectedMicrosummary() {
     var selectedNode = this._view.selectedNode;
     var mss = PlacesUtils.microsummaries;
@@ -763,17 +708,17 @@ PlacesController.prototype = {
     return reallyOpen;
   },
 
   /**
    * Opens the links in the selected folder, or the selected links in new tabs. 
    */
   openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
     var node = this._view.selectedNode;
-    if (this._view.hasSingleSelection && PlacesUtils.nodeIsContainer(node))
+    if (node && PlacesUtils.nodeIsContainer(node))
       PlacesUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent);
     else
       PlacesUtils.openURINodesInTabs(this._view.getSelectionNodes(), aEvent);
   },
 
   /**
    * Shows the Add Bookmark UI for the current insertion point.
    *
@@ -959,24 +904,26 @@ PlacesController.prototype = {
       else if (PlacesUtils.nodeIsDay(node)) {
         // this is the oldest date
         // for the last node endDate is end of epoch
         var beginDate = 0;
         // this is the newest date
         // day nodes have time property set to the last day in the interval
         var endDate = node.time;
 
-        // if this is not the last day container, then beginDate
-        // is the time property of the next day container
-        for (var j = 0; j < root.childCount-1 && !beginDate; ++j) {
-          if (root.getChild(j) != node)
-            continue;
-          var nextNode = root.getChild(j+1);
-          beginDate = nextNode.time
-        }
+        var nodeIdx = 0;
+        var cc = root.childCount;
+
+        // Find index of current day node
+        while (nodeIdx < cc && root.getChild(nodeIdx) != node)
+          ++nodeIdx;
+
+        // We have an older day
+        if (nodeIdx+1 < cc)
+          beginDate = root.getChild(nodeIdx+1).time;
 
         // we want to exclude beginDate from the removal
         bhist.removePagesByTimeframe(beginDate+1, endDate);
       }
     }
 
     // if we have to delete a lot of urls RemovePage will be slow, it's better
     // to delete them in bunch and rebuild the full treeView
@@ -1031,21 +978,24 @@ PlacesController.prototype = {
    * @returns A TransferDataSet object that can be dragged and dropped 
    *          elsewhere.
    */
   getTransferData: function PC_getTransferData(dragAction) {
     var result = this._view.getResult();
     var oldViewer = result.viewer;
     try {
       result.viewer = null;
-      var nodes = null;
-      if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY)
-        nodes = this._view.getCopyableSelection();
-      else
-        nodes = this._view.getDragableSelection();
+      var nodes = this._view.getDragableSelection();
+      if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_MOVE) {
+        nodes = nodes.filter(function(node) {
+          var parent = node.parent;
+          return parent && !PlacesUtils.nodeIsReadOnly(parent);
+        });
+      }
+
       var dataSet = new TransferDataSet();
       for (var i = 0; i < nodes.length; ++i) {
         var node = nodes[i];
 
         var data = new TransferData();
         function addData(type, overrideURI) {
           data.addDataForFlavour(type, PlacesUtils._wrapString(
                                  PlacesUtils.wrapNode(node, type, overrideURI)));
@@ -1081,24 +1031,24 @@ PlacesController.prototype = {
   /**
    * Copy Bookmarks and Folders to the clipboard
    */
   copy: function PC_copy() {
     var result = this._view.getResult();
     var oldViewer = result.viewer;
     try {
       result.viewer = null;
-      var nodes = this._view.getCopyableSelection();
+      var nodes = this._view.getSelectionNodes();
 
       var xferable =  Cc["@mozilla.org/widget/transferable;1"].
                       createInstance(Ci.nsITransferable);
       var foundFolder = false, foundLink = false;
       var copiedFolders = [];
       var placeString = mozURLString = htmlString = unicodeString = "";
-    
+
       for (var i = 0; i < nodes.length; ++i) {
         var node = nodes[i];
         if (this._shouldSkipNode(node, copiedFolders))
           continue;
         if (PlacesUtils.nodeIsFolder(node))
           copiedFolders.push(node);
         
         function generateChunk(type, overrideURI) {
@@ -1109,17 +1059,17 @@ PlacesController.prototype = {
             uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
 
           mozURLString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_X_MOZ_URL,
                                                  uri) + suffix);
           unicodeString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_UNICODE,
                                                  uri) + suffix);
           htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
                                                  uri) + suffix);
-        
+
           var placeSuffix = i < (nodes.length - 1) ? "," : "";
           return PlacesUtils.wrapNode(node, type, overrideURI) + placeSuffix;
         }
 
         // all items wrapped as TYPE_X_MOZ_PLACE
         placeString += generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE);
       }
 
--- a/browser/components/places/content/history-panel.js
+++ b/browser/components/places/content/history-panel.js
@@ -97,31 +97,28 @@ function GroupBy(groupingType)
   searchHistory("");
 }
 
 function historyAddBookmarks()
 { 
   // no need to check gHistoryTree.view.selection.count
   // node will be null if there is a multiple selection 
   // or if the selected item is not a URI node
-  var node = gHistoryTree.selectedURINode;
-  if (!node) 
-    return;
-
-  PlacesUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
+  var node = gHistoryTree.selectedNode;
+  if (node && PlacesUtils.nodeIsURI(node))
+    PlacesUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
 }
 
 function searchHistory(aInput)
 {
   var query = PlacesUtils.history.getNewQuery();
   var options = PlacesUtils.history.getNewQueryOptions();
 
   const NHQO = Ci.nsINavHistoryQueryOptions;
   var sortingMode;
-  var groups = []; 
   var resultType;
 
   if (aInput) {
     query.searchTerms = aInput;
     sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
     resultType = NHQO.RESULTS_AS_URI;
   }
   else {
@@ -129,32 +126,30 @@ function searchHistory(aInput)
       case "visited":
         resultType = NHQO.RESULTS_AS_URI;
         sortingMode = NHQO.SORT_BY_VISITCOUNT_DESCENDING;
         break; 
       case "lastvisited":
         resultType = NHQO.RESULTS_AS_URI;
         sortingMode = NHQO.SORT_BY_DATE_DESCENDING;
         break; 
-      case "dayandsite":  // fall through
-        groups.push(NHQO.GROUP_BY_DAY);
+      case "dayandsite":
+        resultType = NHQO.RESULTS_AS_DATE_SITE_QUERY;
+        break;
       case "site":
-        groups.push(NHQO.GROUP_BY_HOST);
-        resultType = NHQO.RESULTS_AS_VISIT;
+        resultType = NHQO.RESULTS_AS_SITE_QUERY;
         sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
         break;
+      case "day":
       default:
-        resultType = NHQO.RESULTS_AS_VISIT;
-        groups.push(NHQO.GROUP_BY_DAY);
-        sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
+        resultType = NHQO.RESULTS_AS_DATE_QUERY;
         break;
     }
   }
 
-  options.setGroupingMode(groups, groups.length);
   options.sortingMode = sortingMode;
   options.resultType = resultType;
 
   // call load() on the tree manually
   // instead of setting the place attribute in history-panel.xul
   // otherwise, we will end up calling load() twice
   gHistoryTree.load([query], options);
 }
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/history-panel.xul
@@ -114,19 +114,19 @@
     </button>
   </hbox>
 
   <tree id="historyTree"
         class="sidebar-placesTree"
         flex="1"
         type="places"
         context="placesContext"
-        onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
         hidecolumnpicker="true"
-        onclick="SidebarUtils.handleClick(this, event, true);"
+        onkeypress="SidebarUtils.handleTreeKeyPress(event);"
+        onclick="SidebarUtils.handleTreeClick(this, event);"
         onmousemove="SidebarUtils.handleTreeMouseMove(event);"
         onmouseout="SidebarUtils.clearURLFromStatusBar();">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
     <treechildren class="sidebar-placesTreechildren" flex="1"/>
   </tree>
 </page>
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -182,21 +182,22 @@
         ]]></body>
       </method>
 
       <method name="onDragStart">
         <parameter name="aEvent"/>
         <parameter name="aXferData"/>
         <parameter name="aDragAction"/>
         <body><![CDATA[
-          this._rootView._selection = aEvent.target.node;
-          this._rootView._cachedInsertionPoint = undefined;
-
           if (aEvent.ctrlKey)
             aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
+
+          // activate the view and cache the dragged node
+          this._rootView._draggedNode = aEvent.target.node;
+          this._rootView.focus();
           aXferData.data = this._rootView.controller
                                          .getTransferData(aDragAction.action);
         ]]></body>
       </method>
 
       <method name="onDrop">
         <parameter name="aEvent"/>
          <parameter name="aDropData"/>
@@ -243,38 +244,37 @@
 
       <!-- This function returns information about where to drop when
            dragging over this popup insertion point -->
       <method name="_getDropPoint">
         <parameter name="aEvent"/>
           <body><![CDATA[
             // Can't drop if the menu isn't a folder
             var resultNode = this._resultNode;
-
             if (!PlacesUtils.nodeIsFolder(resultNode))
               return null;
 
             var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
-            // Loop through all the nodes to see which one this should
-            // get dropped in/above/below.
+
+            // set the limits for valid items
             var start = 0;
             var popup = this;
             var end = popup.childNodes.length;
-            if (popup == this._rootView &&
-                this._rootView.localName == "menupopup") {
-              // Ignore static content at the top and bottom of the menu.
-              start = this._rootView._startMarker + 1;
-              if (this._rootView._endMarker != -1)
-                end = this._rootView._endMarker;
-            }
+            if (this._startMarker != -1)
+              start = this._startMarker + 1;
+            if (this._endMarker != -1)
+              end = this._endMarker;
 
-            var popupFirstChildY = popup.firstChild.boxObject.y;
+            // Loop through all the nodes to find the correct dropPoint
+            var popupY = popup.boxObject.y;
+            // we should add the scrollBox button height if visible
+            popupY += this._scrollBox.scrollBoxObject.y - popup.boxObject.y;
             for (var i = start; i < end; i++) {
               var xulNode = popup.childNodes[i];
-              var nodeY = xulNode.boxObject.y - popupFirstChildY;
+              var nodeY = xulNode.boxObject.y - popupY;
               var nodeHeight = xulNode.boxObject.height;
               if (xulNode.node &&
                   PlacesUtils.nodeIsFolder(xulNode.node) &&
                   !PlacesUtils.nodeIsReadOnly(xulNode.node)) {
                 // This is a folder. If the mouse is in the top 25% of the
                 // node, drop above the folder.  If it's in the middle
                 // 50%, drop into the folder.  If it's past that, drop below.
                 if (aEvent.layerY < nodeY + (nodeHeight * 0.25)) {
@@ -290,17 +290,17 @@
                   dropPoint.beforeIndex = i;
                   dropPoint.folderNode = xulNode;
                   return dropPoint;
                 }
               }
               else {
                 // This is a non-folder node. If the mouse is above the middle,
                 // drop above the folder.  Otherwise, drop below.
-                if (aEvent.layerY < nodeY + (nodeHeight / 2)) {
+                if (aEvent.layerY <= nodeY + (nodeHeight / 2)) {
                   // Drop above this bookmark.
                   dropPoint.ip = new InsertionPoint(resultNode.itemId,
                                                     i - start, -1);
                   dropPoint.beforeIndex = i;
                   return dropPoint;
                 }
               }
             }
@@ -502,18 +502,16 @@
           var popup = aEvent.target;
           var resultNode = popup._resultNode;
           resultNode.containerOpen = true;
           if (!popup._built)
             this._rebuild(popup);
         ]]></body>
       </method>
 
-      <field name="_selection">null</field>
-
       <!-- nsIPlacesView -->
       <method name="getResult">
         <body><![CDATA[
           return this._result;
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
@@ -583,16 +581,21 @@
             for (var i=0; i < this._containerNodesMap.length; i++) {
               if (this._containerNodesMap[i].resultNode == child.node) {
                 this._containerNodesMap.splice(i, 1);
                 break;
               }
             }
           }
 
+          // if document.popupNode pointed to this child, null it out,
+          // otherwise controller's command-updating may rely on the removed
+          // item still being "selected".
+          if (document.popupNode == child)
+            document.popupNode = null;
           child.parentNode.removeChild(child);
         ]]></body>
       </method>
 
       <method name="insertNewItem">
         <parameter name="aChild"/>
         <parameter name="aParentPopup"/>
         <parameter name="aBefore"/>
@@ -867,129 +870,106 @@
           result.viewer = this._viewer;
           return val;
         ]]></setter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="hasSelection">
         <getter><![CDATA[
-          return this._selection != null;
-        ]]></getter>
-      </property>
-
-      <!-- nsIPlacesView -->
-      <property name="hasSingleSelection">
-        <getter><![CDATA[
-          return this.hasSelection;
+          return this.selectedNode != null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <method name="getSelectionNodes">
         <body><![CDATA[
-          return this.hasSelection ? [this.selectedNode] : [];
+          var selectedNode = this.selectedNode;
+          return selectedNode ? [selectedNode] : [];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <method name="getRemovableSelectionRanges">
         <body><![CDATA[
           return [this.getSelectionNodes()];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
-      <method name="getCopyableSelection">
-        <body><![CDATA[
-          return this.getSelectionNodes();
-        ]]></body>
-      </method>
-
-      <!-- nsIPlacesView -->
       <method name="getDragableSelection">
         <body><![CDATA[
-          if (PlacesUtils.nodeIsReadOnly(this._resultNode))
-            return null;
-          return this.getSelectionNodes();
+          return [this._draggedNode];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <property name="selectedNode">
         <getter><![CDATA[
-          return this.hasSelection ? this._selection : null;
-        ]]></getter>
-      </property>
-
-      <!-- nsIPlacesView -->
-      <property name="selectedURINode">
-        <getter><![CDATA[
-          var node = this.selectedNode;
-          return node && PlacesUtils.nodeIsURI(node) ? node : null;
+          if (this._contextMenuShown) {
+            var popupNode = document.popupNode;
+            return popupNode.node || popupNode.parentNode._resultNode || null;
+          }
+          return null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
-          if (this._cachedInsertionPoint !== undefined)
-            return this._cachedInsertionPoint;
-
           // By default, the insertion point is at the top level, at the end.
           var index = -1;
           var folderId = 0;
           if (PlacesUtils.nodeIsFolder(this._resultNode))
             folderId = PlacesUtils.getConcreteItemId(this._resultNode);
 
-          if (this.hasSelection) {
-            if (PlacesUtils.nodeIsFolder(this.selectedNode)) {
+          var selectedNode = this.selectedNode;
+          if (selectedNode) {
+            if (PlacesUtils.nodeIsFolder(selectedNode)) {
               // If there is a folder selected, the insertion point is the
               // end of the folder.
-              folderId = PlacesUtils.getConcreteItemId(this.selectedNode);
-            } else {
+              folderId = PlacesUtils.getConcreteItemId(selectedNode);
+            }
+            else {
               // If there is another type of node selected, the insertion point
               // is after that node.
-              folderId = PlacesUtils.getConcreteItemId(this.selectedNode.parent);
-              index = PlacesUtils.getIndexOfNode(this.selectedNode)
+              folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
+              index = PlacesUtils.getIndexOfNode(selectedNode)
             }
           }
-          this._cachedInsertionPoint = new InsertionPoint(folderId, index);
-          return this._cachedInsertionPoint;
+          return new InsertionPoint(folderId, index);
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <method name="selectAll">
-        <body><![CDATA[
-          // Nothing
-        ]]></body>
+        <body/>
       </method>
 
       <method name="selectItems">
-        <body><![CDATA[
-          // Nothing
-        ]]></body>
+        <body/>
       </method>
 
       <property name="selType" readonly="true" onget="return 'single';"/>
 
       <method name="buildContextMenu">
         <parameter name="aPopup"/>
         <body><![CDATA[
           this._ensureInitialized();
+          this._contextMenuShown = true;
           this.focus();
           return this.controller.buildContextMenu(aPopup);
         ]]></body>
       </method>
 
       <method name="destroyContextMenu">
         <parameter name="aPopup"/>
         <body>
           <![CDATA[
+            this._contextMenuShown = false;
             if (window.content)
               window.content.focus();
           ]]>
         </body>
       </method>
     </implementation>
     <handlers>
       <handler event="popupshowing" phase="capturing"><![CDATA[
@@ -1008,34 +988,12 @@
         if (!PlacesUtils.nodeIsFolder(popup._resultNode))
           popup._resultNode.containerOpen = false;
 
         // The autoopened attribute is set for folders which have been
         // automatically opened when dragged over.  Turn off this attribute
         // when the folder closes because it is no longer applicable.
         popup.removeAttribute("autoopened");
       ]]></handler>
-
-      <!-- Set selected node on DOMMenuItemActive/contextmenu events
-           so that they're set up when command and click events fire. -->
-      <handler event="DOMMenuItemActive"><![CDATA[
-        // Set the selection to the node that was activated.  If that
-        // node has a command but no data associated with it, it should
-        // act on the entire menu.
-        if (event.target.parentNode._resultNode) {
-          this._cachedInsertionPoint = undefined;
-          this._selection = event.target.node ||
-                            event.target.parentNode._resultNode;
-        }
-      ]]></handler>
-      <handler event="contextmenu"><![CDATA[
-        // DOMMenuItemActive is not dispatched for disabled menuitems and
-        // menuseparators. Set the selection here manually.
-        var popupNode = document.popupNode;
-        // |popupNode == menupopup| happens when the area between
-        // menuseparators is clicked.
-        this._selection = popupNode.node || popupNode.parentNode._resultNode;
-        this._cachedInsertionPoint = undefined;
-      ]]></handler>
     </handlers>
   </binding>
 
 </bindings>
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -227,43 +227,42 @@ var PlacesOrganizer = {
   /**
    * Handle clicks on the tree. If the user middle clicks on a URL, load that
    * URL according to rules. Single clicks or modified clicks do not result in
    * any special action, since they're related to selection.
    * @param   aEvent
    *          The mouse event.
    */
   onTreeClick: function PO_onTreeClick(aEvent) {
-    var currentView = aEvent.currentTarget;
-    var controller = currentView.controller;
-
     if (aEvent.target.localName != "treechildren")
       return;
 
-    if (currentView.hasSingleSelection && aEvent.button == 1) {
-      if (PlacesUtils.nodeIsURI(currentView.selectedNode))
-        controller.openSelectedNodeWithEvent(aEvent);
-      else if (PlacesUtils.nodeIsContainer(currentView.selectedNode)) {
+    var currentView = aEvent.currentTarget;
+    var selectedNode = currentView.selectedNode;
+    if (selectedNode && aEvent.button == 1) {
+      if (PlacesUtils.nodeIsURI(selectedNode))
+        PlacesUtils.openNodeWithEvent(selectedNode, aEvent);
+      else if (PlacesUtils.nodeIsContainer(selectedNode)) {
         // The command execution function will take care of seeing the
         // selection is a folder/container and loading its contents in
         // tabs for us.
-        controller.openLinksInTabs();
+        PlacesUtils.openContainerNodeInTabs(selectedNode);
       }
     }
   },
 
   openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) {
     if (aContainer.itemId != -1)
       this._places.selectItems([aContainer.itemId]);
     else if (PlacesUtils.nodeIsQuery(aContainer))
       this._places.selectPlaceURI(aContainer.uri);
   },
 
   openSelectedNode: function PU_openSelectedNode(aEvent) {
-    this._content.controller.openSelectedNodeWithEvent(aEvent);
+    PlacesUtils.openNodeWithEvent(this._content.selectedNode, aEvent);
   },
 
   /**
    * Returns the options associated with the query currently loaded in the
    * main places pane.
    */
   getCurrentOptions: function PO_getCurrentOptions() {
     return asQuery(this._content.getResult().root).queryOptions;
@@ -520,33 +519,31 @@ var PlacesOrganizer = {
       if ((focusedElement instanceof HTMLInputElement ||
            focusedElement instanceof HTMLTextAreaElement) &&
           /^editBMPanel.*/.test(focusedElement.parentNode.parentNode.id))
         focusedElement.blur();
     }
 
     var contentTree = document.getElementById("placeContent");
     var detailsDeck = document.getElementById("detailsDeck");
-    if (contentTree.hasSelection) {
-      detailsDeck.selectedIndex = 1;
-      if (contentTree.hasSingleSelection) {
-        var selectedNode = contentTree.selectedNode;
-        if (selectedNode.itemId != -1 &&
-            !PlacesUtils.nodeIsSeparator(selectedNode)) {
-          if (this._paneDisabled) {
-            this._setDetailsFieldsDisabledState(false);
-            this._paneDisabled = false;
-          }
+    detailsDeck.selectedIndex = 1;
+    var selectedNode = contentTree.selectedNode;
+    if (selectedNode) {
+      if (selectedNode.itemId != -1 &&
+          !PlacesUtils.nodeIsSeparator(selectedNode)) {
+        if (this._paneDisabled) {
+          this._setDetailsFieldsDisabledState(false);
+          this._paneDisabled = false;
+        }
 
-          gEditItemOverlay.initPanel(selectedNode.itemId,
-                                     { hiddenRows: ["folderPicker"] });
+        gEditItemOverlay.initPanel(selectedNode.itemId,
+                                   { hiddenRows: ["folderPicker"] });
 
-          this._detectAndSetDetailsPaneMinimalState(selectedNode);
-          return;
-        }
+        this._detectAndSetDetailsPaneMinimalState(selectedNode);
+        return;
       }
     }
     else {
       detailsDeck.selectedIndex = 0;
       var selectItemDesc = document.getElementById("selectItemDescription");
       var itemsCountLabel = document.getElementById("itemsCountText");
       var rowCount = this._content.treeBoxObject.view.rowCount;
       if (rowCount == 0) {
--- a/browser/components/places/content/sidebarUtils.js
+++ b/browser/components/places/content/sidebarUtils.js
@@ -32,17 +32,17 @@
 # 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 *****
 
 var SidebarUtils = {
-  handleClick: function SU_handleClick(aTree, aEvent, aGutterSelect) {
+  handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
     var tbo = aTree.treeBoxObject;
 
     var row = { }, col = { }, obj = { };
     tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
 
     if (row.value == -1 || obj.value == "twisty")
       return;
 
@@ -62,20 +62,25 @@ var SidebarUtils = {
     }
     if (!mouseInGutter && 
         aEvent.originalTarget.localName == "treechildren" && 
         (aEvent.button == 0 || aEvent.button == 1)) {
       // Clear all other selection since we're loading a link now. We must
       // do this *before* attempting to load the link since openURL uses
       // selection as an indication of which link to load. 
       tbo.view.selection.select(row.value);
-      aTree.controller.openSelectedNodeWithEvent(aEvent);
+      PlacesUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
     }
   },
-  
+
+  handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
+    if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
+      PlacesUtils.openNodeWithEvent(aEvent.target.selectedNode, aEvent);
+  },
+
   /**
    * The following function displays the URL of a node that is being
    * hovered over.
    */
   handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) {
     if (aEvent.target.localName != "treechildren")
       return;
 
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -117,18 +117,16 @@
           this.place = this.place;
         }
         ]]></body>
       </method>
 
       <field name="_dropIndicatorBar">document.getAnonymousElementByAttribute(this, "class", "toolbar-drop-indicator-bar")</field>
       <field name="_chevron">document.getAnonymousElementByAttribute(this, "class", "chevron")</field>
 
-      <field name="_selection">null</field>
-
       <field name="_openedMenuButton">null</field>
 
       <field name="_result">null</field>
 
       <!-- nsIPlacesView -->
       <method name="getResult">
         <body><![CDATA[
           return this._result;
@@ -227,16 +225,21 @@
             for (var i=0; i < this._containerNodesMap.length; i++) {
               if (this._containerNodesMap[i].resultNode == child.node) {
                 this._containerNodesMap.splice(i, 1);
                 break;
               }
             }
           }
 
+          // if document.popupNode pointed to this child, null it out,
+          // otherwise controller's command-updating may rely on the removed
+          // item still being "selected".
+          if (document.popupNode == child)
+            document.popupNode = null;
           child.parentNode.removeChild(child);
         ]]></body>
       </method>
 
       <method name="chevronPopupShowing">
         <parameter name="aEvent"/>
         <body><![CDATA[
           var popup = aEvent.target;
@@ -326,95 +329,75 @@
           }
           return val;
         ]]></setter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="hasSelection">
         <getter><![CDATA[ 
-          return this._selection != null;
-        ]]></getter>
-      </property>
-
-      <!-- nsIPlacesView -->
-      <property name="hasSingleSelection">
-        <getter><![CDATA[ 
-          return this.hasSelection;
+          return this.selectedNode != null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <method name="getSelectionNodes">
         <body><![CDATA[
-          return this.hasSelection ? [this.selectedNode] : [];
+          var selectedNode = this.selectedNode;
+          return selectedNode ? [selectedNode] : [];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <method name="getRemovableSelectionRanges">
-        <body><![CDATA[ 
+        <body><![CDATA[
           return [this.getSelectionNodes()];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
-      <method name="getCopyableSelection">
-        <body><![CDATA[ 
-          return this.getSelectionNodes();
-        ]]></body>
-      </method>
-
-      <!-- nsIPlacesView -->
       <method name="getDragableSelection">
         <body><![CDATA[
-          if (PlacesUtils.nodeIsReadOnly(this._result.root))
-            return null;
-          return this.getSelectionNodes();
+          return [this._draggedNode];
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <property name="selectedNode">
-        <getter><![CDATA[ 
-          return this.hasSelection ? this._selection : null;
-        ]]></getter>
-      </property>
-
-      <!-- nsIPlacesView -->
-      <property name="selectedURINode">
         <getter><![CDATA[
-          var node = this.selectedNode;
-          return node && PlacesUtils.nodeIsURI(node) ? node : null;
+          if (this._contextMenuShown) {
+            var popupNode = document.popupNode;
+            return popupNode.node || popupNode.parentNode._resultNode || null;
+          }
+          return null;
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
-          if (this._cachedInsertionPoint !== undefined)
-            return this._cachedInsertionPoint;
-
           // By default, the insertion point is at the top level, at the end. 
           var index = -1;
           var folderId = PlacesUtils.getConcreteItemId(this._result.root);
 
-          if (this.hasSelection) {
-            if (PlacesUtils.nodeIsFolder(this.selectedNode)) {
+          var selectedNode = this.selectedNode;
+          if (selectedNode) {
+            if (PlacesUtils.nodeIsFolder(selectedNode)) {
               // If there is a folder selected, the insertion point is the
               // end of the folder.
-              folderId = PlacesUtils.getConcreteItemId(this.selectedNode);
-            } else {
+              folderId = PlacesUtils.getConcreteItemId(selectedNode);
+            }
+            else {
               // If there is another type of node selected, the insertion point
               // is after that node.
-              index = PlacesUtils.getIndexOfNode(this.selectedNode);
+              folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
+              index = PlacesUtils.getIndexOfNode(selectedNode);
             }
           }
-          this._cachedInsertionPoint = new InsertionPoint(folderId, index, 1);
-          return this._cachedInsertionPoint;
+          return new InsertionPoint(folderId, index, 1);
         ]]></getter>
       </property>
 
       <!-- nsIPlacesView -->
       <method name="selectAll">
         <body><![CDATA[ 
           // Nothing
         ]]></body>
@@ -699,17 +682,17 @@
           // Timer to open a menubutton that's being dragged over.
           if (timer == this._overFolder.openTimer) {
             // Set the autoopen attribute on the folder's menupopup so that
             // the menu will automatically close when the mouse drags off of it.
             this._overFolder.node.lastChild.setAttribute("autoopened", "true");
             this._overFolder.node.open = true;
             this._overFolder.openTimer = null;
           }
-          
+
           // Timer to close a menubutton that's been dragged off of.
           if (timer == this._overFolder.closeTimer) {
             // Only close the menubutton if the drag session isn't currently over
             // it or one of its children.  (The autoopened attribute will let the menu
             // know to close later if the menu is still being dragged over.)
             var currentNode = PlacesControllerDragHelper.currentDropTarget;
             var inHierarchy = false;
             while (currentNode) {
@@ -723,17 +706,17 @@
             // So null it out if we don't want to close it.
             if (inHierarchy)
               this._overFolder.node = null;
             
             // Clear out the folder and all associated timers.
             this._clearOverFolder();
           }
         },
-        
+
         // The mouse is no longer dragging over the stored menubutton.
         // Close the menubutton, clear out drag styles, and clear all
         // timers for opening/closing it.
         _clearOverFolder: function TBV_DO_clearOverFolder() {
           if (this._overFolder.node && this._overFolder.node.lastChild) {
             if (!this._overFolder.node.lastChild.hasAttribute("dragover")) {
               this._overFolder.node.lastChild.hidePopup();
             }
@@ -744,26 +727,26 @@
             this._overFolder.openTimer.cancel();
             this._overFolder.openTimer = null;
           }
           if (this._overFolder.closeTimer) {
             this._overFolder.closeTimer.cancel();
             this._overFolder.closeTimer = null;
           }
         },
-        
+
         // This function returns information about where to drop when
         // dragging over this menu--insertion point, child index to drop
         // before, and folder to drop into.
         _getDropPoint: function TBV_DO_getDropPoint(event) {
           // Can't drop if the toolbar isn't a folder.
           var result = this._self.getResult();
           if (!PlacesUtils.nodeIsFolder(result.root))
             return null;
-          
+
           var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
           // Loop through all the nodes to see which one this should
           // get dropped in/next to
           for (var i = 0; i < this._self.childNodes.length; i++) {
             var xulNode = this._self.childNodes[i];
             if (PlacesUtils.nodeIsFolder(xulNode.node) &&
                 !PlacesUtils.nodeIsReadOnly(xulNode.node)) {
               NS_ASSERT(xulNode.getAttribute("type") == "menu");
@@ -782,17 +765,18 @@
                 // Drop inside this folder.
                 dropPoint.ip =
                   new InsertionPoint(PlacesUtils.getConcreteItemId(xulNode.node),
                                      -1, 1);
                 dropPoint.beforeIndex = i;
                 dropPoint.folderNode = xulNode;
                 return dropPoint;
               }
-            } else{
+            }
+            else {
               // This is a non-folder node. If the mouse is left of the middle,
               // drop to the left of the folder.  If it's right, drop to the right.
               if (event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width / 2)) {
                 // Drop to the left of this bookmark.
                 dropPoint.ip =
 	        new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
 	                           i, -1);
                 dropPoint.beforeIndex = i;
@@ -804,43 +788,50 @@
           dropPoint.ip =
 	  new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
 	                     -1, 1);
           dropPoint.beforeIndex = -1;
           return dropPoint;
         },
         
         onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
+          // sub menus have their own d&d handlers
+          if (event.target.parentNode != this._self)
+            return false;
+
           if (event.target.localName == "toolbarbutton" &&
               event.target.getAttribute("type") == "menu") {
 #ifdef XP_WIN
             // Support folder dragging on the personal toolbar when the user 
             // holds the "alt" key while they drag (Ctrl+drag has another 
             // meaning - Copy). This does not appear to work at all on Linux.
             if (!event.shiftKey && !event.altKey && !event.ctrlKey)
               return false;
             event.target.firstChild.hidePopup();
 #else
             return;
 #endif
           }
 
-          if (event.ctrlKey) {
+          if (event.ctrlKey)
             dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
-          }
+
+          // activate the view and cache the dragged node
+          this._self._draggedNode = event.target.node;
+          this._self.focus();
           xferData.data = this._self._controller.getTransferData(dragAction.action);
 #ifdef XP_WIN
           return true;
 #endif
         },
-        
+
         canDrop: function TBV_DO_canDrop(event, session) {
           return PlacesControllerDragHelper.canDrop();
         },
-        
+
         onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
           PlacesControllerDragHelper.currentDropTarget = event.target;
           var dropPoint = this._getDropPoint(event);
           var ib = this._self._dropIndicatorBar;
           if (this._ibTimer) {
             this._ibTimer.cancel();
             this._ibTimer = null;
           }
@@ -869,17 +860,18 @@
               if (!this._self.childNodes.length)
                 ind.style.marginLeft = 0 - this._self.boxObject.x - halfInd + 'px'
               else if (dropPoint.beforeIndex == -1)
                 ind.style.marginLeft = this._self.lastChild.boxObject.x + 
                                        this._self.lastChild.boxObject.width - this._self.boxObject.x - halfInd + 'px';
               else
                 ind.style.marginLeft = this._self.childNodes[dropPoint.beforeIndex].boxObject.x -
                                        this._self.boxObject.x - halfInd + 'px';
-            } else {
+            }
+            else {
               halfInd = Math.floor(halfInd);
               if (dropPoint.beforeIndex == -1 || !this._self.childNodes.length)
                 ind.style.marginRight = '0px';
               else
                 ind.style.marginRight = (this._self.childNodes[this._self.childNodes.length - 1].boxObject.x +
                                          this._self.childNodes[this._self.childNodes.length - 1].boxObject.width) -
                                         (this._self.childNodes[dropPoint.beforeIndex].boxObject.x) - halfInd + 'px';
             }
@@ -941,24 +933,26 @@
         ]]></body>
       </method>
 
       <property name="selType" onget="return 'single';"/>
 
       <method name="buildContextMenu">
         <parameter name="aPopup"/>
         <body><![CDATA[
+          this._contextMenuShown = true;
           this.focus();
           return this.controller.buildContextMenu(aPopup);
         ]]></body>
       </method>
 
       <method name="destroyContextMenu">
         <parameter name="aPopup"/>
         <body><![CDATA[
+          this._contextMenuShown = false;
           if (window.content)
             window.content.focus();
         ]]></body>
       </method>
 
       <method name="_showEmptyMenuItem">
         <parameter name="aPopup"/>
         <body><![CDATA[
@@ -1047,32 +1041,16 @@
         var button = event.target;
         if (button.parentNode == this && button.node &&
             PlacesUtils.nodeIsURI(button.node))
           window.XULBrowserWindow.setOverLink(event.target.node.uri, null);
       ]]></handler>
       <handler event="mouseout"><![CDATA[
         window.XULBrowserWindow.setOverLink("", null);
       ]]></handler>
-      <handler event="mousedown"><![CDATA[
-        // When the user clicks down on a button, set it as the selection and 
-        // tell the controller that we are the active view.
-        //
-        var target = event.target;
-        if (target == this)
-          this._selection = this.getResult().root;
-        else if (target.parentNode == this &&
-                 (target.localName == "toolbarbutton" ||
-                  target.localName == "toolbarseparator"))
-          this._selection = target.node;
-        else  // Sub-menus are handled by the DOMMenuItemActive handler
-          return;
-
-        this._cachedInsertionPoint = undefined;
-      ]]></handler>
       <handler event="draggesture"><![CDATA[
         if (event.target.localName == "toolbarbutton" ||
             event.target.localName == "toolbarseparator")
           nsDragAndDrop.startDrag(event, this._DNDObserver);
       ]]></handler>
       <handler event="dragover"><![CDATA[
         if (!this.checkForMenuEvent(event, "dragOver"))
           nsDragAndDrop.dragOver(event, this._DNDObserver);
@@ -1115,45 +1093,16 @@
           target._resultNode.containerOpen = false;
 
         var targetParent = target.parentNode;
         if (targetParent.localName == "toolbarbutton" &&
             !PlacesControllerDragHelper.getSession())
           this._openedMenuButton = null;
       ]]></handler>
 
-       <!-- Set selected node on DOMMenuItemActive/contextmenu events
-           so that they're set up when command and click events fire. -->
-      <handler event="DOMMenuItemActive"><![CDATA[
-        // Set the selection to the node that was activated.  If that
-        // node has a command but no data associated with it, it should
-        // act on the entire menu.
-        if (event.target.parentNode._resultNode) {
-          // the chevron has its own view
-          if (this._isChevronChild(event.target))
-            return;
-
-          this._cachedInsertionPoint = undefined;
-          this._selection = event.target.node ||
-                            event.target.parentNode._resultNode;
-        }
-      ]]></handler>
-      <handler event="contextmenu"><![CDATA[
-        // DOMMenuItemActive is not dispatched for disabled menuitems and
-        // menuseparators. Set the selection here manually.
-        var popupNode = document.popupNode;
-        // the chevron has its own view
-        if (this._isChevronChild(popupNode))
-          return;
-
-        // |popupNode == menupopup| happens when the area between menuseparators
-        // is clicked.
-        this._selection = popupNode.node || popupNode.parentNode._resultNode;
-        this._cachedInsertionPoint = undefined;
-      ]]></handler>
       <handler event="mousemove"><![CDATA[
         if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
           return;
 
         var target = event.originalTarget;
         if (this._openedMenuButton != target &&
             target.localName == "toolbarbutton" &&
             target.type == "menu") {
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -92,25 +92,16 @@
         <body><![CDATA[
           // preserve grouping
           var queryNode = asQuery(this.getResultNode());
           var options = queryNode.queryOptions.clone();
 
           var query = PlacesUtils.history.getNewQuery();
           query.searchTerms = filterString;
 
-          // Remove "group by folder" from the options list, because
-          // nsNavHistory::RecursiveGroup doesn't support it.
-          function isFolderGrouping(grouping, index, ary) {
-            return grouping != Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER;
-          }
-          var groupings = options.getGroupingMode({});
-          var folderGroupings = groupings.filter(isFolderGrouping);
-          options.setGroupingMode(folderGroupings, folderGroupings.length);
-
           if (folderRestrict) {
             query.setFolders(folderRestrict, folderRestrict.length);
             options.queryType = options.QUERY_TYPE_BOOKMARKS;
           }
 
           this.load([query], options);
         ]]></body>
       </method>
@@ -335,23 +326,16 @@
       </property>
 
       <!-- nsIPlacesView -->
       <property name="hasSelection">
         <getter><![CDATA[
           return this.view.selection.count >= 1;
         ]]></getter>
       </property>
-
-      <!-- nsIPlacesView -->
-      <property name="hasSingleSelection">
-        <getter><![CDATA[
-          return this.view.selection.count == 1;
-        ]]></getter>
-      </property>
       
       <!-- nsIPlacesView -->
       <method name="getSelectionNodes">
         <body><![CDATA[ 
           var selection = this.view.selection;
           var rc = selection.getRangeCount();
           var nodes = [];
           var resultview = this.getResultView();
@@ -414,69 +398,36 @@
             }
             nodes.push(range);
           }
           return nodes;
         ]]></body>
       </method>
       
       <!-- nsIPlacesView -->
-      <method name="getCopyableSelection">
-        <body><![CDATA[ 
-          // XXXben implement me!
-          return this.getSelectionNodes();
-        ]]></body>
-      </method>
-
-      <!-- nsIPlacesView -->
       <method name="getDragableSelection">
         <body><![CDATA[
-          var nodes = this.getSelectionNodes();
-          for (var i = nodes.length - 1; i >= 0; i--) {
-            if (PlacesUtils.nodeIsReadOnly(nodes[i].parent))
-              nodes.splice(i, 1);
-          }
-          return nodes;
+          return this.getSelectionNodes();
         ]]></body>
       </method>
       
       <!-- nsIPlacesView -->
       <property name="selectedNode">
         <getter><![CDATA[
           var view = this.view;
+          if (view.selection.count != 1)
+            return null;
+
           var selection = view.selection;
-          var rc = selection.getRangeCount();
-          if (rc != 1) 
-            return null;
           var min = { }, max = { };
           selection.getRangeAt(0, min, max);
 
           return this.getResultView().nodeForTreeIndex(min.value);
         ]]></getter>
       </property>
-      
-      <!-- nsIPlacesView -->
-      <property name="selectedURINode">
-        <getter><![CDATA[
-          var view = this.view;
-          var selection = view.selection;
-          var rc = selection.getRangeCount();
-          if (rc != 1) 
-            return null;
-          var min = { }, max = { };
-          selection.getRangeAt(0, min, max);
-
-          // only URI nodes should be returned
-          var node = this.getResultView().nodeForTreeIndex(min.value);
-          if (PlacesUtils.nodeIsURI(node))
-            return node;
-          return null;
-        ]]></getter>
-      </property>
-
 
       <!-- nsIPlacesView -->
       <property name="insertionPoint">
         <getter><![CDATA[
           // invalidated on selection and focus changes
           if (this._cachedInsertionPoint !== undefined)
             return this._cachedInsertionPoint;
 
@@ -521,17 +472,17 @@
           // than adjacent to it. Note that this only applies to _single_ 
           // selections - if the last element within a multi-selection is an
           // open folder, insert _adajacent_ to the selection.
           //
           // If the sole selection is the bookmarks toolbar folder, we insert
           // into it even if it is not opened
           var itemId =
             PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value));
-          if (this.hasSingleSelection && resultView.isContainer(max.value) &&
+          if (selection.count == 1 && resultView.isContainer(max.value) &&
               (resultView.isContainerOpen(max.value) ||
                itemId == PlacesUtils.bookmarksMenuFolderId))
             orientation = Ci.nsITreeView.DROP_ON;
 
           this._cachedInsertionPoint =
             this._getInsertionPoint(max.value, orientation);
           return this._cachedInsertionPoint;
         ]]></getter>
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -80,16 +80,23 @@ PlacesTreeView.prototype = {
    * This is called when the result or tree may have changed.
    * It reinitializes everything. Result and/or tree can be null
    * when calling.
    */
   _finishInit: function PTV__finishInit() {
     if (this._tree && this._result)
       this.sortingChanged(this._result.sortingMode);
 
+    var qoInt = Ci.nsINavHistoryQueryOptions;
+    var options = asQuery(this._result.root).queryOptions;
+    this._showQueryAsFolder = (options &&
+        (options.resultType == qoInt.RESULTS_AS_DATE_QUERY ||
+         options.resultType == qoInt.RESULTS_AS_SITE_QUERY ||
+         options.resultType == qoInt.RESULTS_AS_DATE_SITE_QUERY));
+
     // if there is no tree, BuildVisibleList will clear everything for us
     this._buildVisibleList();
   },
 
   _computeShowSessions: function PTV__computeShowSessions() {
     NS_ASSERT(this._result, "Must have a result to show sessions!");
     this._showSessions = false;
 
@@ -104,24 +111,16 @@ PlacesTreeView.prototype = {
         resultType != Ci.nsINavHistoryQueryOptions.RESULTS_AS_FULL_VISIT)
       return; // not visits
 
     var sortType = this._result.sortingMode;
     if (sortType != nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING &&
         sortType != nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING)
       return; // not date sorting
 
-    // showing sessions only makes sense if we are grouping by date
-    // any other grouping (or recursive grouping) doesn't make sense
-    var groupings = options.getGroupingMode({});
-    for (var i=0; i < groupings.length; i++) {
-      if (groupings[i] != Ci.nsINavHistoryQueryOptions.GROUP_BY_DAY)
-        return; // non-time-based grouping
-    }
-
     this._showSessions = true;
   },
 
   SESSION_STATUS_NONE: 0,
   SESSION_STATUS_START: 1,
   SESSION_STATUS_CONTINUE: 2,
   _getRowSessionStatus: function PTV__getRowSessionStatus(aRow) {
     var node = this._visibleElements[aRow];
@@ -195,36 +194,16 @@ PlacesTreeView.prototype = {
     const openLiteral = PlacesUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
     const trueLiteral = PlacesUtils.RDF.GetLiteral("true");
 
     var cc = aContainer.childCount;
     for (var i=0; i < cc; i++) {
       var curChild = aContainer.getChild(i);
       var curChildType = curChild.type;
 
-      // collapse all duplicates starting from here
-      if (this._collapseDuplicates) {
-        var showThis = { value: false };
-        while (i <  cc - 1 &&
-               this._canCollapseDuplicates(curChild, aContainer.getChild(i+1),
-                                           showThis)) {
-          if (showThis.value) {
-            // collapse the first and use the second
-            curChild.viewIndex = -1;
-            curChild = aContainer.getChild(i+1);
-            curChildType = curChild.type;
-          }
-          else {
-            // collapse the second and use the first
-            aContainer.getChild(i+1).viewIndex = -1;
-          }
-          i++;
-        }
-      }
-
       // don't display separators when sorted
       if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
         if (this._result.sortingMode !=
             Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
           curChild.viewIndex = -1;
           continue;
         }
       }
@@ -413,40 +392,16 @@ PlacesTreeView.prototype = {
         selection.rangedSelect(previouslySelectedNodes[0].oldIndex,
                                previouslySelectedNodes[0].oldIndex, true);
       }
 
       selection.selectEventsSuppressed = false;
     }
   },
 
-  /**
-   * This returns true if the two results can be collapsed as duplicates.
-   * aShowThisOne will be either 0 or 1, indicating which of the
-   * duplicates should be shown.
-   */
-  _canCollapseDuplicates:
-  function PTV__canCollapseDuplicate(aTop, aNext, aShowThisOne) {
-    if (!this._collapseDuplicates)
-      return false;
-    if (!PlacesUtils.nodeIsVisit(aTop) ||
-        !PlacesUtils.nodeIsVisit(aNext))
-      return false; // only collapse two visits
-
-    asVisit(aTop);
-    asVisit(aNext);
-
-    if (aTop.uri != aNext.uri)
-      return false; // don't collapse nonmatching URIs
-
-    // now we know we want to collapse, show the one with the more recent time
-    aShowThisOne.value = aTop.time < aNext.time;
-    return true;
-  },
-
   _convertPRTimeToString: function PTV__convertPRTimeToString(aTime) {
     var timeInMilliseconds = aTime / 1000; // PRTime is in microseconds
     var timeObj = new Date(timeInMilliseconds);
 
     // Check if it is today and only display the time.  Only bother
     // checking for today if it's within the last 24 hours, since
     // computing midnight is not really cheap. Sometimes we may get dates
     // in the future, so always show those.
@@ -595,54 +550,16 @@ PlacesTreeView.prototype = {
         // At the end of the child list without finding a visible sibling: This
         // is a little harder because we don't know how many rows the last item
         // in our list takes up (it could be a container with many children).
         var prevChild = aParent.getChild(aNewIndex - 1);
         newViewIndex = prevChild.viewIndex + this._countVisibleRowsForItem(prevChild);
       }
     }
 
-    // Try collapsing with the previous node. Note that we do not have to try
-    // to redraw the surrounding rows (which we normally would because session
-    // boundaries may have changed) because when an item is merged, it will
-    // always be in the same session.
-    var showThis =  { value: true };
-    if (newViewIndex > 0 &&
-        this._canCollapseDuplicates
-          (this._visibleElements[newViewIndex - 1], aItem, showThis)) {
-      if (!showThis.value) {
-        // new node is invisible, collapsed with previous one
-        aItem.viewIndex = -1;
-      }
-      else {
-        // new node replaces the previous
-       this.itemReplaced(aParent, this._visibleElements[newViewIndex - 1],
-                         aItem, 0);
-      }
-      return;
-    }
-
-    // try collapsing with the next node (which is currently at the same
-    // index we are trying to insert at)
-    if (newViewIndex < this._visibleElements.length &&
-        this._canCollapseDuplicates(aItem, this._visibleElements[newViewIndex],
-                                    showThis)) {
-      if (!showThis.value) {
-        // new node replaces the next node
-        this.itemReplaced(aParent, this._visibleElements[newViewIndex], aItem,
-                          0);
-      }
-      else {
-        // new node is invisible, replaced by next one
-        aItem.viewIndex = -1;
-      }
-      return;
-    }
-
-    // no collapsing, insert new item
     aItem.viewIndex = newViewIndex;
     this._visibleElements.splice(newViewIndex, 0, aItem);
     for (var i = newViewIndex + 1;
          i < this._visibleElements.length; i ++) {
       this._visibleElements[i].viewIndex = i;
     }
     this._tree.rowCountChanged(newViewIndex, 1);
 
@@ -663,50 +580,24 @@ PlacesTreeView.prototype = {
 
   // this is used in itemRemoved and itemMoved to fix viewIndex values
   // throw if the item has an invalid viewIndex
   _fixViewIndexOnRemove: function PTV_fixViewIndexOnRemove(aItem, aParent) {
     var oldViewIndex = aItem.viewIndex;
     // this may have been a container, in which case it has a lot of rows
     var count = this._countVisibleRowsForItem(aItem);
 
-    // We really want tail recursion here, since we sometimes do another
-    // remove after this when duplicates are being collapsed. This loop
-    // emulates that.
-    while (true) {
-      if (oldViewIndex > this._visibleElements.length)
-        throw("Trying to remove an item with an invalid viewIndex");
-
-      this._visibleElements.splice(oldViewIndex, count);
-      for (var i = oldViewIndex; i < this._visibleElements.length; i++)
-        this._visibleElements[i].viewIndex = i;
-
-      this._tree.rowCountChanged(oldViewIndex, -count);
+    if (oldViewIndex > this._visibleElements.length)
+      throw("Trying to remove an item with an invalid viewIndex");
 
-      // the removal might have put two things together that should be collapsed
-      if (oldViewIndex > 0 &&
-          oldViewIndex < this._visibleElements.length) {
-        var showThisOne =  { value: true };
-        if (this._canCollapseDuplicates
-             (this._visibleElements[oldViewIndex - 1],
-              this._visibleElements[oldViewIndex], showThisOne))
-        {
-          // Fake-tail-recurse to the beginning of this function to
-          // remove the collapsed row. Note that we need to set the
-          // visible index to -1 before looping because we can never
-          // touch the row we're removing (callers may have already
-          // destroyed it).
-          oldViewIndex = oldViewIndex - 1 + (showThisOne.value ? 1 : 0);
-          this._visibleElements[oldViewIndex].viewIndex = -1;
-          count = 1; // next time remove one row
-          continue;
-        }
-      }
-      break; // normal path: just remove once
-    }
+    this._visibleElements.splice(oldViewIndex, count);
+    for (var i = oldViewIndex; i < this._visibleElements.length; i++)
+      this._visibleElements[i].viewIndex = i;
+
+    this._tree.rowCountChanged(oldViewIndex, -count);
 
     // redraw parent because twisty may have changed
     if (!aParent.hasChildren)
       this.itemChanged(aParent);
 
     return;
   },
 
@@ -912,32 +803,16 @@ PlacesTreeView.prototype = {
     // we should do nothing.
     if (this._result != val) {
       this._result = val;
       this._finishInit();
     }
     return val;
   },
 
-  // nsINavHistoryResultTreeViewer
-  get collapseDuplicates() {
-    return this._collapseDuplicates;
-  },
-
-  set collapseDuplicates(val) {
-    if (this._collapseDuplicates == val)
-      return val; // no change;
-
-    this._collapseDuplicates = val;
-    if (this._tree && this._result)
-      this.invalidateAll();
-
-    return val;
-  },
-
   nodeForTreeIndex: function PTV_nodeForTreeIndex(aIndex) {
     if (aIndex > this._visibleElements.length)
       throw Cr.NS_ERROR_INVALID_ARG;
 
     return this._visibleElements[aIndex];
   },
 
   treeIndexForNode: function PTV_treeNodeForIndex(aNode) {
@@ -1002,20 +877,22 @@ PlacesTreeView.prototype = {
 
     if (columnType != "title")
       return;
 
     var node = this._visibleElements[aRow];
 
     var nodeType = node.type;
     if (PlacesUtils.containerTypes.indexOf(nodeType) != -1) {
-      if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
+      if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
         aProperties.AppendElement(this._getAtomFor("query"));
-      else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
-               nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
+        if (this._showQueryAsFolder)
+          aProperties.AppendElement(this._getAtomFor("folder"));
+      } else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
+                 nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
         if (PlacesUtils.annotations.itemHasAnnotation(node.itemId,
                                                       LMANNO_FEEDURI))
           aProperties.AppendElement(this._getAtomFor("livemark"));
         else if (PlacesUtils.bookmarks.getFolderIdForItem(node.itemId) ==
                  PlacesUtils.tagsFolderId)
           aProperties.AppendElement(this._getAtomFor("tagContainer"));
       }
     }
@@ -1462,16 +1339,15 @@ PlacesTreeView.prototype = {
 };
 
 function PlacesTreeView(aShowRoot, aFlatList, aOnOpenFlatContainer) {
   if (aShowRoot && aFlatList)
     throw("Flat-list mode is not supported when show-root is set");
 
   this._tree = null;
   this._result = null;
-  this._collapseDuplicates = true;
   this._showSessions = false;
   this._selection = null;
   this._visibleElements = [];
   this._showRoot = aShowRoot;
   this._flatList = aFlatList;
   this._openContainerCallback = aOnOpenFlatContainer;
 }
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -344,40 +344,47 @@ var PlacesUtils = {
   /**
    * Determines whether or not a ResultNode is a host container.
    * @param   aNode
    *          A result node
    * @returns true if the node is a host container, false otherwise
    */
   nodeIsHost: function PU_nodeIsHost(aNode) {
     NS_ASSERT(aNode, "null node");
-    return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST;
+    return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
+           aNode.parent &&
+           asQuery(aNode.parent).queryOptions.resultType ==
+             Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY;
   },
 
   /**
    * Determines whether or not a ResultNode is a day container.
    * @param   node
    *          A NavHistoryResultNode
    * @returns true if the node is a day container, false otherwise
    */
   nodeIsDay: function PU_nodeIsDay(aNode) {
-    return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY;
+    NS_ASSERT(aNode, "null node");
+    var resultType;
+    return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
+           aNode.parent &&
+           ((resultType = asQuery(aNode.parent).queryOptions.resultType) ==
+               Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY ||
+             resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY);
   },
 
   /**
    * Determines whether or not a ResultNode is a container.
    * @param   aNode
    *          A result node
    * @returns true if the node is a container item, false otherwise
    */
   containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
                    Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
                    Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
-                   Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST,
-                   Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY,
                    Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
   nodeIsContainer: function PU_nodeIsContainer(aNode) {
     NS_ASSERT(aNode, "null node");
     return this.containerTypes.indexOf(aNode.type) != -1;
   },
 
   /**
    * Determines whether or not a result-node is a dynamic-container item.
@@ -1661,21 +1668,18 @@ var PlacesUtils = {
         if (!wasOpen) {
           result.viewer = null;
           aNode.containerOpen = true;
         }
         for (let i = 0; i < aNode.childCount; ++i) {
           // Include visible url nodes only
           let child = aNode.getChild(i);
           if (this.nodeIsURI(child)) {
-            // If the node contents is visible, add the uri only if its node is
-            // visible. Otherwise follow viewer's collapseDuplicates property,
-            // default to true
+            // If the node contents is visible, add the uri
             if ((wasOpen && oldViewer && child.viewIndex != -1) ||
-                (oldViewer && !oldViewer.collapseDuplicates) ||
                 urls.indexOf(child.uri) == -1) {
               urls.push({ uri: child.uri,
                           isBookmark: this.nodeIsBookmark(child) });
             }
           }
         }
         if (!wasOpen)
           aNode.containerOpen = false;
@@ -1776,16 +1780,61 @@ var PlacesUtils = {
       // skip over separators and folders
       if (this.nodeIsURI(aNodes[i]))
         urlsToOpen.push({uri: aNodes[i].uri, isBookmark: this.nodeIsBookmark(aNodes[i])});
     }
     this._openTabset(urlsToOpen, aEvent);
   },
 
   /**
+   * Loads the node's URL in the appropriate tab or window or as a web
+   * panel given the user's preference specified by modifier keys tracked by a
+   * DOM mouse/key event.
+   * @param   aNode
+   *          An uri result node.
+   * @param   aEvent
+   *          The DOM mouse/key event with modifier keys set that track the
+   *          user's preferred destination window or tab.
+   */
+  openNodeWithEvent: function PU_openNodeWithEvent(aNode, aEvent) {
+    this.openNodeIn(aNode, whereToOpenLink(aEvent));
+  },
+  
+  /**
+   * Loads the node's URL in the appropriate tab or window or as a
+   * web panel.
+   * see also openUILinkIn
+   */
+  openNodeIn: function PU_openNodeIn(aNode, aWhere) {
+    if (aNode && PlacesUtils.nodeIsURI(aNode) &&
+        PlacesUtils.checkURLSecurity(aNode)) {
+      var isBookmark = PlacesUtils.nodeIsBookmark(aNode);
+
+      if (isBookmark)
+        PlacesUtils.markPageAsFollowedBookmark(aNode.uri);
+      else
+        PlacesUtils.markPageAsTyped(aNode.uri);
+
+      // Check whether the node is a bookmark which should be opened as
+      // a web panel
+      if (aWhere == "current" && isBookmark) {
+        if (PlacesUtils.annotations
+                       .itemHasAnnotation(aNode.itemId, LOAD_IN_SIDEBAR_ANNO)) {
+          var w = getTopWin();
+          if (w) {
+            w.openWebPanel(aNode.title, aNode.uri);
+            return;
+          }
+        }
+      }
+      openUILinkIn(aNode.uri, aWhere);
+    }
+  },
+
+  /**
    * Helper for the toolbar and menu views
    */
   createMenuItemForNode: function(aNode, aContainersMap) {
     var element;
     var type = aNode.type;
     if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
       element = document.createElement("menuseparator");
     else {
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -32,16 +32,19 @@
 # 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 *****
 
+// Load DownloadUtils module for convertByteUnits
+Cu.import("resource://gre/modules/DownloadUtils.jsm");
+
 var gAdvancedPane = {
   _inited: false,
 
   /**
    * Brings the appropriate tab to the front and initializes various bits of UI.
    */
   init: function ()
   {
@@ -191,17 +194,17 @@ var gAdvancedPane = {
   showOfflineExceptions: function()
   {
     var bundlePreferences = document.getElementById("bundlePreferences");
     var params = { blockVisible     : false,
                    sessionVisible   : false,
                    allowVisible     : false,
                    prefilledHost    : "",
                    permissionType   : "offline-app",
-                   manageCapability : Ci.nsIPermissionManager.DENY_ACTION,
+                   manageCapability : Components.interfaces.nsIPermissionManager.DENY_ACTION,
                    windowTitle      : bundlePreferences.getString("offlinepermissionstitle"),
                    introText        : bundlePreferences.getString("offlinepermissionstext") };
     document.documentElement.openWindow("Browser:Permissions",
                                         "chrome://browser/content/preferences/permissions.xul",
                                         "", params);
   },
 
   /**
@@ -212,27 +215,33 @@ var gAdvancedPane = {
     var pm = Components.classes["@mozilla.org/permissionmanager;1"]
                        .getService(Components.interfaces.nsIPermissionManager);
 
     var list = document.getElementById("offlineAppsList");
     while (list.firstChild) {
       list.removeChild(list.firstChild);
     }
 
+    var bundle = document.getElementById("bundlePreferences");
+
     var enumerator = pm.enumerator;
     while (enumerator.hasMoreElements()) {
       var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       if (perm.type == "offline-app" &&
           perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
           perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
         var row = document.createElement("listitem");
         row.id = "";
-        row.className = "listitem";
-        row.setAttribute("label", perm.host);
-
+        row.className = "offlineapp";
+        row.setAttribute("host", perm.host);
+        var converted = DownloadUtils.
+                        convertByteUnits(getOfflineAppUsage(perm.host));
+        row.setAttribute("usage",
+                         bundle.getFormattedString("offlineAppUsage",
+                                                   converted));
         list.appendChild(row);
       }
     }
   },
 
   offlineAppSelected: function()
   {
     var removeButton = document.getElementById("offlineAppsListRemove");
@@ -243,17 +252,17 @@ var gAdvancedPane = {
       removeButton.setAttribute("disabled", "true");
     }
   },
 
   removeOfflineApp: function()
   {
     var list = document.getElementById("offlineAppsList");
     var item = list.selectedItem;
-    var host = item.getAttribute("label");
+    var host = item.getAttribute("host");
 
     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                             .getService(Components.interfaces.nsIPromptService);
     var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
                 prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1;
 
     var bundle = document.getElementById("bundlePreferences");
     var title = bundle.getString("offlineAppRemoveTitle");
--- a/browser/components/preferences/handlers.css
+++ b/browser/components/preferences/handlers.css
@@ -46,8 +46,12 @@ richlistitem[selected="true"] {
  * Make the icons appear.
  * Note: we display the icon box for every item whether or not it has an icon
  * so the labels of all the items align vertically.
  */
 .actionsMenu > menupopup > menuitem > .menu-iconic-left {
   display: -moz-box;
   min-width: 16px;
 }
+
+listitem.offlineapp {
+  -moz-binding: url("chrome://browser/content/preferences/handlers.xml#offlineapp");
+}
--- a/browser/components/preferences/handlers.xml
+++ b/browser/components/preferences/handlers.xml
@@ -95,9 +95,19 @@
     <implementation>
       <constructor>
         gApplicationsPane.rebuildActionsMenu();
       </constructor>
     </implementation>
 
   </binding>
 
+  <binding id="offlineapp"
+	   extends="chrome://global/content/bindings/listbox.xml#listitem">
+    <content>
+      <children>
+	<xul:listcell xbl:inherits="label=host"/>
+	<xul:listcell xbl:inherits="label=usage"/>
+      </children>
+    </content>
+  </binding>
+
 </bindings>
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -192,17 +192,17 @@ var gPrivacyPane = {
 
   /**
    * Enables/disables the "keep until" label and menulist in response to the
    * "accept cookies" checkbox being checked or unchecked.
    */
   writeAcceptCookies: function ()
   {
     var checkbox = document.getElementById("acceptCookies");
-    return checkbox.checked ? 1 : 2;
+    return checkbox.checked ? 0 : 2;
   },
 
   /**
    * Displays fine-grained, per-site preferences for cookies.
    */
   showCookieExceptions: function ()
   {
     var bundlePreferences = document.getElementById("bundlePreferences");
--- a/browser/components/preferences/selectBookmark.js
+++ b/browser/components/preferences/selectBookmark.js
@@ -64,18 +64,18 @@ var SelectBookmarkDialog = {
       if (!PlacesUtils.nodeIsSeparator(bookmarks.selectedNode))
         disableAcceptButton = false;
     }
     accept.disabled = disableAcceptButton;
   },
 
   onItemDblClick: function SBD_onItemDblClick() {
     var bookmarks = document.getElementById("bookmarks");
-    if (bookmarks.hasSingleSelection && 
-        PlacesUtils.nodeIsURI(bookmarks.selectedNode)) {
+    var selectedNode = bookmarks.selectedNode;
+    if (selectedNode && PlacesUtils.nodeIsURI(selectedNode)) {
       /**
        * The user has double clicked on a tree row that is a link. Take this to
        * mean that they want that link to be their homepage, and close the dialog.
        */
       document.documentElement.getButton("accept").click();
     }
   },
 
--- a/browser/components/safebrowsing/Makefile.in
+++ b/browser/components/safebrowsing/Makefile.in
@@ -38,21 +38,17 @@
 
 DEPTH     = ../../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS      = public src
-
-ifdef ENABLE_TESTS
-DIRS     += tests
-endif
+DIRS      = src
 
 ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
 DEFINES += -DOFFICIAL_BUILD=1
 endif
 
 # EXTRA_COMPONENTS installs components written in JS to dist/bin/components
 EXTRA_PP_COMPONENTS = \
          src/nsSafebrowsingApplication.js \
--- a/browser/components/safebrowsing/content/application.js
+++ b/browser/components/safebrowsing/content/application.js
@@ -77,27 +77,56 @@ function PROT_Application() {
       G_DebugL("UNITTESTS", "END UNITTESTS");
     }
   };
 
   runUnittests();
 #endif
   
   // expose some classes
-  this.PROT_Controller = PROT_Controller;
   this.PROT_PhishingWarden = PROT_PhishingWarden;
   this.PROT_MalwareWarden = PROT_MalwareWarden;
 
   // Load data provider pref values
   gDataProvider = new PROT_DataProvider();
 
   // expose the object
   this.wrappedJSObject = this;
 }
 
+var gInitialized = false;
+PROT_Application.prototype.initialize = function() {
+  if (gInitialized)
+    return;
+  gInitialized = true;
+
+  var obs = Cc["@mozilla.org/observer-service;1"].
+            getService(Ci.nsIObserverService);
+  obs.addObserver(this, "xpcom-shutdown", true);
+
+  // XXX: move table names to a pref that we originally will download
+  // from the provider (need to workout protocol details)
+  this.malwareWarden = new PROT_MalwareWarden();
+  this.malwareWarden.registerBlackTable("goog-malware-shavar");
+  this.malwareWarden.maybeToggleUpdateChecking();
+
+  this.phishWarden = new PROT_PhishingWarden();
+  this.phishWarden.registerBlackTable("goog-phish-shavar");
+  this.phishWarden.maybeToggleUpdateChecking();
+}
+
+PROT_Application.prototype.observe = function(subject, topic, data) {
+  switch (topic) {
+    case "xpcom-shutdown":
+      this.malwareWarden.shutdown();
+      this.phishWarden.shutdown();
+      break;
+  }
+}
+
 /**
  * @param name String The type of url to get (either Phish or Error).
  * @return String the report phishing URL (localized).
  */
 PROT_Application.prototype.getReportURL = function(name) {
   return gDataProvider["getReport" + name + "URL"]();
 }
 
@@ -116,14 +145,16 @@ PROT_Application.prototype.newChannel = 
 }
 
 PROT_Application.prototype.getURIFlags = function(uri) {
   return Ci.nsIAboutModule.ALLOW_SCRIPT;
 }
 
 PROT_Application.prototype.QueryInterface = function(iid) {
   if (iid.equals(Ci.nsISupports) ||
+      iid.equals(Ci.nsISupportsWeakReference) ||
+      iid.equals(Ci.nsIObserver) ||
       iid.equals(Ci.nsIAboutModule))
     return this;
 
   Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
   return null;
 }
deleted file mode 100644
--- a/browser/components/safebrowsing/content/browser-view.js
+++ /dev/null
@@ -1,590 +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 Google Safe Browsing.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Fritz Schneider <fritz@google.com> (original author)
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-// There is one BrowserView per browser window, and each BrowserView
-// is responsible for keeping track of problems (phishy documents)
-// within that window. The BrowserView is also responsible for
-// figuring out what to do about such problems, for example, whether
-// the tab with a phishy page is currently showing and therefore if we
-// should be showing a warning.
-// 
-// The BrowserView receives information from three places:
-//
-// - from the phishing warden. When the phishing warden notices a
-//   problem, it queries all browser views to see which one (if any)
-//   has the Document that is problematic. It then hands the problem
-//   off to the appropriate BrowserView.
-// 
-// - from the controller. The controller responds to explicit user 
-//   actions (tab switches, requests to hide the warning message, 
-//   etc.) and let's the BrowserView know about any user action 
-//   having to do with the problems it is tracking.
-//
-// The BrowserView associates at most one "problem" with each Document
-// in the browser window. It keeps state about which Documents are 
-// problematic by storing a "problem queue" on each browser (tab).
-// At most one problematic document per browser (tab) is active
-// at any time. That is, we show the warning for at most one phishy
-// document at any one time. If another phishy doc loads in that tab,
-// it goes onto the end of the queue to be activated only when the
-// currently active document goes away.
-//
-// If we had multiple types of warnings (one for after the page had
-// loaded, one for when the user clicked a link, etc) here's where
-// we'd select the appropate one to use. As it stands, we only have
-// one displayer (an "afterload" displayer). A displayer knows _how_
-// to display a warning, whereas as the BrowserView knows _what_ and
-// _when_.
-//
-// To keep things (relatively) easy to reason about and efficient (the
-// phishwarden could be querying us inside a progresslistener
-// notification, or the controller inside an event handler), we have
-// the following rules:
-//
-// - at most one of a displayer's start() or stop() methods is called
-//   in any iteration (if calling two is required, the second is run in 
-//   the next event loop)
-// - displayers should run their operations synchronously so we don't have
-//   to look two places (here and in the displayer) to see what is happening 
-//   when
-// - displayer actions are run after cleaning up the browser view state
-//   in case they have consequences
-//
-// TODO: this could use some redesign, but I don't have time.
-// TODO: the queue needs to be abstracted, but we want another release fast,
-//       so I'm not going to touch it for the time being
-// TODO: IDN issues and canonical URLs?
-// TODO: Perhaps we should blur the page before showing a warning in order
-//       to prevent stray keystrokes?
-
-/**
- * The BrowerView is responsible for keeping track of and figuring out
- * what to do with problems within a single browser window.
- * 
- * TODO 
- * Unify all browser-related state here. Currently it's split
- * between two objects, this object and the controller. We could have
- * this object be solely responsible for UI hide/show decisions, which
- * would probably make it easier to reason about what's going on.
- * 
- * TODO 
- * Investigate an alternative model. For example, we could factor out
- * the problem signaling stuff from the tab/UI logic into a
- * ProblemRegistry. Attach listeners to new docs/requests as they go
- * by and have these listeners periodically check in with a
- * ProblemRegistry to see if they're watching a problematic
- * doc/request. If so, then have them flag the browser view to be
- * aware of the problem.
- *
- * @constructor
- * @param tabBrowser Reference to the main tabbrowser we'll use to query 
- *                   for information about active tabs/browsers.
- */ 
-function PROT_BrowserView(tabBrowser) {
-  this.debugZone = "browserview";
-  this.tabBrowser_ = tabBrowser;
-  this.doc_ = this.tabBrowser_.ownerDocument;
-}
-
-/**
- * Invoked by the warden to give us the opportunity to handle a
- * problem.  A problem is signaled once per request for a problem
- * Document and is handled at most once, so there's no issue with us
- * "losing" a problem due to multiple concurrently loading Documents
- * with the same URL.
- *
- * @param warden Reference to the warden signalling the problem. We'll
- *               need him to instantiate one of his warning displayers
- * 
- * @param request The nsIRequest that is problematic
- *
- * @returns Boolean indicating whether we handled problem
- */
-PROT_BrowserView.prototype.tryToHandleProblemRequest = function(warden,
-                                                                request) {
-  // XXX: pass around the URL instead of the request.  request.name isn't
-  // really supposed to be used and isn't guaranteed to give the URL.
-  var url = request.name;
-  var browsers = this.tabBrowser_.browsers;
-  for (var i = 0; i < browsers.length; i++) {
-    var browser = browsers[i];
-    var doc = browser.contentDocument;
-
-    // We only care about top level documents (and not about frames)
-    if (doc.location.href == url && !this.getProblem_(doc, browser)) {
-      this.isProblemDocument_(browser, doc, warden);
-      return true;
-    }
-  }
-  return false;
-}
-
-/**
- * We're sure a particular Document is problematic, so let's instantiate
- * a dispalyer for it and add it to the problem queue for the browser.
- *
- * @param browser Reference to the browser in which the problem doc resides
- *
- * @param doc Reference to the problematic document
- * 
- * @param warden Reference to the warden signalling the problem.
- */
-PROT_BrowserView.prototype.isProblemDocument_ = function(browser, 
-                                                         doc, 
-                                                         warden) {
-
-  G_Debug(this, "Document is problem: " + doc.location.href);
- 
-  var url = doc.location.href;
-
-  // We only have one type of displayer right now
-  var displayer = new warden.displayers_["afterload"]("Phishing afterload",
-                                                      browser,
-                                                      this.doc_,
-                                                      url);
-
-  // We listen for the problematic document being navigated away from
-  // so we can remove it from the problem queue
-
-  var hideHandler = BindToObject(this.onNavAwayFromProblem_, 
-                                 this, 
-                                 doc, 
-                                 browser);
-  doc.defaultView.addEventListener("pagehide", hideHandler, true);
-
-  // More info than we technically need, but it comes in handy for debugging
-  var problem = {
-    "browser_": browser,
-    "doc_": doc,
-    "displayer_": displayer,
-    "url_": url,
-    "hideHandler_": hideHandler,
-  };
-  var numInQueue = this.queueProblem_(browser, problem);
-
-  // If the queue was empty, schedule us to take something out
-  if (numInQueue == 1)
-    new G_Alarm(BindToObject(this.unqueueNextProblem_, this, browser), 0);
-}
-
-/**
- * Invoked when a problematic document is navigated away from. 
- *
- * @param doc Reference to the problematic Document navigated away from
-
- * @param browser Reference to the browser in which the problem document
- *                unloaded
- */
-PROT_BrowserView.prototype.onNavAwayFromProblem_ = function(doc, browser) {
-
-  var problem = this.getProblem_(doc, browser);
-  // We want to know if the user navigated away from the phish site
-  // before or after viewing the warning.
-  var message = problem.displayer_.messageShowing_ ? "phishnavaway"
-                                                   : "ignorenavaway";
-  G_Debug(this, "User nav'd away from problem: " + message);
-  (new PROT_Reporter).report(message, problem.url_);
-
-  G_Assert(this, doc === problem.doc_, "State doc not equal to nav away doc?");
-  G_Assert(this, browser === problem.browser_, 
-           "State browser not equal to nav away browser?");
-  
-  this.problemResolved(browser, doc);
-}
-
-/**
- * @param browser Reference to a browser we'd like to know about
- * 
- * @returns Boolean indicating if the browser in question has 
- *          problematic content
- */
-PROT_BrowserView.prototype.hasProblem = function(browser) {
-  return this.hasNonemptyProblemQueue_(browser);
-}
-
-/**
- * @param browser Reference to a browser we'd like to know about
- *
- * @returns Boolean indicating if the browser in question has a
- *          problem (i.e., it has a non-empty problem queue)
- */
-PROT_BrowserView.prototype.hasNonemptyProblemQueue_ = function(browser) {
-  try {
-    return !!browser.PROT_problemState__ && 
-      !!browser.PROT_problemState__.length;
-  } catch(e) {
-    // We could be checking a browser that has just been closed, in
-    // which case its properties will not be valid, causing the above
-    // statement to throw an error. Since this case handled elsewhere,
-    // just return false.
-    return false;
-  }
-}
-
-/**
- * Invoked to indicate that the problem for a particular problematic
- * document in a browser has been resolved (e.g., by being navigated
- * away from).
- *
- * @param browser Reference to the browser in which resolution is happening
- *
- * @param opt_doc Reference to the problematic doc whose problem was resolved
- *                (if absent, assumes the doc assocaited with the currently
- *                active displayer)
- */
-PROT_BrowserView.prototype.problemResolved = function(browser, opt_doc) {
-  var problem;
-  var doc;
-  if (!!opt_doc) {
-    doc = opt_doc;
-    problem = this.getProblem_(doc, browser);
-  } else {
-    problem = this.getCurrentProblem_(browser);
-    doc = problem.doc_;
-  }
-
-  problem.displayer_.done();
-  var wasHead = this.deleteProblemFromQueue_(doc, browser);
-
-  // Peek at the next problem (if any) in the queue for this browser
-  var queueNotEmpty = this.getCurrentProblem_(browser);
-
-  if (wasHead && queueNotEmpty) {
-    G_Debug(this, "More problems pending. Scheduling unqueue.");
-    new G_Alarm(BindToObject(this.unqueueNextProblem_, this, browser), 0);
-  }
-}
-
-/**
- * Peek at the top of the problem queue and if there's something there,
- * make it active. 
- *
- * @param browser Reference to the browser we should activate a problem
- *                displayer in if one is available
- */
-PROT_BrowserView.prototype.unqueueNextProblem_ = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-  if (!problem) {
-    G_Debug(this, "No problem in queue; doc nav'd away from? (shrug)");
-    return;
-  }
-
-  // Two problem docs that load in rapid succession could both schedule 
-  // themselves to be unqueued before this method is called. So ensure 
-  // that the problem at the head of the queue is not, in fact, active.
-  if (!problem.displayer_.isActive()) {
-
-    // It could be the case that the server is really slow to respond,
-    // so there might not yet be anything in the problem Document. If
-    // we show the warning when that's the case, the user will see a
-    // blank document greyed out, and if they cancel the dialog
-    // they'll see the page they're navigating away from because it
-    // hasn't been painted over yet (b/c there's no content for the
-    // problem page). So here we ensure that we have content for the
-    // problem page before showing the dialog.
-    var haveContent = false;
-    try {
-      // This will throw if there's no content yet
-      var h = problem.doc_.defaultView.getComputedStyle(problem.doc_.body, "")
-              .getPropertyValue("height");
-      G_Debug(this, "body height: " + h);
-
-      if (Number(h.substring(0, h.length - 2)))
-        haveContent = true;
-
-    } catch (e) {
-      G_Debug(this, "Masked in unqueuenextproblem: " + e);
-    }
-    
-    if (!haveContent) {
-
-      G_Debug(this, "Didn't get computed style. Re-queueing.");
-
-      // One stuck problem document in a page shouldn't prevent us
-      // warning on other problem frames that might be loading or
-      // loaded. So stick the Document that doesn't have content
-      // back at the end of the queue.
-      var p = this.removeProblemFromQueue_(problem.doc_, browser);
-      G_Assert(this, p === problem, "Unqueued wrong problem?");
-      this.queueProblem_(browser, problem);
-
-      // Try again in a bit. This opens us up to a potential
-      // vulnerability (put tons of hanging frames in a page
-      // ahead of your real phishy frame), but the risk at the
-      // moment is really low (plus it is outside our threat
-      // model).
-      new G_Alarm(BindToObject(this.unqueueNextProblem_, 
-                               this, 
-                               browser),
-                  200 /*ms*/);
-      return;
-    }
-
-    problem.displayer_.start();
-
-    // OK, we have content, but there there is an additional
-    // issue. Due to a bfcache bug, if we show the warning during
-    // paint suppression, the collapsing of the content pane affects
-    // the doc we're naving from :( The symptom is a page with grey
-    // screen on navigation to or from a phishing page (the
-    // contentDocument will have width zero).
-    //
-    // Paint supression lasts at most 250ms from when the parser sees
-    // the body, and the parser sees the body well before it has a
-    // height. We err on the side of caution.
-    //
-    // Thanks to bryner for helping to track the bfcache bug down.
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=319646
-    
-    if (this.tabBrowser_.selectedBrowser === browser)
-      new G_Alarm(BindToObject(this.problemBrowserMaybeSelected, 
-                               this, 
-                               browser),
-                  350 /*ms*/);
-  }
-}
-
-/**
- * Helper function that adds a new problem to the queue of problems pending
- * on this browser.
- *
- * @param browser Browser to which we should add state
- *
- * @param problem Object (structure, really) encapsulating the problem
- *
- * @returns Number indicating the number of items in the queue (and from
- *          which you can infer whether the recently added item was
- *          placed at the head, and hence should be active.
- */
-PROT_BrowserView.prototype.queueProblem_ = function(browser, problem) {
-  G_Debug(this, "Adding problem state for " + problem.url_);
-
-  if (this.hasNonemptyProblemQueue_(browser))
-    G_Debug(this, "Already has problem state. Queueing this problem...");
-
-  // First problem ever signaled on this browser? Make a new queue!
-  if (browser.PROT_problemState__ == undefined)
-    browser.PROT_problemState__ = [];
-
-  browser.PROT_problemState__.push(problem);
-  return browser.PROT_problemState__.length;
-}
-
-/**
- * Helper function that removes a problem from the queue and deactivates
- * it.
- *
- * @param doc Reference to the doc for which we should remove state
- *
- * @param browser Reference to the browser from which we should remove
- *                state
- *
- * @returns Boolean indicating if the remove problem was currently active
- *          (that is, if it was at the head of the queue)
- */
-PROT_BrowserView.prototype.deleteProblemFromQueue_ = function(doc, browser) {
-  G_Debug(this, "Deleting problem state for " + browser);
-  G_Assert(this, !!this.hasNonemptyProblemQueue_(browser),
-           "Browser has no problem state");
-
-  var problem = this.getProblem_(doc, browser);
-  G_Assert(this, !!problem, "Couldnt find state in removeproblemstate???");
-
-  var wasHead = browser.PROT_problemState__[0] === problem;
-  this.removeProblemFromQueue_(doc, browser);
-
-  var hideHandler = problem.hideHandler_;
-  G_Assert(this, !!hideHandler, "No hidehandler in state?");
-  problem.doc_.defaultView.removeEventListener("pagehide",
-                                               hideHandler,
-                                               true);
-  return wasHead;
-}
-
-/**
- * Helper function that removes a problem from the queue but does 
- * NOT deactivate it.
- *
- * @param doc Reference to the doc for which we should remove state
- *
- * @param browser Reference to the browser from which we should remove
- *                state
- *
- * @returns Boolean indicating if the remove problem was currently active
- *          (that is, if it was at the head of the queue)
- */
-PROT_BrowserView.prototype.removeProblemFromQueue_ = function(doc, browser) {
-  G_Debug(this, "Removing problem state for " + browser);
-  G_Assert(this, !!this.hasNonemptyProblemQueue_(browser),
-           "Browser has no problem state");
-
-  var problem = null;
-  // TODO Blech. Let's please have an abstraction here instead.
-  for (var i = 0; i < browser.PROT_problemState__.length; i++)
-    if (browser.PROT_problemState__[i].doc_ === doc) {
-      problem = browser.PROT_problemState__.splice(i, 1)[0];
-      break;
-    }
-  return problem;
-}
-
-/**
- * Retrieve (but do not remove) the problem state for a particular
- * problematic Document in this browser
- *
- * @param doc Reference to the problematic doc to get state for
- *
- * @param browser Reference to the browser from which to get state
- *
- * @returns Object encapsulating the state we stored, or null if none
- */
-PROT_BrowserView.prototype.getProblem_ = function(doc, browser) {
-  if (!this.hasNonemptyProblemQueue_(browser))
-    return null;
-
-  // TODO Blech. Let's please have an abstraction here instead.
-  for (var i = 0; i < browser.PROT_problemState__.length; i++)
-    if (browser.PROT_problemState__[i].doc_ === doc)
-      return browser.PROT_problemState__[i];
-  return null;
-}
-
-/**
- * Retrieve the problem state for the currently active problem Document 
- * in this browser
- *
- * @param browser Reference to the browser from which to get state
- *
- * @returns Object encapsulating the state we stored, or null if none
- */
-PROT_BrowserView.prototype.getCurrentProblem_ = function(browser) {
-  return browser.PROT_problemState__[0];
-}
-
-/**
- * Invoked by the controller when the user switches tabs away from a problem 
- * tab. 
- *
- * @param browser Reference to the tab that was switched from
- */
-PROT_BrowserView.prototype.problemBrowserUnselected = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-  G_Assert(this, !!problem, "Couldn't get state from browser");
-  problem.displayer_.browserUnselected();
-}
-
-/**
- * Checks to see if the problem browser is selected, and if so, 
- * tell it it to show its warning.
- *
- * @param browser Reference to the browser we wish to check
- */
-PROT_BrowserView.prototype.problemBrowserMaybeSelected = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-
-  if (this.tabBrowser_.selectedBrowser === browser &&
-      problem &&
-      problem.displayer_.isActive()) 
-    this.problemBrowserSelected(browser);
-}
-
-/**
- * Invoked by the controller when the user switches tabs to a problem tab
- *
- * @param browser Reference to the tab that was switched to
- */
-PROT_BrowserView.prototype.problemBrowserSelected = function(browser) {
-  G_Debug(this, "Problem browser selected");
-  var problem = this.getCurrentProblem_(browser);
-  G_Assert(this, !!problem, "No state? But we're selected!");
-  problem.displayer_.browserSelected();
-}
-
-/**
- * Invoked by the controller when the user accepts our warning. Passes
- * the accept through to the message displayer, which knows what to do
- * (it will be displayer-specific).
- *
- * @param browser Reference to the browser for which the user accepted
- *                our warning
- */
-PROT_BrowserView.prototype.acceptAction = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-
-  // We run the action only after we're completely through processing
-  // this event. We do this because the action could cause state to be
-  // cleared (e.g., by navigating the problem document) that we need
-  // to finish processing the event.
-
-  new G_Alarm(BindToObject(problem.displayer_.acceptAction, 
-                           problem.displayer_), 
-              0);
-}
-
-/**
- * Invoked by the controller when the user declines our
- * warning. Passes the decline through to the message displayer, which
- * knows what to do (it will be displayer-specific).
- *
- * @param browser Reference to the browser for which the user declined
- *                our warning
- */
-PROT_BrowserView.prototype.declineAction = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-  G_Assert(this, !!problem, "User declined but no state???");
-
-  // We run the action only after we're completely through processing
-  // this event. We do this because the action could cause state to be
-  // cleared (e.g., by navigating the problem document) that we need
-  // to finish processing the event.
-
-  new G_Alarm(BindToObject(problem.displayer_.declineAction, 
-                           problem.displayer_), 
-              0);
-}
-
-/**
- * The user wants to see the warning message. So let em! At some point when
- * we have multiple types of warnings, we'll have to mediate them here.
- *
- * @param browser Reference to the browser that has the warning the user 
- *                wants to see. 
- */
-PROT_BrowserView.prototype.explicitShow = function(browser) {
-  var problem = this.getCurrentProblem_(browser);
-  G_Assert(this, !!problem, "Explicit show on browser w/o problem state???");
-  problem.displayer_.explicitShow();
-}
deleted file mode 100644
--- a/browser/components/safebrowsing/content/controller.js
+++ /dev/null
@@ -1,203 +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 Google Safe Browsing.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Fritz Schneider <fritz@google.com> (original author)
-#   Simon B├╝nzli <zeniko@gmail.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-
-// This is our controller -- the thingy that listens to what the user
-// is doing. There is one controller per browser window, and each has
-// a BrowserView that manages information about problems within the
-// window. The controller figures out when the browser might want to
-// know about something, but the browser view figures out what exactly
-// to do (and the BrowserView's displayer figures out how to do it).
-//
-// For example, the controller might notice that the user has switched
-// to a tab that has something problematic in it. It would tell its 
-// BrowserView this, and the BrowserView would figure out whether it 
-// is appropriate to show a warning (e.g., perhaps the user previously
-// dismissed the warning for that problem). If so, the BrowserView tells
-// the displayer to show the warning. Anyhoo...
-//
-// TODO Could move all browser-related hide/show logic into the browser
-//      view. Need to think about this more.
-
-/**
- * Handles user actions, translating them into messages to the view
- *
- * @constructor
- * @param win Reference to the Window (browser window context) we should
- *            attach to
- * @param tabBrowser  Reference to the window's main tabbrowser object.
- * @param phishingWarden Reference to the PhishingWarden we should register
- *                       our browserview with
- */
-function PROT_Controller(win, tabBrowser, phishingWarden) {
-  this.debugZone = "controller";
-
-  this.win_ = win;
-  this.phishingWarden_ = phishingWarden;
-
-  // Use this to query preferences
-  this.prefs_ = new G_Preferences();
-
-  // Set us up to receive the events we want.
-  this.tabBrowser_ = tabBrowser;
-  this.onTabSwitchClosure_ = BindToObject(this.onTabSwitch, this);
-  this.tabBrowser_.mTabBox.addEventListener("select", this.onTabSwitchClosure_, true);
-
-  // Used to determine when the user has switched tabs
-  this.lastTab_ = tabBrowser.selectedBrowser;
-
-  // Install our command controllers. These commands are issued from
-  // various places in our UI, including our preferences dialog, the
-  // warning dialog, etc.
-  var commandHandlers = { 
-    "safebrowsing-show-warning" :
-      BindToObject(this.onUserShowWarning, this),
-    "safebrowsing-accept-warning" :
-      BindToObject(this.onUserAcceptWarning, this),
-    "safebrowsing-decline-warning" :
-      BindToObject(this.onUserDeclineWarning, this),
-  };
-
-  this.commandController_ = new PROT_CommandController(commandHandlers);
-  this.win_.controllers.appendController(this.commandController_);
-
-  // This guy embodies the logic of when to display warnings
-  // (displayers embody the how).
-  this.browserView_ = new PROT_BrowserView(this.tabBrowser_);
-
-  G_Debug(this, "Controller initialized.");
-}
-
-/**
- * Invoked when the browser window is closing. Do some cleanup.
- */
-PROT_Controller.prototype.shutdown = function(e) {
-  G_Debug(this, "Browser window closing. Shutting controller down.");
-
-  if (this.commandController_) {
-    this.win_.controllers.removeController(this.commandController_);
-    this.commandController_ = null;
-  }
-
-  // No need to drain the browser view's problem queue explicitly; it will
-  // receive pagehides for all the browsers in its queues as they're torn
-  // down, and it will remove them.
-  this.browserView_ = null;
-
-  if (this.tabBrowser_)
-    this.tabBrowser_.mTabBox.removeEventListener("select", this.onTabSwitchClosure_, true);
-  // Break circular refs so we can be gc'ed.
-  this.tabBrowser_ = this.lastTab_ = null;
-
-  this.win_.removeEventListener("unload", this.onShutdown_, false);
-  this.prefs_ = null;
-
-  G_Debug(this, "Controller shut down.");
-}
-
-/**
- * The user clicked the urlbar icon; they want to see the warning message
- * again.
- */
-PROT_Controller.prototype.onUserShowWarning = function() {
-  var browser = this.tabBrowser_.selectedBrowser;
-  this.browserView_.explicitShow(browser);
-}
-
-/**
- * Deal with a user accepting our warning. 
- *
- * TODO the warning hide/display instructions here can probably be moved
- * into the browserview in the future, given its knowledge of when the
- * problem doc hides/shows.
- */
-PROT_Controller.prototype.onUserAcceptWarning = function() {
-  G_Debug(this, "User accepted warning.");
-  var browser = this.tabBrowser_.selectedBrowser;
-  G_Assert(this, !!browser, "Couldn't get current browser?!?");
-  G_Assert(this, this.browserView_.hasProblem(browser),
-           "User accept fired, but browser doesn't have warning showing?!?");
-
-  this.browserView_.acceptAction(browser);
-  this.browserView_.problemResolved(browser);
-}
-
-/**
- * Deal with a user declining our warning. 
- *
- * TODO the warning hide/display instructions here can probably be moved
- * into the browserview in the future, given its knowledge of when the
- * problem doc hides/shows.
- */
-PROT_Controller.prototype.onUserDeclineWarning = function() {
-  G_Debug(this, "User declined warning.");
-  var browser = this.tabBrowser_.selectedBrowser;
-  G_Assert(this, this.browserView_.hasProblem(browser),
-           "User decline fired, but browser doesn't have warning showing?!?");
-  this.browserView_.declineAction(browser);
-  // We don't call problemResolved() here because all declining does it
-  // hide the message; we still have the urlbar icon showing, giving
-  // the user the ability to bring the warning message back up if they
-  // so desire.
-}
-
-/**
- * Notice tab switches, and display or hide warnings as appropriate.
- *
- * TODO this logic can probably move into the browser view at some
- * point. But one thing at a time.
- */
-PROT_Controller.prototype.onTabSwitch = function(e) {
-  // Filter spurious events
-  // The event target is usually tabs but can be tabpanels when tabs were opened
-  // programatically via tabbrowser.addTab().
-  if (!e.target || (e.target.localName != "tabs" && e.target.localName != "tabpanels"))
-    return;
-
-  var fromBrowser = this.lastTab_;
-  var toBrowser = this.tabBrowser_.selectedBrowser;
-
-  if (fromBrowser != toBrowser) {
-    this.lastTab_ = toBrowser;
-
-    if (this.browserView_.hasProblem(fromBrowser)) 
-      this.browserView_.problemBrowserUnselected(fromBrowser);
-
-    if (this.browserView_.hasProblem(toBrowser))
-      this.browserView_.problemBrowserSelected(toBrowser);
-  }
-}
deleted file mode 100644
--- a/browser/components/safebrowsing/content/firefox-commands.js
+++ /dev/null
@@ -1,83 +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 Google Safe Browsing.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Fritz Schneider <fritz@google.com> (original author)
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-
-// Some misc command-related plumbing used by the controller.
-
-
-/**
- * A tiny wrapper class for super-simple command handlers.
- *
- * @param commandHandlerMap An object containing name/value pairs where
- *                          the name is command name (string) and value
- *                          is the function to execute for that command
- */
-function PROT_CommandController(commandHandlerMap) {
-  this.debugZone = "commandhandler";
-  this.cmds_ = commandHandlerMap;
-}
-
-/**
- * @param cmd Command to query support for
- * @returns Boolean indicating if this controller supports cmd
- */
-PROT_CommandController.prototype.supportsCommand = function(cmd) { 
-  return (cmd in this.cmds_); 
-}
-
-/**
- * Trivial implementation
- *
- * @param cmd Command to query status of
- */
-PROT_CommandController.prototype.isCommandEnabled = function(cmd) { 
-  return true; 
-}
-  
-/**
- * Execute a command
- *
- * @param cmd Command to execute
- */
-PROT_CommandController.prototype.doCommand = function(cmd) {
-  return this.cmds_[cmd](); 
-}
- 
-/**
- * Trivial implementation
- */
-PROT_CommandController.prototype.onEvent = function(cmd) { }
-
--- a/browser/components/safebrowsing/content/globalstore.js
+++ b/browser/components/safebrowsing/content/globalstore.js
@@ -126,19 +126,23 @@ PROT_DataProvider.prototype.updateListMa
   var listManager = Cc["@mozilla.org/url-classifier/listmanager;1"]
                       .getService(Ci.nsIUrlListManager);
 
   // If we add support for changing local data providers, we need to add a
   // pref observer that sets the update url accordingly.
   listManager.setUpdateUrl(this.getUpdateURL());
 
   // setKeyUrl has the side effect of fetching a key from the server.
-  // This shouldn't happen if anti-phishing is disabled or we're in local
-  // list mode, so we need to check for that.
-  var isEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, false);
+  // This shouldn't happen if anti-phishing/anti-malware is disabled.
+  var isEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, false) ||
+                  this.prefs_.getPref(kMalwareWardenEnabledPref, false);
+  if (isEnabled) {
+    listManager.setKeyUrl(this.keyURL_);
+  }
+
   listManager.setGethashUrl(this.getGethashURL());
 }
 
 /**
  * Lookup the value of a URL from prefs file and do parameter substitution.
  */
 PROT_DataProvider.prototype.getUrlPref_ = function(prefName) {
   var url = this.prefs_.getPref(prefName);
--- a/browser/components/safebrowsing/content/list-warden.js
+++ b/browser/components/safebrowsing/content/list-warden.js
@@ -13,18 +13,17 @@
 #
 # The Original Code is Google Safe Browsing.
 #
 # The Initial Developer of the Original Code is Google Inc.
 # Portions created by the Initial Developer are Copyright (C) 2006
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Niels Provos <niels@google.com> (original author)d
-
+#   Niels Provos <niels@google.com> (original author)
 #   Fritz Schneider <fritz@google.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
--- a/browser/components/safebrowsing/content/malware-warden.js
+++ b/browser/components/safebrowsing/content/malware-warden.js
@@ -84,18 +84,18 @@ function PROT_MalwareWarden() {
 
     updateUrlRequested: function(url) { },
     streamCompleted: function() { },
     updateError: function(errorCode) { },
     updateSuccess: function(requestedTimeout) { }
   };
 
   try {
-    dbService_.beginUpdate(listener);
-    dbService_.beginStream("");
+    dbService_.beginUpdate(listener, "");
+    dbService_.beginStream("", "");
     dbService_.updateStream(testUpdate);
     dbService_.finishStream();
     dbService_.finishUpdate();
   } catch(ex) {
     // beginUpdate will throw harmlessly if there's an existing update
     // in progress, ignore failures.
   }
   G_Debug(this, "malwareWarden initialized");
deleted file mode 100644
--- a/browser/components/safebrowsing/content/phishing-afterload-displayer.js
+++ /dev/null
@@ -1,716 +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 Google Safe Browsing.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Fritz Schneider <fritz@google.com> (original author)
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-
-// Implementation of the warning message we show users when we
-// notice navigation to a phishing page after it has loaded. The
-// browser view encapsulates all the hide/show logic, so the displayer
-// doesn't need to know when to display itself, only how.
-//
-// Displayers implement the following interface:
-//
-// start() -- fired to initialize the displayer (to make it active). When
-//            called, this displayer starts listening for and responding to
-//            events. At most one displayer per tab should be active at a 
-//            time, and start() should be called at most once.
-// declineAction() -- fired when the user declines the warning.
-// acceptAction() -- fired when the user declines the warning
-// explicitShow() -- fired when the user wants to see the warning again
-// browserSelected() -- the browser is the top tab
-// browserUnselected() -- the browser is no long the top tab
-// done() -- clean up. May be called once (even if the displayer wasn't
-//           activated).
-//
-// At the moment, all displayers share access to the same xul in 
-// safebrowsing-overlay.xul. Hence the need for at most one displayer
-// to be active per tab at a time.
-
-/**
- * Factory that knows how to create a displayer appropriate to the
- * user's platform. We use a clunky canvas-based displayer for all
- * platforms until such time as we can overlay semi-transparent
- * areas over browser content.
- *
- * See the base object for a description of the constructor args
- *
- * @constructor
- */
-function PROT_PhishMsgDisplayer(msgDesc, browser, doc, url) {
-
-  // TODO: Change this to return a PhishMsgDisplayerTransp on windows
-  // (and maybe other platforms) when Firefox 2.0 hits.
-
-  return new PROT_PhishMsgDisplayerCanvas(msgDesc, browser, doc, url);
-}
-
-
-/**
- * Base class that implements most of the plumbing required to hide
- * and show a phishing warning. Subclasses implement the actual
- * showMessage and hideMessage methods. 
- *
- * This class is not meant to be instantiated directly.
- *
- * @param msgDesc String describing the kind of warning this is
- * @param browser Reference to the browser over which we display the msg
- * @param doc Reference to the document in which browser is found
- * @param url String containing url of the problem document
- * @constructor
- */
-function PROT_PhishMsgDisplayerBase(msgDesc, browser, doc, url) {
-  this.debugZone = "phishdisplayer";
-  this.msgDesc_ = msgDesc;                                // currently unused
-  this.browser_ = browser;
-  this.doc_ = doc;
-  this.url_ = url;
-
-  // We'll need to manipulate the XUL in safebrowsing-overlay.xul
-  this.messageId_ = "safebrowsing-palm-message";
-  this.messageTailId_ = "safebrowsing-palm-message-tail-container";
-  this.messageContentId_ = "safebrowsing-palm-message-content";
-  this.extendedMessageId_ = "safebrowsing-palm-extended-message";
-  this.showmoreLinkId_ = "safebrowsing-palm-showmore-link";
-  this.faqLinkId_ = "safebrowsing-palm-faq-link";
-  this.urlbarIconId_ = "safebrowsing-urlbar-icon";
-  this.refElementId_ = this.urlbarIconId_;
-
-  // We use this to report user actions to the server
-  this.reporter_ = new PROT_Reporter();
-
-  // The active UI elements in our warning send these commands; bind them
-  // to their handlers but don't register the commands until we start
-  // (because another displayer might be active)
-  this.commandHandlers_ = {
-    "safebrowsing-palm-showmore":
-      BindToObject(this.showMore_, this),
-  };
-
-  this.windowWatcher_ = 
-    Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-    .getService(Components.interfaces.nsIWindowWatcher);
-}
-
-/**
- * @returns The default background color of the browser
- */
-PROT_PhishMsgDisplayerBase.prototype.getBackgroundColor_ = function() {
-  var pref = Components.classes["@mozilla.org/preferences-service;1"].
-             getService(Components.interfaces.nsIPrefBranch);
-  return pref.getCharPref("browser.display.background_color");
-}
-
-/**
- * Fired when the user declines our warning. Report it!
- */
-PROT_PhishMsgDisplayerBase.prototype.declineAction = function() {
-  G_Debug(this, "User declined warning.");
-  G_Assert(this, this.started_, "Decline on a non-active displayer?");
-  this.reporter_.report("phishdecline", this.url_);
-
-  this.messageShouldShow_ = false;
-  if (this.messageShowing_)
-    this.hideMessage_();
-}
-
-/**
- * Fired when the user accepts our warning
- */
-PROT_PhishMsgDisplayerBase.prototype.acceptAction = function() {
-  G_Assert(this, this.started_, "Accept on an unstarted displayer?");
-  G_Assert(this, this.done_, "Accept on a finished displayer?");
-  G_Debug(this, "User accepted warning.");
-  this.reporter_.report("phishaccept", this.url_);
-
-  var url = this.getMeOutOfHereUrl_();
-  this.browser_.loadURI(url);
-}
-
-/**
- * Get the url for "Get me out of here."  This is the browser's default home
- * page, or, about:blank.
- * @return String url
- */
-PROT_PhishMsgDisplayerBase.prototype.getMeOutOfHereUrl_ = function() {
-  // Try to get their homepage from prefs.
-  var prefs = Cc["@mozilla.org/preferences-service;1"]
-              .getService(Ci.nsIPrefService).getDefaultBranch(null);
-
-  var url = "about:blank";
-  try {
-    url = prefs.getComplexValue("browser.startup.homepage",
-                                Ci.nsIPrefLocalizedString).data;
-    // If url is a pipe-delimited set of pages, just take the first one.
-    // This will need to change once bug 221445 is fixed.
-    if (url.indexOf("|") != -1)
-      url = url.split("|")[0];
-  } catch(e) {
-    G_Debug(this, "Couldn't get homepage pref: " + e);
-  }
-  
-  return url;
-}
-
-/**
- * Invoked when the browser is resized
- */
-PROT_PhishMsgDisplayerBase.prototype.onBrowserResized_ = function(event) {
-  G_Debug(this, "Got resize for " + event.target);
-
-  if (this.messageShowing_) {
-    this.hideMessage_(); 
-    this.showMessage_();
-  }
-}
-
-/**
- * Invoked by the browser view when our browser is switched to
- */
-PROT_PhishMsgDisplayerBase.prototype.browserSelected = function() {
-  G_Assert(this, this.started_, "Displayer selected before being started???");
-
-  // If messageshowing hasn't been set, then this is the first time this
-  // problematic browser tab has been on top, so do our setup and show
-  // the warning.
-  if (this.messageShowing_ === undefined) {
-    this.messageShouldShow_ = true;
-  }
-
-  this.addWarningInUrlbar_();  // Goes away when we are unselected or unloaded
-
-  // messageShouldShow might be false if the user dismissed the warning, 
-  // switched tabs, and then switched back. We're still active, but don't
-  // want to show the warning again. The user can cause it to show by
-  // clicking our icon in the urlbar.
-  if (this.messageShouldShow_)
-    this.showMessage_();
-}
-
-/**
- * Invoked to display the warning message explicitly, for example if the user
- * clicked the url warning icon.
- */
-PROT_PhishMsgDisplayerBase.prototype.explicitShow = function() {
-  this.messageShouldShow_ = true;
-  if (!this.messageShowing_)
-    this.showMessage_();
-}
-
-/** 
- * Invoked by the browser view when our browser is switched away from
- */
-PROT_PhishMsgDisplayerBase.prototype.browserUnselected = function() {
-  this.removeWarningInUrlbar_();
-  if (this.messageShowing_)
-    this.hideMessage_();
-}
-
-/**
- * Invoked to make this displayer active. The displayer will now start
- * responding to notifications such as commands and resize events. We
- * can't do this in the constructor because there might be many 
- * displayers instantiated waiting in the problem queue for a particular
- * browser (e.g., a page has multiple framed problem pages), and we
- * don't want them all responding to commands!
- *
- * Invoked zero (the page we're a warning for was nav'd away from
- * before it reaches the head of the problem queue) or one (we're
- * displaying this warning) times by the browser view.
- */
-PROT_PhishMsgDisplayerBase.prototype.start = function() {
-  G_Assert(this, this.started_ == undefined, "Displayer started twice?");
-  this.started_ = true;
-
-  this.commandController_ = new PROT_CommandController(this.commandHandlers_);
-  this.doc_.defaultView.controllers.appendController(this.commandController_);
-
-  // Add an event listener for when the browser resizes (e.g., user
-  // shows/hides the sidebar).
-  this.resizeHandler_ = BindToObject(this.onBrowserResized_, this);
-  this.browser_.addEventListener("resize",
-                                 this.resizeHandler_, 
-                                 false);
-}
-
-/**
- * @returns Boolean indicating whether this displayer is currently
- *          active
- */
-PROT_PhishMsgDisplayerBase.prototype.isActive = function() {
-  return !!this.started_;
-}
-
-/**
- * Invoked by the browser view to clean up after the user is done 
- * interacting with the message. Should be called once by the browser
- * view. 
- */
-PROT_PhishMsgDisplayerBase.prototype.done = function() {
-  G_Assert(this, !this.done_, "Called done more than once?");
-  this.done_ = true;
-
-  // If the Document we're showing the warning for was nav'd away from
-  // before we had a chance to get started, we have nothing to do.
-  if (this.started_) {
-
-    // If we were started, we must be the current problem, so these things
-    // must be showing
-    this.removeWarningInUrlbar_();
-
-    // Could be though that they've closed the warning dialog
-    if (this.messageShowing_)
-      this.hideMessage_();
-
-    if (this.resizeHandler_) {
-      this.browser_.removeEventListener("resize", 
-                                        this.resizeHandler_, 
-                                        false);
-      this.resizeHandler_ = null;
-    }
-    
-    var win = this.doc_.defaultView;
-    win.controllers.removeController(this.commandController_);
-    this.commandController_ = null;
-  }
-}
-
-/**
- * Helper function to remove a substring from inside a string.
- *
- * @param orig String to remove substring from
- * 
- * @param toRemove String to remove (if it is present)
- *
- * @returns String with the substring removed
- */
-PROT_PhishMsgDisplayerBase.prototype.removeIfExists_ = function(orig,
-                                                                toRemove) {
-  var pos = orig.indexOf(toRemove);
-  if (pos != -1)
-    orig = orig.substring(0, pos) + orig.substring(pos + toRemove.length);
-
-  return orig;
-}
-
-/**
- * This method makes our warning icon visible in the location bar. It will
- * be removed only when the problematic document is navigated awy from 
- * (i.e., when done() is called), and not when the warning is dismissed.
- */
-PROT_PhishMsgDisplayerBase.prototype.addWarningInUrlbar_ = function() {
-  var urlbarIcon = this.doc_.getElementById(this.urlbarIconId_);
-  if (!urlbarIcon)
-    return;
-  urlbarIcon.setAttribute('level', 'warn');
-}
-
-/**
- * Hides our urlbar icon
- */
-PROT_PhishMsgDisplayerBase.prototype.removeWarningInUrlbar_ = function() {
-  var urlbarIcon = this.doc_.getElementById(this.urlbarIconId_);
-  if (!urlbarIcon)
-    return;
-  urlbarIcon.setAttribute('level', 'safe');
-}
-
-/**
- * VIRTUAL -- Displays the warning message
- */
-PROT_PhishMsgDisplayerBase.prototype.showMessage_ = function() { };
-
-/**
- * VIRTUAL -- Hide the warning message from the user.
- */
-PROT_PhishMsgDisplayerBase.prototype.hideMessage_ = function() { };
-
-/**
- * Reposition the message relative to refElement in the parent window
- *
- * @param message Reference to the element to position
- * @param tail Reference to the message tail
- * @param refElement Reference to element relative to which we position
- *                   ourselves
- */
-PROT_PhishMsgDisplayerBase.prototype.adjustLocation_ = function(message,
-                                                                tail,
-                                                                refElement) {
-  var refX = refElement.boxObject.x;
-  var refY = refElement.boxObject.y;
-  var refHeight = refElement.boxObject.height;
-  var refWidth = refElement.boxObject.width;
-  G_Debug(this, "Ref element is at [window-relative] (" + refX + ", " + 
-          refY + ")");
-
-  var pixelsIntoRefY = -2;
-  var tailY = refY + refHeight - pixelsIntoRefY;
-  var tailPixelsLeftOfRefX = tail.boxObject.width;
-  var tailPixelsIntoRefX = Math.round(refWidth / 2);
-  var tailX = refX - tailPixelsLeftOfRefX + tailPixelsIntoRefX;
-
-  // Move message up a couple pixels so the tail overlaps it.
-  var messageY = tailY + tail.boxObject.height - 2;
-  var messagePixelsLeftOfRefX = 375;
-  var messageX = refX - messagePixelsLeftOfRefX;
-  G_Debug(this, "Message is at [window-relative] (" + messageX + ", " + 
-          messageY + ")");
-  G_Debug(this, "Tail is at [window-relative] (" + tailX + ", " + 
-          tailY + ")");
-
-  if (messageX < 0) {
-    // We're hanging off the left edge, switch to floating mode
-    tail.style.display = "none";
-    this.adjustLocationFloating_(message);
-    return;
-  }
-
-  tail.style.top = tailY + "px";
-  tail.style.left = tailX + "px";
-  message.style.top = messageY + "px";
-  message.style.left = messageX + "px";
-  
-  this.maybeAddScrollbars_();
-}
-
-/**
- * Position the warning bubble with no reference element.  In this case we
- * just center the warning bubble at the top of the users window.
- * @param message XULElement message bubble XUL container.
- */
-PROT_PhishMsgDisplayerBase.prototype.adjustLocationFloating_ = function(message) {
-  // Compute X offset
-  var browserX = this.browser_.boxObject.x;
-  var browserXCenter = browserX + this.browser_.boxObject.width / 2;
-  var messageX = browserXCenter - (message.boxObject.width / 2);
-
-  // Compute Y offset (top of the browser window)
-  var messageY = this.browser_.boxObject.y;
-
-  // Position message
-  message.style.top = messageY + "px";
-  message.style.left = messageX + "px";
-
-  this.maybeAddScrollbars_();
-}
-
-/**
- * Add a vertical scrollbar if we're falling out of the browser window.
- */
-PROT_PhishMsgDisplayerBase.prototype.maybeAddScrollbars_ = function() {
-  var message = this.doc_.getElementById(this.messageId_);
-  
-  var content = this.doc_.getElementById(this.messageContentId_);
-  var bottom = content.boxObject.y + content.boxObject.height;
-  var maxY = this.doc_.defaultView.innerHeight;
-  G_Debug(this, "bottom: " + bottom + ", maxY: " + maxY
-                + ", new height: " + (maxY - content.boxObject.y));
-  if (bottom > maxY) {
-    var newHeight = maxY - content.boxObject.y;
-    if (newHeight < 1)
-      newHeight = 1;
-
-    content.style.height = newHeight + "px";
-    content.style.overflow = "auto";
-  }
-}
-
-/**
- * Show the extended warning message
- */
-PROT_PhishMsgDisplayerBase.prototype.showMore_ = function() {
-  this.doc_.getElementById(this.extendedMessageId_).hidden = false;
-  this.doc_.getElementById(this.showmoreLinkId_).style.display = "none";
-
-  // set FAQ URL
-  var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
-                            .getService(Components.interfaces.nsIURLFormatter);
-  var faqURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL");
-  var labelEl = this.doc_.getElementById(this.faqLinkId_);
-  labelEl.setAttribute("href", faqURL);
-  
-  this.maybeAddScrollbars_();
-}
-
-/**
- * The user clicked on one of the links in the buble.  Display the
- * corresponding page in a new window with all the chrome enabled.
- *
- * @param url The URL to display in a new window
- */
-PROT_PhishMsgDisplayerBase.prototype.showURL_ = function(url) {
-  this.windowWatcher_.openWindow(this.windowWatcher_.activeWindow,
-                                 url,
-                                 "_blank",
-                                 null,
-                                 null);
-}
-
-/**
- * If the warning bubble came up in error, this url goes to a form
- * to notify the data provider.
- * @return url String
- */
-PROT_PhishMsgDisplayerBase.prototype.getReportErrorURL_ = function() {
-  var badUrl = this.url_;
-
-  var url = gDataProvider.getReportErrorURL();
-  url += "&url=" + encodeURIComponent(badUrl);
-  return url;
-}
-
-/**
- * URL for the user to report back to us.  This is to provide the user
- * with an action after being warned.
- */
-PROT_PhishMsgDisplayerBase.prototype.getReportGenericURL_ = function() {
-  var badUrl = this.url_;
-
-  var url = gDataProvider.getReportGenericURL();
-  url += "&url=" + encodeURIComponent(badUrl);
-  return url;
-}
-
-
-/**
- * A specific implementation of the dislpayer using a canvas. This
- * class is meant for use on platforms that don't support transparent
- * elements over browser content (currently: all platforms). 
- *
- * The main ugliness is the fact that we're hiding the content area and
- * painting the page to canvas. As a result, we must periodically
- * re-paint the canvas to reflect updates to the page. Otherwise if
- * the page was half-loaded when we showed our warning, it would
- * stay that way even though the page actually finished loading. 
- *
- * See base constructor for full details of constructor args.
- *
- * @constructor
- */
-function PROT_PhishMsgDisplayerCanvas(msgDesc, browser, doc, url) {
-  PROT_PhishMsgDisplayerBase.call(this, msgDesc, browser, doc, url);
-
-  this.dimAreaId_ = "safebrowsing-dim-area-canvas";
-  this.pageCanvasId_ = "safebrowsing-page-canvas";
-  this.xhtmlNS_ = "http://www.w3.org/1999/xhtml";     // we create html:canvas
-}
-
-PROT_PhishMsgDisplayerCanvas.inherits(PROT_PhishMsgDisplayerBase);
-
-/**
- * Displays the warning message.  First we make sure the overlay is loaded
- * then call showMessageAfterOverlay_.
- */
-PROT_PhishMsgDisplayerCanvas.prototype.showMessage_ = function() { }
-
-/**
- * This does the actual work of showing the warning message.
- */
-PROT_PhishMsgDisplayerCanvas.prototype.showMessageAfterOverlay_ = function() {
-  this.messageShowing_ = true;
-
-  // Position the canvas overlay. Order here is significant, but don't ask me
-  // why for some of these. You need to:
-  // 1. get browser dimensions
-  // 2. add canvas to the document
-  // 3. unhide the dimmer (gray out overlay)
-  // 4. display to the canvas
-  // 5. unhide the warning message
-  // 6. update link targets in warning message
-  // 7. focus the warning message
-
-  // (1)
-  var w = this.browser_.boxObject.width;
-  G_Debug(this, "browser w=" + w);
-  var h = this.browser_.boxObject.height;
-  G_Debug(this, "browser h=" + h);
-  var x = this.browser_.boxObject.x;
-  G_Debug(this, "browser x=" + w);
-  var y = this.browser_.boxObject.y;
-  G_Debug(this, "browser y=" + h);
-
-  var win = this.browser_.contentWindow;
-  var scrollX = win.scrollX;
-  G_Debug(this, "win scrollx=" + scrollX);
-  var scrollY = win.scrollY;
-  G_Debug(this, "win scrolly=" + scrollY);
-
-  // (2)
-  // We add the canvas dynamically and remove it when we're done because
-  // leaving it hanging around consumes a lot of memory.
-  var pageCanvas = this.doc_.createElementNS(this.xhtmlNS_, "html:canvas");
-  pageCanvas.id = this.pageCanvasId_;
-  pageCanvas.style.left = x + 'px';
-  pageCanvas.style.top = y + 'px';
-
-  var dimarea = this.doc_.getElementById(this.dimAreaId_);
-  this.doc_.getElementById('main-window').insertBefore(pageCanvas,
-                                                       dimarea);
-
-  // (3)
-  dimarea.style.left = x + 'px';
-  dimarea.style.top = y + 'px';
-  dimarea.style.width = w + 'px';
-  dimarea.style.height = h + 'px';
-  dimarea.hidden = false;
-  
-  // (4)
-  pageCanvas.setAttribute("width", w);
-  pageCanvas.setAttribute("height", h);
-
-  var bgcolor = this.getBackgroundColor_();
-
-  var cx = pageCanvas.getContext("2d");
-  cx.drawWindow(win, scrollX, scrollY, w, h, bgcolor);
-
-  // Now repaint the window every so often in case the content hasn't fully
-  // loaded at this point.
-  var debZone = this.debugZone;
-  function repaint() {
-    G_Debug(debZone, "Repainting canvas...");
-    cx.drawWindow(win, scrollX, scrollY, w, h, bgcolor);
-  };
-  this.repainter_ = new PROT_PhishMsgCanvasRepainter(repaint);
-
-  // (5)
-  this.showAndPositionWarning_();
-
-  // (6)
-  var link = this.doc_.getElementById('safebrowsing-palm-falsepositive-link');
-  link.href = this.getReportErrorURL_();
-
-  // (7)
-  this.doc_.getElementById(this.messageContentId_).focus();
-}
-
-/**
- * Show and position the warning message.  We position the waring message
- * relative to the icon in the url bar, but if the element doesn't exist,
- * (e.g., the user remove the url bar from her/his chrome), we anchor at the
- * top of the window.
- */
-PROT_PhishMsgDisplayerCanvas.prototype.showAndPositionWarning_ = function() {
-  var refElement = this.doc_.getElementById(this.refElementId_);
-  var message = this.doc_.getElementById(this.messageId_);
-  var tail = this.doc_.getElementById(this.messageTailId_);
-
-  message.hidden = false;
-  message.style.display = "block";
-
-  // Determine if the refElement is visible.
-  if (this.isVisibleElement_(refElement)) {
-    // Show tail and position warning relative to refElement.
-    tail.hidden = false;
-    tail.style.display = "block";
-    this.adjustLocation_(message, tail, refElement);
-  } else {
-    // No ref element, position in the top center of window.
-    tail.hidden = true;
-    tail.style.display = "none";
-    this.adjustLocationFloating_(message);
-  }
-}
-
-/**
- * @return Boolean true if elt is a visible XUL element.
- */
-PROT_PhishMsgDisplayerCanvas.prototype.isVisibleElement_ = function(elt) {
-  if (!elt)
-    return false;
-  
-  // If it's on a collapsed/hidden toolbar, the x position is set to 0.
-  if (elt.boxObject.x == 0)
-    return false;
-
-  return true;
-}
-
-/**
- * Hide the warning message from the user.
- */
-PROT_PhishMsgDisplayerCanvas.prototype.hideMessage_ = function() { }
-
-
-/**
- * Helper class that periodically repaints the canvas. We repaint
- * frequently at first, and then back off to a less frequent schedule
- * at "steady state," and finally just stop altogether. We have to do
- * this because we're not sure if the page has finished loading when
- * we first paint the canvas, and because we want to reflect any
- * dynamically written content into the canvas as it appears in the
- * page after load.
- *
- * @param repaintFunc Function to call to repaint browser.
- *
- * @constructor
- */
-function PROT_PhishMsgCanvasRepainter(repaintFunc) {
-  this.count_ = 0;
-  this.repaintFunc_ = repaintFunc;
-  this.initPeriodMS_ = 500;             // Initially repaint every 500ms
-  this.steadyStateAtMS_ = 10 * 1000;    // Go slowly after 10 seconds,
-  this.steadyStatePeriodMS_ = 3 * 1000; // repainting every 3 seconds, and
-  this.quitAtMS_ = 20 * 1000;           // stop after 20 seconds
-  this.startMS_ = (new Date).getTime();
-  this.alarm_ = new G_Alarm(BindToObject(this.repaint, this), 
-                            this.initPeriodMS_);
-}
-
-/**
- * Called periodically to repaint the canvas
- */
-PROT_PhishMsgCanvasRepainter.prototype.repaint = function() {
-  this.repaintFunc_();
-
-  var nextRepaint;
-  // If we're in "steady state", use the slow repaint rate, else fast
-  if ((new Date).getTime() - this.startMS_ > this.steadyStateAtMS_)
-    nextRepaint = this.steadyStatePeriodMS_;
-  else 
-    nextRepaint = this.initPeriodMS_;
-
-  if (!((new Date).getTime() - this.startMS_ > this.quitAtMS_))
-    this.alarm_ = new G_Alarm(BindToObject(this.repaint, this), nextRepaint);
-}
-
-/**
- * Called to stop repainting the canvas
- */
-PROT_PhishMsgCanvasRepainter.prototype.cancel = function() {
-  if (this.alarm_) {
-    this.alarm_.cancel();
-    this.alarm_ = null;
-  }
-  this.repaintFunc_ = null;
-}
--- a/browser/components/safebrowsing/content/phishing-warden.js
+++ b/browser/components/safebrowsing/content/phishing-warden.js
@@ -59,38 +59,28 @@
 // loaded).
 //
 // Note: There is a single warden for the whole application.
 //
 // TODO better way to expose displayers/views to browser view
 
 const kPhishWardenEnabledPref = "browser.safebrowsing.enabled";
 
-// We have hardcoded URLs that we let people navigate to in order to 
-// check out the warning.
-const kTestUrls = {
-  "http://www.google.com/tools/firefox/safebrowsing/phish-o-rama.html": true,
-  "http://www.mozilla.org/projects/bonecho/anti-phishing/its-a-trap.html": true,
-  "http://www.mozilla.com/firefox/its-a-trap.html": true,
-}
-
 /**
  * Abtracts the checking of user/browser actions for signs of
  * phishing. 
  *
  * @param progressListener nsIDocNavStartProgressListener
  * @param tabbrowser XUL tabbrowser element
  * @constructor
  */
 function PROT_PhishingWarden() {
   PROT_ListWarden.call(this);
 
   this.debugZone = "phishwarden";
-  this.testing_ = false;
-  this.browserViews_ = [];
 
   // Use this to query preferences
   this.prefs_ = new G_Preferences();
 
   // We need to know whether we're enabled and whether we're in advanced
   // mode, so reflect the appropriate preferences into our state.
 
   // Global preference to enable the phishing warden
@@ -101,19 +91,16 @@ function PROT_PhishingWarden() {
     BindToObject(this.onPhishWardenEnabledPrefChanged, this);
   this.prefs_.addObserver(kPhishWardenEnabledPref, phishWardenPrefObserver);
 
   G_Debug(this, "phishWarden initialized");
 }
 
 PROT_PhishingWarden.inherits(PROT_ListWarden);
 
-/**
- * We implement nsIWebProgressListener
- */
 PROT_PhishingWarden.prototype.QueryInterface = function(iid) {
   if (iid.equals(Ci.nsISupports) || 
       iid.equals(Ci.nsISupportsWeakReference))
     return this;
   throw Components.results.NS_ERROR_NO_INTERFACE;
 }
 
 /**
@@ -131,19 +118,16 @@ PROT_PhishingWarden.prototype.shutdown =
  * This is a little tricky; we start or stop management only when we
  * have complete information we can use to determine whether we
  * should.  It could be the case that one pref or the other isn't set
  * yet (e.g., they haven't opted in/out of advanced features). So do
  * nothing unless we have both pref values -- we get notifications for
  * both, so eventually we will start correctly.
  */ 
 PROT_PhishingWarden.prototype.maybeToggleUpdateChecking = function() {
-  if (this.testing_)
-    return;
-
   var phishWardenEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, null);
 
   G_Debug(this, "Maybe toggling update checking. " +
           "Warden enabled? " + phishWardenEnabled);
 
   // Do nothing unless both prefs are set.  They can be null (unset), true, or
   // false.
   if (phishWardenEnabled === null)
--- a/browser/components/safebrowsing/content/report-phishing-overlay.xul
+++ b/browser/components/safebrowsing/content/report-phishing-overlay.xul
@@ -1,70 +1,66 @@
 <?xml version="1.0"?>
-<!-- ***** BEGIN LICENSE BLOCK *****
-   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
-   -
-   - The contents of this file are subject to the Mozilla Public License Version
-   - 1.1 (the "License"); you may not use this file except in compliance with
-   - the License. You may obtain a copy of the License at
-   - http://www.mozilla.org/MPL/
-   -
-   - Software distributed under the License is distributed on an "AS IS" basis,
-   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-   - for the specific language governing rights and limitations under the
-   - License.
-   -
-   - The Original Code is Mozilla Reporter (r.m.o).
-   -
-   - The Initial Developer of the Original Code is
-   -      Robert Accettura <robert@accettura.com>.
-   -
-   - Portions created by the Initial Developer are Copyright (C) 2004
-   - the Initial Developer. All Rights Reserved.
-   -
-   - Contributor(s):
-   -      Jay Patel <jay@mozilla.org>
-   -      Gavin Sharp <gavin@gavinsharp.com>
-   -
-   - Alternatively, the contents of this file may be used under the terms of
-   - either the GNU General Public License Version 2 or later (the "GPL"), or
-   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-   - in which case the provisions of the GPL or the LGPL are applicable instead
-   - of those above. If you wish to allow use of your version of this file only
-   - under the terms of either the GPL or the LGPL, and not to allow others to
-   - use your version of this file under the terms of the MPL, indicate your
-   - decision by deleting the provisions above and replace them with the notice
-   - and other provisions required by the LGPL or the GPL. If you do not delete
-   - the provisions above, a recipient may use your version of this file under
-   - the terms of any one of the MPL, the GPL or the LGPL.
-   -
-   - ***** END LICENSE BLOCK ***** -->
-
+# ***** 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 Reporter (r.m.o).
+#
+# The Initial Developer of the Original Code is Robert Accettura <robert@accettura.com>.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Jay Patel <jay@mozilla.org>
+#  Gavin Sharp <gavin@gavinsharp.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 *****
 <!DOCTYPE overlay [
 <!ENTITY % reportphishDTD SYSTEM "chrome://browser/locale/safebrowsing/report-phishing.dtd">
 %reportphishDTD;
-<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
-%safebrowsingDTD;
 ]>
 
 <overlay id="reportPhishingMenuOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <broadcasterset id="mainBroadcasterSet">
     <broadcaster id="reportPhishingBroadcaster" disabled="true"/>
-    <broadcaster id="reportPhishingErrorBroadcaster" disabled="true"/>
+    <!--<broadcaster id="reportPhishingErrorBroadcaster" disabled="true"/>-->
   </broadcasterset>
   <menupopup id="menu_HelpPopup">
     <menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
               label="&reportPhishSiteMenu.title;..."
               accesskey="&reportPhishSiteMenu.accesskey;"
               insertbefore="updateSeparator"
               observes="reportPhishingBroadcaster"
               oncommand="openUILink(safebrowsing.getReportURL('Phish'), event);"
               onclick="checkForMiddleClick(this, event);"/>
+    <!-- XXX Bug 415846
     <menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
               label="&safeb.palm.notforgery.label;..."
               accesskey="&reportPhishSiteMenu.accesskey;"
               insertbefore="updateSeparator"
               observes="reportPhishingErrorBroadcaster"
               oncommand="openUILinkIn(safebrowsing.getReportURL('Error'), 'tab');"
-              onclick="checkForMiddleClick(this, event);"/>
+              onclick="checkForMiddleClick(this, event);"/>-->
   </menupopup>
 </overlay>
deleted file mode 100644
--- a/browser/components/safebrowsing/content/reporter.js
+++ /dev/null
@@ -1,77 +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 Google Safe Browsing.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Fritz Schneider <fritz@google.com> (original author)
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# **** END LICENSE BLOCK ****
-
-
-// A tiny class to do reporting for us. We report interesting user actions
-// such as the user hitting a blacklisted page, and the user accepting
-// or declining the warning.
-//
-// Each report has a subject and data. Current reports are:
-//
-// subject         data     meaning
-// --------------------------------
-// phishnavaway    url      the user navigated away from a phishy page
-// phishdecline    url      the user declined our warning
-// phishaccept     url      the user accepted our warning
-// phishblhit      url      the user loaded a phishing page
-//
-// We only send reports in advanced protection mode, and even then we
-// strip cookies from the request before sending it.
-
-/**
- * A very complicated class to send pings to the provider. The class does
- * nothing if we're not in advanced protection mode.
- *
- * @constructor
- */
-function PROT_Reporter() {
-  this.debugZone = "reporter";
-  this.prefs_ = new G_Preferences();
-}
-
-/**
- * Send a report!
- *
- * @param subject String indicating what this report is about (will be 
- *                urlencoded)
- * @param data String giving extra information about this report (will be 
- *                urlencoded)
- */
-PROT_Reporter.prototype.report = function(subject, data) {
-  // XXX: this is disabled for now, since we don't have advanced mode
-  // anymore.
-  return;
-}
--- a/browser/components/safebrowsing/content/sb-loader.js
+++ b/browser/components/safebrowsing/content/sb-loader.js
@@ -29,120 +29,47 @@
 # 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 *****
 
-
-/**
- * This file is included into the main browser chrome from
- * browser/base/content/global-scripts.inc
- */
-
 var safebrowsing = {
-  controller: null,
-  phishWarden: null,
+  appContext: null,
 
   startup: function() {
     setTimeout(safebrowsing.deferredStartup, 2000);
-
-    // clean up
     window.removeEventListener("load", safebrowsing.startup, false);
   },
-  
+
   deferredStartup: function() {
-    var appContext = Cc["@mozilla.org/safebrowsing/application;1"]
-                     .getService().wrappedJSObject;
-
-    var malwareWarden = new appContext.PROT_MalwareWarden();
-    safebrowsing.malwareWarden = malwareWarden;
-
-    // Register tables
-    malwareWarden.registerBlackTable("goog-malware-shavar");
-
-    malwareWarden.maybeToggleUpdateChecking();
-
-    var phishWarden = new appContext.PROT_PhishingWarden();
-    safebrowsing.phishWarden = phishWarden;
-
-    // Register tables
-    // XXX: move table names to a pref that we originally will download
-    // from the provider (need to workout protocol details)
-    phishWarden.registerBlackTable("goog-phish-shavar");
-
-    // Download/update lists if we're in non-enhanced mode
-    phishWarden.maybeToggleUpdateChecking();
-    safebrowsing.controller = new appContext.PROT_Controller(
-        window, getBrowser(), phishWarden);
-  },
-
-  /**
-   * Clean up.
-   */
-  shutdown: function() {
-    if (safebrowsing.controller) {
-      // If the user shuts down before deferredStartup, there is no controller.
-      safebrowsing.controller.shutdown();
-    }
-    if (safebrowsing.phishWarden) {
-      safebrowsing.phishWarden.shutdown();
-    }
-    if (safebrowsing.malwareWarden) {
-      safebrowsing.malwareWarden.shutdown();
-    }
-    
-    window.removeEventListener("unload", safebrowsing.shutdown, false);
+    this.appContext = Cc["@mozilla.org/safebrowsing/application;1"].
+                      getService().wrappedJSObject;
+    this.appContext.initialize();
   },
 
   setReportPhishingMenu: function() {
     var uri = getBrowser().currentURI;
-    if (!uri)
-      return;
-
-    var sbIconElt = document.getElementById("safebrowsing-urlbar-icon");
-    var helpMenuElt = document.getElementById("helpMenu");
-    var phishLevel = sbIconElt.getAttribute("level");
-
-    // Show/hide the appropriate menu item.
-    document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")
-            .hidden = ("safe" != phishLevel);
-    document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
-            .hidden = ("safe" == phishLevel);
+    var broadcaster = document.getElementById("reportPhishingBroadcaster");
+    if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
+      broadcaster.removeAttribute("disabled");
+    else
+      broadcaster.disabled = true;
+  },
 
-    var broadcasterId;
-    if ("safe" == phishLevel) {
-      broadcasterId = "reportPhishingBroadcaster";
-    } else {
-      broadcasterId = "reportPhishingErrorBroadcaster";
-    }
-
-    var broadcaster = document.getElementById(broadcasterId);
-    if (!broadcaster)
-      return;
-
-    var progressListener =
-      Cc["@mozilla.org/browser/safebrowsing/navstartlistener;1"]
-      .createInstance(Ci.nsIDocNavStartProgressListener);
-    broadcaster.setAttribute("disabled", progressListener.isSpurious(uri));
-  },
-  
   /**
    * Used to report a phishing page or a false positive
    * @param name String either "Phish" or "Error"
    * @return String the report phishing URL.
    */
   getReportURL: function(name) {
-    var appContext = Cc["@mozilla.org/safebrowsing/application;1"]
-                     .getService().wrappedJSObject;
-    var reportUrl = appContext.getReportURL(name);
+    var reportUrl = this.appContext.getReportURL(name);
 
     var pageUrl = getBrowser().currentURI.asciiSpec;
     reportUrl += "&url=" + encodeURIComponent(pageUrl);
 
     return reportUrl;
   }
 }
 
 window.addEventListener("load", safebrowsing.startup, false);
-window.addEventListener("unload", safebrowsing.shutdown, false);
deleted file mode 100644
--- a/browser/components/safebrowsing/content/warning-overlay.xul
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This css and dtd are for the phishing warning message -->
-
-<?xml-stylesheet
- href="chrome://browser/skin/safebrowsing/browser-protection.css" 
- type="text/css" ?>
-<!DOCTYPE window [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
-%brandDTD;
-<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
-%safebrowsingDTD;
-]>
-
-<overlay id="safebrowsing-overlay"
-         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <window id="main-window">
-    <!-- This is the spike aka tail on top of the warning -->
-
-    <hbox id="safebrowsing-palm-message-tail-container" hidden="true" 
-          pack="end">
-      <image id="safebrowsing-palm-message-tail"
-             src="chrome://browser/skin/safebrowsing/tail.png"/>
-    </hbox>
-
-    <!-- This is the phishing afterload warning message -->
-
-    <vbox id="safebrowsing-palm-message" hidden="true" pack="center"
-          class="safebrowsing-palm-fixed-width">
-
-      <!-- This is the main warning area -->
-
-      <vbox id="safebrowsing-palm-message-content" 
-            class="safebrowsing-palm-fixed-width"
-            style="-moz-user-focus: normal"
-            role="alert">
-
-        <hbox id="safebrowsing-palm-close-container" align="center"
-              class="safebrowsing-palm-fixed-width">
-          <spacer flex="1"/>
-          <image id="safebrowsing-palm-close"
-                 onclick="goDoCommand('safebrowsing-decline-warning')"/>
-        </hbox>
-
-        <!-- Top line -->
-        <description id="safebrowsing-palm-message-titlebox"
-                     class="safebrowsing-palm-fixed-width">
-          &safeb.palm.warning.title;
-        </description>
-
-        <!-- Content area: short warning -->
-
-        <description id="safebrowsing-palm-content"
-                     class="safebrowsing-paragraph">
-          &safeb.palm.message.p1; 
-          <label class="text-link plain"
-                 statustext="&safeb.palm.p1.linkStatusText;"
-                 id="safebrowsing-palm-showmore-link"
-                 onclick="goDoCommand('safebrowsing-palm-showmore'); document.getElementById('safebrowsing-palm-faq-link').focus()"
-                 value="&safeb.palm.message.p1.linkText;"/>
-        </description>
-
-        <!-- Content area: rest of the warning, revealed if the user
-             hits the more link -->
-
-        <vbox id="safebrowsing-palm-extended-message" hidden="true"
-              class="safebrowsing-palm-fixed-width">
-          <description class="safebrowsing-palm-paragraph">
-            &safeb.palm.message.p2.start;
-            <label class="text-link plain" id="safebrowsing-palm-faq-link"
-                   value="&safeb.palm.message.p2.linkText;"/>
-            &safeb.palm.message.p2.end;
-          </description>
-        </vbox>
-
-        <!-- Main action links -->
-        <description id="safebrowsing-palm-message-actionbox"
-                     class="safebrowsing-palm-fixed-width"
-                     align="center" crop="none">
-         <label class="safebrowsing-palm-bigtext text-link plain"
-                statustext="&safeb.palm.accept.statustext;"
-                id="safebrowsing-palm-accept-link"
-                onclick="goDoCommand('safebrowsing-accept-warning')"
-                value="&safeb.palm.accept.label;"/>
-         <spacer flex="1"/>
-         <label class="safebrowsing-palm-bigtext text-link plain"
-                statustext="&safeb.palm.decline.statustext;"
-                id="safebrowsing-palm-decline-link"
-                onclick="goDoCommand('safebrowsing-decline-warning')"
-                value="&safeb.palm.decline.label;"/>
-        </description>
-
-        <!-- Footer -->
-
-        <hbox align="center" class="safebrowsing-palm-fixed-width">
-          <spacer flex="1"/>
-          <description>
-            [
-            <label id="safebrowsing-palm-falsepositive-link"
-                   class="safebrowsing-palm-smalltext text-link plain"
-                   value="&safeb.palm.notforgery.label;"/>
-            ]
-          </description>
-        </hbox>
-      </vbox>
-    </vbox>
-
-    <!-- The canvas goes here, but since it takes up so much memory and is
-         rarely used, we add and remove it dynamically -->
-
-    <!-- This dims out the browser content -->
-    <vbox id="safebrowsing-dim-area-canvas" hidden="true">
-    </vbox>
-  </window>
-</overlay>
--- a/browser/components/safebrowsing/jar.mn
+++ b/browser/components/safebrowsing/jar.mn
@@ -1,7 +1,5 @@
 browser.jar:
-# script file included into main browser.js
 * content/browser/safebrowsing/sb-loader.js                    (content/sb-loader.js)
-+ content/browser/safebrowsing/warning-overlay.xul             (content/warning-overlay.xul)
-+ content/browser/safebrowsing/report-phishing-overlay.xul     (content/report-phishing-overlay.xul)
-+ content/browser/safebrowsing/blockedSite.xhtml               (content/blockedSite.xhtml)
+* content/browser/safebrowsing/report-phishing-overlay.xul     (content/report-phishing-overlay.xul)
+  content/browser/safebrowsing/blockedSite.xhtml               (content/blockedSite.xhtml)
 % overlay chrome://browser/content/browser.xul         chrome://browser/content/safebrowsing/report-phishing-overlay.xul
deleted file mode 100644
--- a/browser/components/safebrowsing/public/Makefile.in
+++ /dev/null
@@ -1,50 +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 mozilla.org code.
-#
-# The Initial Developer of the Original Code is Google Inc.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Brett Wilson <brettw@gmail.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-
-DEPTH     = ../../../..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE = safebrowsing
-XPIDL_MODULE = safebrowsing
-
-XPIDLSRCS = nsIDocNavStartProgressListener.idl
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/browser/components/safebrowsing/public/nsIDocNavStartProgressListener.idl
+++ /dev/null
@@ -1,78 +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 Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brett Wilson <brettw@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-interface nsIRequest;
-interface nsIURI;
-
-
-[scriptable, function, uuid(163f3437-1d69-4db7-9ce1-fd420fba8219)]
-interface nsIDocNavStartProgressCallback : nsISupports
-{
-  void onDocNavStart(in nsIRequest aRequest, in AUTF8String aUri);
-};
-
-[scriptable, uuid(013bf34b-a7a8-4f89-b0ea-169e7ddbbe15)]
-interface nsIDocNavStartProgressListener : nsISupports
-{
-  /**
-   * Set to true to enable this component. Defaults to false (disabled). When
-   * you set this to true, the listener will be attached to the docloader and
-   * the callback can start getting events.
-   */
-  attribute boolean globalProgressListenerEnabled;
-
-  /**
-   * Number of ms to wait after receiving a doc load event and calling the
-   * callback.  Even when set to zero, we set a timer so the call will fire
-   * asynchronously.  Defaults to 0.
-   */
-  attribute PRUint32 delay;
-
-  /**
-   * The callback, if non-null, used when globalProgressListenerEnabled is
-   * true.  Setting this to null has the side effect of unqueueing any pending
-   * events for which a callback would be notified; setting it to any other
-   * value, however, will not unqueue any events.
-   */
-  attribute nsIDocNavStartProgressCallback callback;
-
-  /**
-   * We ignore about:, chrome: and file: URIs.
-   */
-  boolean isSpurious(in nsIURI aURI);
-};
--- a/browser/components/safebrowsing/src/Makefile.in
+++ b/browser/components/safebrowsing/src/Makefile.in
@@ -36,23 +36,9 @@
 
 DEPTH     = ../../../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE = safebrowsing
-LIBRARY_NAME = safebrowsing_s
-FORCE_STATIC_LIB = 1
-FORCE_USE_PIC = 1
-USE_STATIC_LIBS = 1
-
-REQUIRES = \
-						necko \
-						string \
-						uriloader \
-						xpcom
-
-CPPSRCS = nsDocNavStartProgressListener.cpp
-
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/browser/components/safebrowsing/src/nsDocNavStartProgressListener.cpp
+++ /dev/null
@@ -1,379 +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 Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brett Wilson <brettw@gmail.com>
- *   based on JavaScript code by Fritz Schneider <fritz@google.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 "nsCURILoader.h"
-#include "nsDocNavStartProgressListener.h"
-#include "nsIChannel.h"
-#include "nsINestedURI.h"
-#include "nsIRequest.h"
-#include "nsITimer.h"
-#include "nsIURI.h"
-#include "nsIWebProgress.h"
-#include "nsComponentManagerUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStringAPI.h"
-#include "prlog.h"
-
-NS_IMPL_ISUPPORTS4(nsDocNavStartProgressListener,
-                   nsIDocNavStartProgressListener,
-                   nsIWebProgressListener,
-                   nsIObserver,
-                   nsISupportsWeakReference)
-
-// NSPR_LOG_MODULES=DocNavStart:5
-#if defined(PR_LOGGING)
-static const PRLogModuleInfo *gDocNavStartProgressListenerLog = nsnull;
-#define LOG(args) PR_LOG(gDocNavStartProgressListenerLog, PR_LOG_DEBUG, args)
-#else
-#define LOG(args)
-#endif
-
-nsDocNavStartProgressListener::nsDocNavStartProgressListener() :
-  mEnabled(PR_FALSE), mDelay(0), mRequests(nsnull), mTimers(nsnull)
-{
-#if defined(PR_LOGGING)
-  if (!gDocNavStartProgressListenerLog)
-    gDocNavStartProgressListenerLog = PR_NewLogModule("DocNavStart");
-#endif
-        
-}
-
-
-nsDocNavStartProgressListener::~nsDocNavStartProgressListener()
-{
-  ClearPendingEvents();
-}
-
-void
-nsDocNavStartProgressListener::ClearPendingEvents()
-{
-  mRequests.Clear();
-
-  PRUint32 length = mTimers.Count();
-  for (PRUint32 i = 0; i < length; ++i) {
-    mTimers[i]->Cancel();
-  }
-  mTimers.Clear();
-}
-
-// nsDocNavStartProgressListener::AttachListeners
-
-nsresult
-nsDocNavStartProgressListener::AttachListeners()
-{
-  nsresult rv;
-  nsCOMPtr<nsIWebProgress> webProgressService = do_GetService(
-      NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return webProgressService->AddProgressListener(this,
-      nsIWebProgress::NOTIFY_LOCATION);
-}
-
-
-// nsDocNavStartProgressListener::DetachListeners
-
-nsresult
-nsDocNavStartProgressListener::DetachListeners()
-{
-  nsresult rv;
-  nsCOMPtr<nsIWebProgress> webProgressService = do_GetService(
-      NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return webProgressService->RemoveProgressListener(this);
-}
-
-// Helper method for checking a request URI.
-nsresult
-nsDocNavStartProgressListener::GetRequestUri(nsIRequest* aReq, nsIURI** uri)
-{
-  nsCOMPtr<nsIChannel> channel;
-  nsresult rv;
-  channel = do_QueryInterface(aReq, &rv);
-  if (NS_FAILED(rv))
-    return rv;
-
-  rv = channel->GetURI(uri);
-  if (NS_FAILED(rv))
-    return rv;
-  return NS_OK;
-}
-
-
-// nsIDocNavStartProgressCallback ***********************************************
-
-// nsDocNavStartProgressListener::GetGlobalProgressListenerEnabled
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::GetGlobalProgressListenerEnabled(PRBool* aEnabled)
-{
-  *aEnabled = mEnabled;
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::SetGlobalProgressListenerEnabled
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::SetGlobalProgressListenerEnabled(PRBool aEnabled)
-{
-  if (aEnabled && ! mEnabled) {
-    // enable component
-    mEnabled = PR_TRUE;
-    return AttachListeners();
-  } else if (! aEnabled && mEnabled) {
-    // disable component
-    mEnabled = PR_FALSE;
-    return DetachListeners();
-  }
-  return NS_OK; // nothing to do
-}
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::GetDelay(PRUint32* aDelay)
-{
-  *aDelay = mDelay;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::SetDelay(PRUint32 aDelay)
-{
-  mDelay = aDelay;
-  return NS_OK;
-}
-
-// nsDocNavStartProgressListener::GetCallback
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::GetCallback(
-    nsIDocNavStartProgressCallback** aCallback)
-{
-  NS_ENSURE_ARG_POINTER(aCallback);
-  *aCallback = mCallback;
-  NS_IF_ADDREF(*aCallback);
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::SetCallback
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::SetCallback(
-    nsIDocNavStartProgressCallback* aCallback)
-{
-  mCallback = aCallback;
-
-  // Break any cycles we have from mTimers to us by clearing all pending
-  // requests and timers; the timers we use are not exposed externally, but
-  // since we use ourself as an observer with each timer, we have to
-  // manually break this cycle to ensure prompt destruction of this and
-  // the release of everything this entrains, in the case that we can't wait
-  // for all the timers to expire normally for some reason (e.g. application
-  // shutdown).
-  if (!aCallback)
-    ClearPendingEvents();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::IsSpurious(nsIURI* aURI, PRBool* isSpurious)
-{
-  NS_PRECONDITION(aURI, "Must have a URI!");
-
-  nsCAutoString scheme; 
-  nsresult rv;
-
-  // If there's a nested URI, we want to check the inner URI's scheme.
-  // If we find a spurious scheme then we can break the checking loop at that point.
-  nsCOMPtr<nsIURI> inner = aURI;
-  nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(inner);
-  while (true) {
-    rv = inner->GetScheme(scheme);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    *isSpurious = scheme.Equals("about") ||
-                  scheme.Equals("chrome") ||
-                  scheme.Equals("file") ||
-                  scheme.Equals("javascript");
-    if (*isSpurious || !nestedURI)
-      break;
-
-    rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
-    NS_ENSURE_SUCCESS(rv, rv);
-    nestedURI = do_QueryInterface(inner);
-  }
-
-  return NS_OK;
-}
-
-// nsIWebProgressListener ******************************************************
-
-
-// nsDocNavStartProgressListener::OnStateChange
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::OnStateChange(nsIWebProgress *aWebProgress,
-                                            nsIRequest *aRequest,
-                                            PRUint32 aStateFlags,
-                                            nsresult aStatus)
-{
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::OnProgressChange
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::OnProgressChange(nsIWebProgress *aWebProgress,
-                                               nsIRequest *aRequest,
-                                               PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
-                                               PRInt32 aCurTotalProgress,
-                                               PRInt32 aMaxTotalProgress)
-{
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::OnLocationChange
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::OnLocationChange(nsIWebProgress *aWebProgress,
-                                               nsIRequest *aRequest,
-                                               nsIURI *aLocation)
-{
-  nsresult rv;
-  nsCAutoString uriString;
-  nsCOMPtr<nsIURI> uri;
-
-  // ignore requests with no URI
-  rv = GetRequestUri(aRequest, getter_AddRefs(uri));
-  if (NS_FAILED(rv))
-    return NS_OK;
-  rv = uri->GetAsciiSpec(uriString);
-  if (NS_FAILED(rv))
-    return NS_OK;
-
-  LOG(("Firing OnLocationChange for %s", uriString.get()));
-
-  // We store the request and a timer in queue.  When the timer fires,
-  // we use the request in the front of the queue.
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  NS_ENSURE_TRUE(timer, rv);
-
-  rv = timer->Init(this, mDelay, nsITimer::TYPE_ONE_SHOT);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mRequests.AppendObject(aRequest);
-  mTimers.AppendObject(timer);
-
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::OnStatusChange
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::OnStatusChange(nsIWebProgress *aWebProgress,
-                                             nsIRequest *aRequest,
-                                             nsresult aStatus,
-                                             const PRUnichar *aMessage)
-{
-  return NS_OK;
-}
-
-
-// nsDocNavStartProgressListener::OnSecurityChange
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::OnSecurityChange(nsIWebProgress *aWebProgress,
-                                               nsIRequest *aRequest,
-                                               PRUint32 aState)
-{
-  return NS_OK;
-}
-
-// nsIObserver ****************************************************************
-
-NS_IMETHODIMP
-nsDocNavStartProgressListener::Observe(nsISupports *subject, const char *topic,
-                                       const PRUnichar *data)
-{
-  if (strcmp(topic, NS_TIMER_CALLBACK_TOPIC) == 0) {
-    // Timer callback, pop the front of the request queue and call the callback.
-#ifdef DEBUG
-    PRUint32 length = mRequests.Count();
-    NS_ASSERTION(length > 0, "timer callback with empty request queue?");
-    length = mTimers.Count();
-    NS_ASSERTION(length > 0, "timer callback with empty timer queue?");
-#endif
-
-    nsIRequest* request = mRequests[0];
-
-    if (mCallback) {
-      PRBool isSpurious;
-
-      nsCOMPtr<nsIURI> uri;
-      nsresult rv = GetRequestUri(request, getter_AddRefs(uri));
-      NS_ENSURE_SUCCESS(rv, rv);
-      
-      rv = IsSpurious(uri, &isSpurious);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      if (!isSpurious) {
-        nsCString uriString;
-        rv = uri->GetAsciiSpec(uriString);
-        NS_ENSURE_SUCCESS(rv, rv);
-        
-        // We don't care about URL fragments so we take that off.
-        PRInt32 pos = uriString.FindChar('#');
-        if (pos > -1) {
-          uriString.SetLength(pos);
-        }
-        
-        LOG(("Firing DocNavStart for %s", uriString.get()));
-        mCallback->OnDocNavStart(request, uriString);
-      }
-    }
-
-    mRequests.RemoveObjectAt(0);
-    mTimers.RemoveObjectAt(0);
-  }
-  return NS_OK;
-}
deleted file mode 100644
--- a/browser/components/safebrowsing/src/nsDocNavStartProgressListener.h
+++ /dev/null
@@ -1,81 +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 Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brett Wilson <brettw@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsIDocNavStartProgressListener.h"
-#include "nsIObserver.h"
-#include "nsIWebProgressListener.h"
-#include "nsCOMArray.h"
-#include "nsCOMPtr.h"
-#include "nsWeakReference.h"
-
-// Forward declare template types.
-class nsITimer;
-class nsIRequest;
-class nsIURI;
-
-class nsDocNavStartProgressListener : public nsIDocNavStartProgressListener,
-                                      public nsIWebProgressListener,
-                                      public nsIObserver,
-                                      public nsSupportsWeakReference
-{
-public:
-  nsDocNavStartProgressListener();
-  virtual ~nsDocNavStartProgressListener();
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOCNAVSTARTPROGRESSLISTENER
-  NS_DECL_NSIWEBPROGRESSLISTENER
-  NS_DECL_NSIOBSERVER
-
-protected:
-
-  PRBool mEnabled;
-  PRUint32 mDelay;
-  nsCOMPtr<nsIDocNavStartProgressCallback> mCallback;
-
-  // queue of pending requests; should we use nsDeque instead?
-  nsCOMArray<nsIRequest> mRequests;
-  nsCOMArray<nsITimer> mTimers;
-
-  nsresult AttachListeners();
-  nsresult DetachListeners();
-
-  // clears mRequests, cancels each timer in mTimer and then clears mTimers
-  void ClearPendingEvents();
-
-  // Pull the URI out of the request.
-  nsresult GetRequestUri(nsIRequest* aReq, nsIURI** uri);
-};
--- a/browser/components/safebrowsing/src/nsSafebrowsingApplication.js
+++ b/browser/components/safebrowsing/src/nsSafebrowsingApplication.js
@@ -6,25 +6,20 @@ const Ci = Components.interfaces;
 Function.prototype.inherits = function(parentCtor) {
   var tempCtor = function(){};
   tempCtor.prototype = parentCtor.prototype;
   this.superClass_ = parentCtor.prototype;
   this.prototype = new tempCtor();
 }  
 
 #include ../content/application.js
-#include ../content/browser-view.js
-#include ../content/controller.js
-#include ../content/firefox-commands.js
 #include ../content/globalstore.js
 #include ../content/list-warden.js
-#include ../content/phishing-afterload-displayer.js
 #include ../content/phishing-warden.js
 #include ../content/malware-warden.js
-#include ../content/reporter.js
 
 var modScope = this;
 function Init() {
   var jslib = Cc["@mozilla.org/url-classifier/jslib;1"]
               .getService().wrappedJSObject;
   modScope.G_Debug = jslib.G_Debug;
   modScope.G_Assert = jslib.G_Assert;
   modScope.G_Alarm = jslib.G_Alarm;
deleted file mode 100644
--- a/browser/components/safebrowsing/tests/Makefile.in
+++ /dev/null
@@ -1,47 +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 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 the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-
-DEPTH     = ../../../..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/browser/components/safebrowsing/tests/jar.mn
+++ /dev/null
@@ -1,2 +0,0 @@
-browser.jar:
-+ content/browser/protection/unittests.xul         (unittests.xul)
deleted file mode 100644
--- a/browser/components/safebrowsing/tests/unittests.xul
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0"?>
-<window id="PROT_unittest"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 
-        onload="onProtUnittestLoad();"
-        title="prot unittests">
-
-<script><![CDATA[
-  const Cc = Components.classes;
-  const Ci = Components.interfaces;
-
-  function G_Debug(zone, s) {
-    var label = document.createElement('label');
-    var txt = "[" + zone + "] " + s;
-    label.appendChild(document.createTextNode(txt));
-
-    document.documentElement.appendChild(label);
-  }
-  
-  function G_Assert(zone, cond, msg) {
-    if (!cond) {
-      G_Debug(zone, msg);
-      throw msg;
-    }
-  }
-  
-  function ProtectionPhishWardenTests() {
-    var z = "phishwarden UNITTEST";
-    G_Debug(z, "Starting");
-
-    var listManager = Cc["@mozilla.org/protection/protectionlistmanager;1"]
-                        .getService(Ci.nsIProtectionListManager);
-    var warden = Cc['@mozilla.org/protection/phishwarden;1']
-                   .createInstance(Ci.nsIProtectionListWarden);
-    // Register tables that we are interested in.
-    warden.registerBlackTable("test-black-url");
-
-    var blacklistedCount = 0;
-
-    var blackURLs = [
-        "http://foo.com/1",
-        "http://foo.com/2",
-        "http://foo.com/3",
-        "http://foo.com/4",
-        "http://www.goodsite.com/test",
-        ];
-
-    for (var i = 0; i < blackURLs.length; i++)
-      listManager.safeInsert("test-black-url", blackURLs[i], "1");
-
-    G_Assert(z, !warden.checkUrl("http://bar.com/"), 'should not have found');
-    G_Assert(z, warden.checkUrl("http://foo.com/1"), 'should have found (1)');
-    G_Assert(z, warden.checkUrl("http://foo.com/2"), 'should have found (2)');
-    G_Assert(z, warden.checkUrl("http://foo.com/3"), 'should have found (3)');
-    G_Assert(z, warden.checkUrl("http://foo.com/4"), 'should have found (4)');
-    
-    warden.registerWhiteTable('test-white-domain');
-    listManager.safeInsert("test-white-domain", "http://www.goodsite.com/", "1");
-    
-    G_Assert(z, !warden.checkUrl("http://www.goodsite.com/"),
-             'whitelist failed?')
-
-    
-    G_Debug(z, "PASSED");
-  }
-
-  function onProtUnittestLoad() {
-    ProtectionPhishWardenTests();
-  }
-]]></script>
-</window>
--- a/browser/components/search/nsSearchService.js
+++ b/browser/components/search/nsSearchService.js
@@ -1391,17 +1391,17 @@ Engine.prototype = {
                                                     aTemplate) {
     ENSURE_WARN(!this._readOnly,
                 "Can't call _initFromMetaData on a readonly engine!",
                 Cr.NS_ERROR_FAILURE);
 
     this._urls.push(new EngineURL("text/html", aMethod, aTemplate));
 
     this._name = aName;
-    this._alias = aAlias;
+    this.alias = aAlias;
     this._description = aDescription;
     this._setIcon(aIconURL, true);
 
     this._serializeToFile();
   },
 
   /**
    * Extracts data from an OpenSearch URL element and creates an EngineURL
@@ -1521,19 +1521,16 @@ Engine.prototype = {
         case "Image":
           this._parseImage(child);
           break;
         case "InputEncoding":
           this._queryCharset = child.textContent.toUpperCase();
           break;
 
         // Non-OpenSearch elements
-        case "Alias":
-          this._alias = child.textContent;
-          break;
         case "SearchForm":
           this._searchForm = child.textContent;
           break;
         case "UpdateUrl":
           this._updateURL = child.textContent;
           break;
         case "UpdateInterval":
           this._updateInterval = parseInt(child.textContent);
@@ -1900,17 +1897,16 @@ Engine.prototype = {
       var imageNode = appendTextNode(OPENSEARCH_NS_11, "Image",
                                      this._iconURI.spec);
       if (imageNode) {
         imageNode.setAttribute("width", "16");
         imageNode.setAttribute("height", "16");
       }
     }
 
-    appendTextNode(MOZSEARCH_NS_10, "Alias", this.alias);
     appendTextNode(MOZSEARCH_NS_10, "UpdateInterval", this._updateInterval);
     appendTextNode(MOZSEARCH_NS_10, "UpdateUrl", this._updateURL);
     appendTextNode(MOZSEARCH_NS_10, "IconUpdateUrl", this._iconUpdateURL);
     appendTextNode(MOZSEARCH_NS_10, "SearchForm", this._searchForm);
 
     for (var i = 0; i < this._urls.length; ++i)
       this._urls[i]._serializeToElement(doc, docElem);
     docElem.appendChild(doc.createTextNode("\n"));
--- a/browser/components/search/test/Makefile.in
+++ b/browser/components/search/test/Makefile.in
@@ -40,12 +40,14 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  =  browser/components/search/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = 	  browser_405664.js \
+	                  browser_415700.js \
+	                  testEngine.xml \
 	                  $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/browser_415700.js
@@ -0,0 +1,90 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Ryan Flint <rflint@dslr.net> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+var gSS = Cc["@mozilla.org/browser/search-service;1"].
+           getService(Ci.nsIBrowserSearchService);
+var gObs = Cc["@mozilla.org/observer-service;1"].
+           getService(Ci.nsIObserverService);
+
+var observers = {
+  observe: function(aSubject, aTopic, aData) {
+    switch (aData) {
+      case "engine-added":
+        test2();
+        break;
+      case "engine-current":
+        test3();
+        break;
+      case "engine-removed":
+        test4();
+        break;
+    }
+  }
+};
+
+function test() {
+  waitForExplicitFinish();
+  gObs.addObserver(observers, "browser-search-engine-modified", false);
+
+  gSS.addEngine("http://localhost:8888/browser/browser/components/search/test/testEngine.xml",
+                Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
+                false);
+}
+
+function test2() {
+  var engine = gSS.getEngineByName("Foo");
+  ok(engine, "Engine was added.");
+
+  var aEngine = gSS.getEngineByAlias("fooalias");
+  ok(!aEngine, "Alias was not parsed from engine description");
+
+  gSS.currentEngine = engine;
+}
+
+function test3() {
+  var engine = gSS.currentEngine;
+  is(engine.name, "Foo", "Current engine was changed successfully");
+
+  gSS.removeEngine(engine);
+}
+
+function test4() {
+  var engine = gSS.currentEngine;
+  ok(engine, "An engine is present.");
+  isnot(engine.name, "Foo", "Current engine reset after removal");
+
+  gObs.removeObserver(observers, "browser-search-engine-modified");
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/testEngine.xml
@@ -0,0 +1,12 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+  <ShortName>Foo</ShortName>
+  <Description>Foo Search</Description>
+  <InputEncoding>utf-8</InputEncoding>
+  <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
+  <Url type="text/html" method="GET" template="http://localhost:8888/browser/browser/components/search/test/?search">
+    <Param name="test" value="{searchTerms}"/>
+  </Url>
+  <moz:SearchForm>http://localhost:8888/browser/browser/components/search/test/</moz:SearchForm>
+  <moz:Alias>fooalias</moz:Alias>
+</OpenSearchDescription>
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -501,16 +501,23 @@ SessionStoreService.prototype = {
     
     for (var i = 0; i < tabpanels.childNodes.length; i++) {
       this.onTabRemove(aWindow, tabpanels.childNodes[i], true);
     }
     
     // cache the window state until the window is completely gone
     aWindow.__SS_dyingCache = this._windows[aWindow.__SSi] || this._lastWindowClosed;
     
+    // reset the _tab property to avoid keeping the tab's XUL element alive
+    // longer than we need it
+    var tabCount = aWindow.__SS_dyingCache.tabs.length;
+    for (var t = 0; t < tabCount; t++) {
+      delete aWindow.__SS_dyingCache.tabs[t]._tab;
+    }
+    
     delete aWindow.__SSi;
   },
 
   /**
    * set up listeners for a new tab
    * @param aWindow
    *        Window reference
    * @param aPanel
@@ -570,16 +577,20 @@ SessionStoreService.prototype = {
     // don't update our internal state if we don't have to
     if (maxTabsUndo == 0) {
       return;
     }
     
     // make sure that the tab related data is up-to-date
     var tabState = this._collectTabData(aTab);
     this._updateTextAndScrollDataForTab(aWindow, aTab.linkedBrowser, tabState);
+
+    // reset the _tab property to avoid keeping the tab's XUL element alive
+    // longer than we need it
+    delete tabState._tab;
     
     // store closed-tab data for undo
     if (tabState.entries.length > 1 || tabState.entries[0].url != "about:blank") {
       this._windows[aWindow.__SSi]._closedTabs.unshift({
         state: tabState,
         title: aTab.getAttribute("label"),
         image: aTab.getAttribute("image"),
         pos: aTab._tPos
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -42,10 +42,10 @@ MOZ_PHOENIX=1
 
 MOZ_ENABLE_LIBXUL=1
 MOZ_PLACES=1
 # always enabled for form history
 MOZ_MORKREADER=1
 MOZ_SAFE_BROWSING=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_NO_XPCOM_OBSOLETE=1
-MOZ_EXTENSIONS_DEFAULT=" inspector gnomevfs reporter"
+MOZ_EXTENSIONS_DEFAULT=" gnomevfs reporter"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -82,16 +82,24 @@ components/libqfaservices.so
 components/talkback/master.ini
 components/talkback/talkback
 components/talkback/talkback.so
 components/talkback/XTalkback.ad
 extensions/reporter@mozilla.org/install.rdf
 extensions/reporter@mozilla.org/chrome.manifest
 extensions/reporter@mozilla.org/chrome/reporter.jar
 extensions/reporter@mozilla.org/defaults/preferences/reporter.js
+#Remove Inspector (present from upgrades from Fx2/Fx3b1)
+components/inspector.xpt
+extensions/inspector@mozilla.org/install.rdf
+extensions/inspector@mozilla.org/components/inspector-cmdline.js
+extensions/inspector@mozilla.org/chrome.manifest
+extensions/inspector@mozilla.org/chrome/inspector.jar
+extensions/inspector@mozilla.org/defaults/preferences/inspector.js
+extensions/inspector@mozilla.org/platform/WINNT/chrome/icons/default/winInspectorMain.ico
 extensions/inspector@mozilla.org/components/inspector.xpt
 extensions/inspector@mozilla.org/components/@DLL_PREFIX@inspector@DLL_SUFFIX@
 extensions/inspector@mozilla.org/chrome/icons/default/winInspectorMain.ico
 uninstall/UninstallFirefox.exe
 uninstall/UninstallDeerPark.exe
 uninstall/uninst.exe
 uninstall/uninstall.exe
 components/myspell/en-US.dic
@@ -570,19 +578,31 @@ components/progressDlg.xpt
 components/search.xpt
 components/websrvcs.xpt
 components/widget_mac.xpt
 components/xml-rpc.xpt
 components/xpcom_obsolete.xpt
 init.d/README
 redo-prebinding.sh
 res/viewer.properties
+res/bloatcycle.html
 #endif
 #ifdef XP_UNIX
+#ifndef XP_MACOSX
 readme.txt
+chrome/icons/default/default.xpm
+#endif
 #endif
 dictionaries/PL.dic
 dictionaries/PL.aff
+#ifdef MOZ_MEMORY
+#ifdef XP_WIN
+Microsoft.VC80.CRT.manifest
+msvcm80.dll
+msvcp80.dll
+msvcr80.dll
+#endif
+#endif
 #ifdef XP_WIN
 xpicleanup.exe
 #else
 xpicleanup
 #endif
--- a/browser/installer/windows/packages-static
+++ b/browser/installer/windows/packages-static
@@ -344,16 +344,8 @@ bin\chrome\pippki.manifest
 ;
 bin\updater.exe
 
 ; [Crash Reporter]
 bin\crashreporter.exe
 bin\crashreporter.ini
 bin\crashreporter-override.ini
 
-; [Additional Developer Tools]
-[adt]
-bin\extensions\inspector@mozilla.org\install.rdf
-bin\extensions\inspector@mozilla.org\components\inspector-cmdline.js
-bin\extensions\inspector@mozilla.org\chrome.manifest
-bin\extensions\inspector@mozilla.org\chrome\inspector.jar
-bin\extensions\inspector@mozilla.org\defaults\preferences\inspector.js
-bin\extensions\inspector@mozilla.org\platform\WINNT\chrome\icons\default\winInspectorMain.ico
index 2434023cee756ee0c817db38b2e59c3f09b98ca7..5ee25e9b9fd4150e35e12790556c5ccc413a7f2c
GIT binary patch
literal 865
zc$@)Y1D^beP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10^UhPK~y-6g_2EdRAm%~pYP7S^CPw)Loc*trfMs+0xMRmFfNS5
zCMHI~!~{1Q2reY3wMhde##AE+0T#p<6WRDf;$LFoM(n~E609~M*g%<fidMYLSUNLz
zZfEA+@B8lOrVJ&J_%6>mdCtjuUSW)3wLUoZ-X_;|_bx9lZ;#`63t)s0e?(FAv)1~X
z(UGzF)$?LC;N<D!2YY*SM|MBAXPxi+L^31{L(1h6|1Orz%*@O!Ddor;hu%7S58&vB
z?+^EM_k6x<*VCPj?dVIFF9p-nmm^~!lTMp1x2w~2-SpJdR5b{K;n9(?3jp?QQZktw
z-@0vE=T8&otDg7I$59lW0saO|5Y#tTs+Iko=N-uR<+HPe*>T{By8y<R?l{(z%cbU_
zgKv&<w-$iICr%#Qo5`fJz~Jr1DnQKQ;tgWm6eo^sS<C&DeNkxD1n&4Ij4^!l?!apU
z-QKA$e`wKYfe^6!Nr9UMFnszQG+L%z?|3l9H7_^%>f42*!WhHECn=R5dOo2#o+W5l
zARyOc;bsl73Az4P#Nw?Otz$N1HC8ae!pzrk(w2@5kaD8L+TN#_{N){fywF65n5}~r
zFFYeqs>;H2jjz53C1KM;4llhtjx&4C`h9+LN81A}19BTAS}TNzng3IQNrRC*l9y-=
zTEq1PiIz10luig?jN$O>JJj%=<B4ju%0U04B$G*$lGt_vsT8eNlTxX~Qe}zCQkB7>
zA<ln07GLu=uCW0MUf#^j6=^mbq*Iv{fI@4D(wZ=AQLFjX{2G3(MsaSA!p)okbLWlg
z*Slz~>F@6+l}e$ML@C+6pi-%@R9V9VnG9X7+kRskP%IX)ZTo*OsQW%a5VYfC16Y<-
zXfzs+?cDh|efd5d$3bg_)(WLGVH8rY*YSNH-}kw4^$M0{-TdOSbD<5Owca=R+vM4c
rzg~P;2yx#KuEd>{g*W0jeg)t^ap{j$O5+>+00000NkvXXu0mjf9g>-r
index 5efc13676caa5331993c84b7e757f0e2ea1d7a8c..1ec110be4be728526476fec1ad4d5f1f3d1c8eeb
GIT binary patch
literal 928
zc$@*C17G}!P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H1106|3K~y-6ZINGSTXhu2KR3yev^7go=GLS));XqI7>KA<L&d(h
zBFr(6?qvvWg81mfS}BZz;QTWwmNJI=CJbzSlFe0Nb2<>$u2N~b(p5~`*tBVz=6{#w
z-ut`9hb%)@zi=MTIq>0pzef`h>iYED*@L<sd81IsKdF@3e{Vc%n8t6GX?@q*)Att-
zNUH+|hX#7XVf};d*Nz9u<r0QvV44OS8yl==)?_+9ovBu<{qMfhb733cv(G<%Mb{(W
zzIx>7PSdbd{Pt97dV0zf5xicnw1irGZEcS<-28nkm(6C6_4f4Lr~_O8Ua$9)_V)Ij
zKmIhDTUz>O&@hZIdwcrQ_iVKki^Y@abo#yMp@Yr0#wR`kUc7&Th%h)bke*NeEkozO
zSQZifTNBVZ0l$uUJoZFWll=T>TXh0D>w8xXVw2CNv8{@B_Wc7vug4((9p~oGxP1@3
z-TYE#qgU4vU@Mt)=QgrG{Gn-sPmA<v7e0LK^yA@`fs2>7C|7D%9Y3rQS{E9>YNYMN
zDYW@{0+%iUkm>3|A`w!<!<(vHKB8Uw+HD<Zf6G~MA10eOK@_bajneD=`2Blna=B1*
za|C8)0LVw9NNX!)+h+ax^&2kF4#Vl&(@Ao2kdf~bh!{lo+dTW{DxvP@u;cLuUymb`
z!MkrCz*7zYTUBU_xKYYRDaCxUS_`;R0o&dN5D}=<{JJhr#?-DCo^g7bIyl`Yn5Kbc
zSr|7@QeIrd7YHDg3i)XCKEQ5hU^A5hm~<po!;(lOSXfwKd3l+Yl@-$IG`a3>)^1O;
z<#1pJgZRhC@sEvRG&E4rG;%XDcSWS%1rQE}@%#OFJRU5|#Ih_*y_LIn?vNTD!MA%i
zrH&57wy72h6xLS3w$HbV{Ne&gBoYLJ&A8n=uq+d$RL#b*qnIsw2n>(VI6I4ouo=-A
zjXiHKKD_J92;g!!9J7UD{!lCy!|irsSym08EDWPcN!KZKz06vnNTFCDnOtOPDxMm-
zI9vsADW%@LdhO~rS4OWqu`TZZk<;l+D5Xx-`+osp8K*L$Lx_6-0000<MNUMnLSTY#
CB(eGc
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -182,20 +182,22 @@ menuitem.bookmark-item {
   list-style-image: url("chrome://global/skin/icons/folder-item.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px)
 }
 
 .bookmark-item[container] {
   list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
 }
 
-/* livemarks have the same layout as folder-item, but in the browser-only livemark-item.png */
-/* only the folder icon has any effect for now, item icon is unused */
 .bookmark-item[container][livemark] { 
-  list-style-image: url("chrome://browser/skin/page-livemarks.png");
+  list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
+}
+
+.bookmark-item[container][livemark] .bookmark-item {
+  list-style-image: url("chrome://browser/skin/places/livemark-item.png");
 }
 
 .bookmark-item[container][tagContainer] {
   list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
   -moz-image-region: auto;
 }
 
 .bookmark-item[container][query] {
@@ -204,47 +206,51 @@ menuitem.bookmark-item {
 }
 
 /* Stock icons for the menu bar items */
 menuitem:not([type]) {
   -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
 }
 
 menuitem[command="cmd_newNavigator"],
-#context-openlink {
+#context-openlink,
+#context-openframe {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 80px 16px 64px);
 }
 
 menuitem[command="cmd_newNavigatorTab"],
-#context-openlinkintab {
+#context-openlinkintab,
+#context-openframeintab {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 64px 16px 48px);
 }
 
 menuitem[command="Browser:OpenFile"] {
   list-style-image: url("moz-icon://stock/gtk-open?size=menu");
 }
 
 #menu_close {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
 
 menuitem[command="Browser:SavePage"],
 #context-savelink,
 #context-saveimage,
-#context-savepage {
+#context-savepage,
+#context-saveframe {
   list-style-image: url("moz-icon://stock/gtk-save-as?size=menu");
 }
 
 menuitem[command="cmd_printPreview"] {
   list-style-image: url("moz-icon://stock/gtk-print-preview?size=menu");
 }
 
-menuitem[command="cmd_print"] {
+menuitem[command="cmd_print"],
+#context-printframe {
   list-style-image: url("moz-icon://stock/gtk-print?size=menu");
 }
 
 #menu_FileQuitItem {
   list-style-image: url("moz-icon://stock/gtk-quit?size=menu");
 }
 
 menuitem[command="cmd_undo"],
@@ -273,17 +279,18 @@ menuitem[command="cmd_cut"],
 menuitem[command="cmd_cut"][disabled],
 #context-cut[disabled] {
   list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
 }
 
 menuitem[command="cmd_copy"],
 #context-copy,
 #context-copyimage,
-#context-copylink {
+#context-copylink,
+#context-copyemail {
   list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
 }
 
 menuitem[command="cmd_copy"][disabled],
 #context-copy[disabled] {
   list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
 }
 
@@ -319,28 +326,28 @@ menuitem[command="cmd_selectAll"] {
   list-style-image: url("moz-icon://stock/gtk-find?size=menu&state=disabled");
 }
 
 #menu_preferences {
   list-style-image: url("moz-icon://stock/gtk-preferences?size=menu");
 }
 
 menuitem[command="Browser:Stop"],
-#context-stop,
-#javascriptConsole {
+#context-stop {
   list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
 }
 
 menuitem[command="Browser:Stop"][disabled],
 #context-stop[disabled] {
   list-style-image: url("moz-icon://stock/gtk-stop?size=menu&state=disabled");
 }
 
 menuitem[command="Browser:Reload"],
-#context-reload {
+#context-reload,
+#context-reloadframe {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
 }
 
 menuitem[command="Browser:Reload"][disabled],
 #context-reload[disabled] {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
 }
 
@@ -411,17 +418,18 @@ menuitem[command="Browser:ShowAllBookmar
 }
 
 #menu_openDownloads {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 menuitem[command="View:PageInfo"],
-#context-viewinfo {
+#context-viewinfo,
+#context-viewframeinfo {
   list-style-image: url("moz-icon://stock/gtk-info?size=menu");
 }
 
 #context-metadata {
   list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
 }
 
 #sanitizeItem {
@@ -431,16 +439,20 @@ menuitem[command="View:PageInfo"],
 menuitem[key="key_openHelp"] {
   list-style-image: url("moz-icon://stock/gtk-help?size=menu");
 }
 
 #aboutName {
   list-style-image: url("moz-icon://stock/gtk-about?size=menu");
 }
 
+#javascriptConsole {
+  list-style-image: url("chrome://global/skin/console/console.png");
+}
+
 /* Primary toolbar buttons */
 .toolbarbutton-1 {
   -moz-box-orient: vertical;
   min-width: 0;
   list-style-image: url("chrome://browser/skin/Toolbar.png");
 }
 
 .toolbarbutton-1 .toolbarbutton-icon {
@@ -595,37 +607,49 @@ toolbar[iconsize="small"] .toolbarbutton
 
 toolbar[iconsize="small"] .toolbarbutton-1[type="menu-button"] {
   border: 0 !important;
 }
 
 toolbar[iconsize="small"] #back-button {
   list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu");
 }
+.unified-nav-back[_moz-menuactive] {
+  list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu") !important;
+}
 toolbar[iconsize="small"] #back-button[disabled="true"] {
   list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled");
 }
 
 toolbar[iconsize="small"] #back-button[chromedir="rtl"] {
   list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu");
 }
+menupopup[chromedir="rtl"] > .unified-nav-back[_moz-menuactive] {
+  list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu") !important;
+}
 toolbar[iconsize="small"] #back-button[disabled="true"][chromedir="rtl"] {
   list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled");
 }
 
 toolbar[iconsize="small"] #forward-button {
   list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu");
 }
+.unified-nav-forward[_moz-menuactive] {
+  list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
+}
 toolbar[iconsize="small"] #forward-button[disabled="true"] {
   list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
 }
 
 toolbar[iconsize="small"] #forward-button[chromedir="rtl"] {
   list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu");
 }
+menupopup[chromedir="rtl"] > .unified-nav-forward[_moz-menuactive] {
+  list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
+}
 toolbar[iconsize="small"] #forward-button[disabled="true"][chromedir="rtl"] {
   list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
 }
 
 toolbar[iconsize="small"] #stop-button {
   list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
 }
 toolbar[iconsize="small"] #stop-button[disabled="true"] {
@@ -791,43 +815,44 @@ toolbar[iconsize="small"] #paste-button[
   direction: rtl;
 }
 
 #PopupAutoComplete .autocomplete-treebody {
   direction: ltr;
 }
 
 /* Favicon */
-#page-proxy-deck,
+#page-proxy-stack,
 #page-proxy-favicon,
-#page-proxy-button {
+#urlbar-throbber {
   width: 16px;
   height: 16px;
 }
 
-#page-proxy-deck {
+#page-proxy-stack {
   margin: 2px 3px;
 }
 
-#page-proxy-favicon {
-  list-style-image: none;
+#page-proxy-favicon:not([src]) {
+  list-style-image: url("chrome://global/skin/icons/folder-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
-#page-proxy-button {
-  list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
-  -moz-image-region: rect(0px, 16px, 16px, 0px);}
+#page-proxy-favicon[pageproxystate="invalid"] {
+  -moz-image-region: rect(16px, 16px, 32px, 0px);
+}
 
-#page-proxy-button[pageproxystate="invalid"] {
-  cursor: default;
-  -moz-image-region: rect(32px, 16px, 48px, 0px) !important;
+#urlbar-throbber {
+  list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
 }
 
 /* Identity indicator */
 #identity-box {
   background-color: -moz-dialog;
+  color: -moz-dialogtext;
   -moz-border-end: 1px solid ThreeDShadow;
 }
 
 #identity-box:focus {
   outline: 1px dotted -moz-DialogText;
 }
 
 #identity-icon-label {
@@ -1181,16 +1206,45 @@ tabpanels {
   list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif") !important;
   opacity: 0.6;
 }
 
 .tabs-bottom {
   border-bottom: 1px solid threedshadow;
 }
 
+#context_newTab {
+  list-style-image: url("chrome://browser/skin/Toolbar-small.png");
+  -moz-image-region: rect(0px 64px 16px 48px);
+}
+
+#context_newTab[disabled] {
+  -moz-image-region: rect(16px 64px 32px 48px);
+}
+
+#context_reloadTab {
+  list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
+}
+
+#context_closeOtherTabs {
+  list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
+}
+
+#context_closeOtherTabs[disabled] {
+  list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
+}
+
+#context_undoCloseTab {
+  list-style-image: url("moz-icon://stock/gtk-undelete?size=menu");
+}
+
+#context_closeTab {
+  list-style-image: url("moz-icon://stock/gtk-close?size=menu");
+}
+
 /* tabbrowser-tab focus ring */
 .tabbrowser-tab > .tab-text {
   border: 1px dotted transparent;
 }
 
 .tabbrowser-tab[selected="true"]:focus > .tab-text {
   border: 1px dotted -moz-DialogText;
 }
@@ -1267,16 +1321,20 @@ tabpanels {
   font-weight: bold;
 }
 
 .alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
   list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
   opacity: 0.6;
 }
 
+.tabs-alltabs-button > .toolbarbutton-icon {
+   margin: 0px;
+}
+
 /* Sidebar */
 #sidebar-box .tabs-closebutton {
   margin-bottom: 0px !important;
   padding: 0px 2px 0px 2px !important;
 }
 
 #sidebar-throbber[loading="true"] {
   list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
index 3fb78ad31ec359756334e9644ba1478c53bbae23..eef07e04da40f23c82454932eb1cf4e81661c143
GIT binary patch
literal 10366
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
--- a/browser/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -28,20 +28,17 @@ classic.jar:
   skin/classic/browser/feeds/videoFeedIcon.png        (feeds/videoFeedIcon.png)
   skin/classic/browser/feeds/videoFeedIcon16.png      (feeds/videoFeedIcon16.png)
   skin/classic/browser/feeds/audioFeedIcon.png        (feeds/audioFeedIcon.png)
   skin/classic/browser/feeds/audioFeedIcon16.png      (feeds/audioFeedIcon16.png)
   skin/classic/browser/feeds/subscribe.css            (feeds/subscribe.css)
 * skin/classic/browser/places/bookmarkProperties.css  (places/bookmarkProperties.css)
   skin/classic/browser/places/bookmarksMenu.png       (places/bookmarksMenu.png)
 * skin/classic/browser/places/editBookmarkOverlay.css (places/editBookmarkOverlay.css)
-  skin/classic/browser/places/livemark-folder.png     (places/livemark-folder.png)
-  skin/classic/browser/places/livemark-folder-rtl.png (places/livemark-folder-rtl.png)
   skin/classic/browser/places/livemark-item.png       (places/livemark-item.png)
-  skin/classic/browser/places/livemark-item-rtl.png   (places/livemark-item-rtl.png)
   skin/classic/browser/places/pageStarred.png         (places/pageStarred.png)
   skin/classic/browser/places/starred48.png           (places/starred48.png)
   skin/classic/browser/places/unstarred48.png         (places/unstarred48.png)
   skin/classic/browser/places/places.css              (places/places.css)
   skin/classic/browser/places/organizer.css           (places/organizer.css)
 * skin/classic/browser/places/organizer.xml           (places/organizer.xml)
   skin/classic/browser/places/query.png               (places/query.png)
   skin/classic/browser/places/starPage.png            (places/starPage.png)
@@ -49,21 +46,13 @@ classic.jar:
   skin/classic/browser/places/toolbarDropMarker.png   (places/toolbarDropMarker.png)
   skin/classic/browser/places/wrench.png              (places/wrench.png)
   skin/classic/browser/preferences/alwaysAsk.png      (preferences/alwaysAsk.png)
   skin/classic/browser/preferences/application.png    (preferences/application.png)
   skin/classic/browser/preferences/Options.png        (preferences/Options.png)
   skin/classic/browser/preferences/plugin.png         (preferences/plugin.png)
 * skin/classic/browser/preferences/preferences.css    (preferences/preferences.css)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
-#ifdef MOZ_SAFE_BROWSING
-  skin/classic/browser/safebrowsing/browser-protection.css (safebrowsing/browser-protection.css)
-  skin/classic/browser/safebrowsing/close16x16.png         (safebrowsing/close16x16.png)
-  skin/classic/browser/safebrowsing/dim.png                (safebrowsing/dim.png)
-  skin/classic/browser/safebrowsing/tail.png               (safebrowsing/tail.png)
-  skin/classic/browser/safebrowsing/warning16x16.png       (safebrowsing/warning16x16.png)
-  skin/classic/browser/safebrowsing/warning24x24.png       (safebrowsing/warning24x24.png)
-#endif
   skin/classic/browser/tabbrowser/tab-arrow-end.png    (tabbrowser/tab-arrow-end.png)
   skin/classic/browser/tabbrowser/tab-arrow-start.png  (tabbrowser/tab-arrow-start.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
   icon.png
   preview.png
--- a/browser/themes/gnomestripe/browser/pageInfo.css
+++ b/browser/themes/gnomestripe/browser/pageInfo.css
@@ -57,52 +57,32 @@
   margin: 8px 8px 0 8px;
   padding: 0;
 }
 
 #generalTab {
   -moz-image-region: rect(0px, 32px, 32px, 0px)
 }
 
-#generalTab:hover, #generalTab[selected="true"] {
-  -moz-image-region: rect(32px, 32px, 64px, 0px)
-}
-
 #mediaTab {
   -moz-image-region: rect(0px, 64px, 32px, 32px)
 }
 
-#mediaTab:hover, #mediaTab[selected="true"] {
-  -moz-image-region: rect(32px, 64px, 64px, 32px)
-}
-
 #feedTab {
   -moz-image-region: rect(0px, 96px, 32px, 64px)
 }
 
-#feedTab:hover, #feedTab[selected="true"] {
-  -moz-image-region: rect(32px, 96px, 64px, 64px)
-}
-
 #permTab {
   -moz-image-region: rect(0px, 128px, 32px, 96px)
 }
 
-#permTab:hover, #permTab[selected="true"] {
-  -moz-image-region: rect(32px, 128px, 64px, 96px)
-}
-
 #securityTab {
   -moz-image-region: rect(0px, 160px, 32px, 128px)
 }
 
-#securityTab:hover, #securityTab[selected="true"] {
-  -moz-image-region: rect(32px, 160px, 64px, 128px)
-}
-
 deck {
   padding: 10px 10px 10px 10px;
 }
 
 /* Misc */
 tree {
   margin: .5em;
 }
index a7d40b4ac051c9469c2b6fc7b462de7cd2b5cc72..c77b368c73d003f0675b896b26fc44aa1991ffc0
GIT binary patch
literal 8874
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
deleted file mode 100644
index d7e710e60c96905c2d803f7293ec43bdab7a0154..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 0fcd4a5bada1366ae74aded7df95e92913e3af3c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
index 007003a33cd5f0cbe6dd0734f78f779b0865f017..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index c1431ded33bdd794f5ade02d022ea077f5ebfc05..1ed34429cca0204a19332ed5d9ef421f98049629
GIT binary patch
literal 732
zc$@*;0wev2P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10$E8!K~y-6jgm`9lu;OlpYNRi%#4m#9HY_v5h`0r*e1##+7w6>
z2wfmDY}I91A-M@E6mMN<5hU5BTDGa&1VydN3Jfc#)K(?dqO^3J@&C_hF)1@y;R_$<
z2G94sFGrknboX{PX|1mXK~T+Kq?B?ZlJPumD4kB9X*<>aXz|fGNAHEMi7#I#-TyQ;
zKI%qZzjBwaT=>~{vAfSXhjR`E5Cp->%ESuZjlJdF=$q_1_LlcKH9Y*1WK|W14z|XX
zQb)UbI(7hAz=DkSs3@<bw785|G=|pRVu=>!QYjGF(zvC-Gu~MMFBec!Qch-|8Jn7-
z(BD90?KU!XJD5q$l1x@H^x`Q&V5#+Mv7v2PGC?|>qWHjdO17WCE3V+@z0=s6`$?!-
z{2HG%tJmV!_|(_0M?}mLfQS&rD+$-_B-q+U>B%9Y37;RAHc@7$NhB)qeV<q~Mi_>4
z^>j!cpeSApxAtPMHWGV$9znsb%fuU+N#8k6ydaL&dZC#E@&WU~JkdS<6g8cL$r0wS
zZYE;qFgv@E?;nYNxQnOrVv|2CC~RQ@Ti1j+JcvouqMmdT=mKI5`>^8=F~%&~U6Mg8
z8bjaSjojJ=2+_^Qaib3~o<Xl_fKSgcCh~6!D(5I7xay5aSq)lg#BT&0MJb&(be^Fg
z3@|N&h(H*IP_zQC<v!M0C`uAJ_AI;4nIJzA5yCJ)L=aI3lKt;W|GpEnR=F8u0mhh#
zsp+X?X-O%|(ah`&z&9Y{0fb@LI&h=EKa<JSEC&#YL_S+<kF=d?cfSB55b$m1Df$io
O0000<MNUMnLSTZGqd=qp
--- a/browser/themes/gnomestripe/browser/places/organizer.css
+++ b/browser/themes/gnomestripe/browser/places/organizer.css
@@ -263,94 +263,20 @@
 
 /**** expanders ****/
 .expander-up,
 .expander-down {
   min-width: 0;
 }
 
 /**** menuitem stock icons ****/
-menuitem:not([type]) {
-  -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
-}
-
-menuitem[command="cmd_cut"] {
-  list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
-}
-
-menuitem[command="cmd_cut"][disabled] {
-  list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
-}
-
-menuitem[command="cmd_copy"] {
-  list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
-}
-
-menuitem[command="cmd_copy"][disabled] {
-  list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
-}
-