Merge from tracemonkey.
authorDavid Anderson <danderson@mozilla.com>
Tue, 21 Sep 2010 17:51:37 -0700
changeset 74594 f2383940c993d2fbb57d8fc54dda5ffd8742ed8e
parent 74593 2a468bed70df16134b80a942c3cc1fb2b30d4855 (current diff)
parent 54574 554610a27b0201f08af1d31e3bafb40079d04460 (diff)
child 74595 ac46097e312cf854d997e3bdc566c7c35583f940
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone2.0b7pre
Merge from tracemonkey.
browser/base/content/credits.xhtml
browser/branding/nightly/content/aboutCredits.png
browser/branding/nightly/content/aboutFooter.png
browser/branding/unofficial/content/aboutCredits.png
browser/branding/unofficial/content/aboutFooter.png
browser/locales/en-US/chrome/browser/credits.dtd
browser/themes/gnomestripe/browser/sync-usedBefore.png
browser/themes/gnomestripe/browser/sync-usedNever.png
browser/themes/gnomestripe/browser/tabbrowser/progress-pulsing.png
browser/themes/gnomestripe/browser/tabbrowser/progress.png
browser/themes/pinstripe/browser/Search-addengines.png
browser/themes/pinstripe/browser/feed-icons.png
browser/themes/pinstripe/browser/sync-16-throbber.png
browser/themes/pinstripe/browser/sync-usedBefore.png
browser/themes/pinstripe/browser/sync-usedNever.png
browser/themes/pinstripe/browser/tabbrowser/progress-pulsing.png
browser/themes/pinstripe/browser/tabbrowser/progress.png
browser/themes/winstripe/browser/Search-addengines.png
browser/themes/winstripe/browser/feeds/feed-icons-16-aero.png
browser/themes/winstripe/browser/feeds/feed-icons-16.png
browser/themes/winstripe/browser/sync-16-throbber.png
browser/themes/winstripe/browser/sync-usedBefore.png
browser/themes/winstripe/browser/sync-usedNever.png
browser/themes/winstripe/browser/tabbrowser/progress-pulsing.png
browser/themes/winstripe/browser/tabbrowser/progress.png
content/base/test/chrome/bug514705.html
content/base/test/chrome/bug514705_helper.xul
content/base/test/chrome/test_bug514705.xul
content/events/test/Makefile.in
dom/interfaces/html/nsIDOMHTMLVoidCallback.idl
dom/interfaces/notification/nsIDesktopNotificationPrompt.idl
dom/ipc/TabTypes.h
dom/src/geolocation/nsGeolocationOOP.h
js/src/jsapi-tests/testSeal.cpp
js/src/jsemit.cpp
js/src/jsemit.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.tbl
js/src/jsparse.cpp
js/src/jsparse.h
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jstracer.cpp
js/src/lirasm/tests/f2i.in
js/src/lirasm/tests/f2i.out
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/MonoIC.h
js/src/methodjit/StubCalls.h
js/src/tests/js1_5/extensions/regress-449657.js
layout/style/nsCSSRule.cpp
modules/zlib/src/algorithm.txt
modules/zlib/src/gzio.c
modules/zlib/src/zlib.3
other-licenses/branding/firefox/content/aboutCredits.png
other-licenses/branding/firefox/content/aboutFooter.png
security/patches/maemo-rpath-link.patch
security/patches/msvc-aslr.patch
services/sync/tests/unit/test_service_checkUsername.js
testing/mozmill/jsbridge-2.3.5/MANIFEST.in
testing/mozmill/jsbridge-2.3.5/PKG-INFO
testing/mozmill/jsbridge-2.3.5/jsbridge/__init__.py
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/chrome.manifest
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/chrome/content/overlay.js
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/chrome/content/overlay.xul
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/components/cmdarg.js
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/install.rdf
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/resource/modules/events.js
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/resource/modules/init.js
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/resource/modules/json2.js
testing/mozmill/jsbridge-2.3.5/jsbridge/extension/resource/modules/server.js
testing/mozmill/jsbridge-2.3.5/jsbridge/jsobjects.py
testing/mozmill/jsbridge-2.3.5/jsbridge/network.py
testing/mozmill/jsbridge-2.3.5/jsbridge/xpi/chromebug-0.5.0a1.xpi
testing/mozmill/jsbridge-2.3.5/jsbridge/xpi/firebug-1.4.0a3.xpi
testing/mozmill/jsbridge-2.3.5/jsbridge/xpi/javascript_debugger-0.9.87.4-fx+tb+sb+sm.xpi
testing/mozmill/jsbridge-2.3.5/jsbridge/xpi/mozlab-current-0.1.9.2008050521.xpi
testing/mozmill/jsbridge-2.3.5/jsbridge/xpi/xush-0.2-fx.xpi
testing/mozmill/jsbridge-2.3.5/setup.cfg
testing/mozmill/jsbridge-2.3.5/setup.py
testing/mozmill/mozmill-1.4.1/MANIFEST.in
testing/mozmill/mozmill-1.4.1/PKG-INFO
testing/mozmill/mozmill-1.4.1/docs/Makefile
testing/mozmill/mozmill-1.4.1/docs/_build/doctrees/environment.pickle
testing/mozmill/mozmill-1.4.1/docs/_build/doctrees/index.doctree
testing/mozmill/mozmill-1.4.1/docs/_build/html/_sources/index.txt
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/contents.png
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/default.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/doctools.js
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/file.png
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/jquery.js
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/minus.png
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/navigation.png
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/plus.png
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/pygments.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/rightsidebar.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/searchtools.js
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/sphinxdoc.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/stickysidebar.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/_static/traditional.css
testing/mozmill/mozmill-1.4.1/docs/_build/html/genindex.html
testing/mozmill/mozmill-1.4.1/docs/_build/html/index.html
testing/mozmill/mozmill-1.4.1/docs/_build/html/modindex.html
testing/mozmill/mozmill-1.4.1/docs/_build/html/objects.inv
testing/mozmill/mozmill-1.4.1/docs/_build/html/search.html
testing/mozmill/mozmill-1.4.1/docs/_build/html/searchindex.js
testing/mozmill/mozmill-1.4.1/docs/conf.py
testing/mozmill/mozmill-1.4.1/docs/index.rst
testing/mozmill/mozmill-1.4.1/mozmill/__init__.py
testing/mozmill/mozmill-1.4.1/mozmill/extension/build.xml
testing/mozmill/mozmill-1.4.1/mozmill/extension/chrome-jar.manifest
testing/mozmill/mozmill-1.4.1/mozmill/extension/chrome.manifest
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/mozmill.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-icons_222222_256x240.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-icons_2e83ff_256x240.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-icons_454545_256x240.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-icons_888888_256x240.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/images/ui-icons_cd0a0a_256x240.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/css/smoothness/jquery-ui-1.7.1.custom.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/dx.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/dxwindow.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/change_log.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/about.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/compatibility.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/configuration.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/credits.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/customization_language.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/customization_plugin.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/customization_syntax.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/doc_style.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/include.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/index.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/installation.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/javascript_functions.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/docs/license.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/autocompletion.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_compressor.php
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_full.gz
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_full.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_full_with_plugins.gz
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_full_with_plugins.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_functions.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/edit_area_loader.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/elements_functions.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/highlight.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/autocompletion.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/close.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/fullscreen.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/go_to_line.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/help.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/highlight.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/load.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/move.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/newdocument.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/opacity.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/processing.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/redo.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/reset_highlight.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/save.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/search.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/smooth_selection.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/spacer.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/statusbar_resize.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/undo.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/images/word_wrap.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/keyboard.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/bg.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/cs.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/de.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/dk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/en.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/eo.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/es.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/fi.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/fr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/hr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/it.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/ja.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/mk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/nl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/pl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/pt.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/ru.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/sk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/langs/zh.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/license_apache.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/license_bsd.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/license_lgpl.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/manage_area.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/charmap.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/css/charmap.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/images/charmap.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/jscripts/map.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/bg.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/cs.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/de.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/dk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/en.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/eo.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/es.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/fr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/hr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/it.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/ja.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/mk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/nl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/pl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/pt.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/ru.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/sk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/langs/zh.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/charmap/popup.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/css/test.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/images/Thumbs.db
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/images/test.gif
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/bg.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/cs.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/de.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/dk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/en.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/eo.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/es.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/fr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/hr.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/it.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/ja.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/mk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/nl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/pl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/pt.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/ru.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/sk.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/langs/zh.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/test.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/plugins/test/test2.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/basic.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/brainfuck.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/c.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/coldfusion.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/cpp.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/css.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/html.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/java.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/js.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/pas.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/perl.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/php.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/python.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/robotstxt.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/ruby.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/sql.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/tsql.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/vb.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/reg_syntax/xml.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/regexp.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/resize_area.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/search_replace.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/edit_area/template.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/exemples/exemple_full.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/license_apache.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/license_bsd.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/license_lgpl.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/editarea/todo.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/img/wmIcon.png
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/jquery/jquery-1.3.2.min.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/jquery/jquery-ui-1.7.1.custom.min.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/menus.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/mozmill.html
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/mozmill.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/mozmill.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/output.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/overlay.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/overlay.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/overlay_tb.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/prefs.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/rec.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/shell.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/shortcuts.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/testwindow.xul
testing/mozmill/mozmill-1.4.1/mozmill/extension/content/ui.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/defaults/preferences/debug.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/install.rdf
testing/mozmill/mozmill-1.4.1/mozmill/extension/locale/en-US/mozmill.dtd
testing/mozmill/mozmill-1.4.1/mozmill/extension/locale/en-US/overlay.dtd
testing/mozmill/mozmill-1.4.1/mozmill/extension/mozmill.xpi
testing/mozmill/mozmill-1.4.1/mozmill/extension/readme.txt
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/EventUtils.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/controller.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/elementslib.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/events.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/frame.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/init.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/inspection.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/jum.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/mozmill.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/modules/utils.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/arrays.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/dom.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/httpd.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/json2.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/objects.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/os.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/strings.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/resource/stdlib/withs.js
testing/mozmill/mozmill-1.4.1/mozmill/extension/skin/overlay.css
testing/mozmill/mozmill-1.4.1/mozmill/extension/zipexclude.lst
testing/mozmill/mozmill-1.4.1/setup.cfg
testing/mozmill/mozmill-1.4.1/setup.py
testing/mozmill/mozmill-1.4.1/test/test_python_callbacks_callbacks.py
testing/mozmill/mozrunner-2.4.2/PKG-INFO
testing/mozmill/mozrunner-2.4.2/mozrunner/__init__.py
testing/mozmill/mozrunner-2.4.2/mozrunner/killableprocess.py
testing/mozmill/mozrunner-2.4.2/mozrunner/qijo.py
testing/mozmill/mozrunner-2.4.2/mozrunner/winprocess.py
testing/mozmill/mozrunner-2.4.2/mozrunner/wpk.py
testing/mozmill/mozrunner-2.4.2/setup.cfg
testing/mozmill/mozrunner-2.4.2/setup.py
testing/mozmill/tests/addons/readme.txt
testing/mozmill/tests/addons/toolbar@google.com/testToolbarInstalled.js
testing/mozmill/tests/firefox/crashTests/testRemoveCookieAfterPrivateBrowsing.js
testing/mozmill/tests/firefox/helperClasses/testAddonsAPI.js
testing/mozmill/tests/firefox/helperClasses/testDownloadsAPI.js
testing/mozmill/tests/firefox/helperClasses/testPreferencesDialog.js
testing/mozmill/tests/firefox/helperClasses/testSearchAPI.js
testing/mozmill/tests/firefox/helperClasses/testSessionStoreAPI.js
testing/mozmill/tests/firefox/readme.txt
testing/mozmill/tests/firefox/restartTests/testDefaultBookmarks/test1.js
testing/mozmill/tests/firefox/restartTests/testExtensionInstallGetAddons/test1.js
testing/mozmill/tests/firefox/restartTests/testExtensionInstallGetAddons/test2.js
testing/mozmill/tests/firefox/restartTests/testExtensionInstallUninstall/test1.js
testing/mozmill/tests/firefox/restartTests/testExtensionInstallUninstall/test2.js
testing/mozmill/tests/firefox/restartTests/testExtensionInstallUninstall/test3.js
testing/mozmill/tests/firefox/restartTests/testMasterPassword/test1.js
testing/mozmill/tests/firefox/restartTests/testThemeInstallUninstall/test1.js
testing/mozmill/tests/firefox/restartTests/testThemeInstallUninstall/test2.js
testing/mozmill/tests/firefox/restartTests/testThemeInstallUninstall/test3.js
testing/mozmill/tests/firefox/softwareUpdate/testDirectUpdate/test1.js
testing/mozmill/tests/firefox/softwareUpdate/testDirectUpdate/test2.js
testing/mozmill/tests/firefox/softwareUpdate/testFallbackUpdate/test1.js
testing/mozmill/tests/firefox/softwareUpdate/testFallbackUpdate/test2.js
testing/mozmill/tests/firefox/softwareUpdate/testFallbackUpdate/test3.js
testing/mozmill/tests/firefox/testAddons/files/plugin.html
testing/mozmill/tests/firefox/testAddons/testDisableEnablePlugin.js
testing/mozmill/tests/firefox/testAddons/testGetAddons.js
testing/mozmill/tests/firefox/testAddons/testSearchAddons.js
testing/mozmill/tests/firefox/testAwesomeBar/testAccessLocationBar.js
testing/mozmill/tests/firefox/testAwesomeBar/testCheckItemHighlight.js
testing/mozmill/tests/firefox/testAwesomeBar/testEscapeAutocomplete.js
testing/mozmill/tests/firefox/testAwesomeBar/testLocationBarSearches.js
testing/mozmill/tests/firefox/testAwesomeBar/testSuggestHistoryBookmarks.js
testing/mozmill/tests/firefox/testAwesomeBar/testVisibleItemsMax.js
testing/mozmill/tests/firefox/testBookmarks/testAddBookmarkToMenu.js
testing/mozmill/tests/firefox/testCookies/testDisableCookies.js
testing/mozmill/tests/firefox/testCookies/testEnableCookies.js
testing/mozmill/tests/firefox/testCookies/testRemoveAllCookies.js
testing/mozmill/tests/firefox/testCookies/testRemoveCookie.js
testing/mozmill/tests/firefox/testDownloading/testCloseDownloadManager.js
testing/mozmill/tests/firefox/testDownloading/testDownloadStates.js
testing/mozmill/tests/firefox/testDownloading/testOpenDownloadManager.js
testing/mozmill/tests/firefox/testFindInPage/testFindInPage.js
testing/mozmill/tests/firefox/testFormManager/testAutoCompleteOff.js
testing/mozmill/tests/firefox/testFormManager/testBasicFormCompletion.js
testing/mozmill/tests/firefox/testFormManager/testClearFormHistory.js
testing/mozmill/tests/firefox/testFormManager/testDisableFormManager.js
testing/mozmill/tests/firefox/testGeneral/testBackForwardButtons.js
testing/mozmill/tests/firefox/testGeneral/testGoogleSuggestions.js
testing/mozmill/tests/firefox/testGeneral/testStopReloadButtons.js
testing/mozmill/tests/firefox/testInstallation/testBreakpadInstalled.js
testing/mozmill/tests/firefox/testLayout/testNavigateFTP.js
testing/mozmill/tests/firefox/testPasswordManager/testPasswordNotSaved.js
testing/mozmill/tests/firefox/testPasswordManager/testPasswordSavedAndDeleted.js
testing/mozmill/tests/firefox/testPopups/testPopupsAllowed.js
testing/mozmill/tests/firefox/testPopups/testPopupsBlocked.js
testing/mozmill/tests/firefox/testPreferences/testPaneRetention.js
testing/mozmill/tests/firefox/testPreferences/testPreferredLanguage.js
testing/mozmill/tests/firefox/testPreferences/testRestoreHomepageToDefault.js
testing/mozmill/tests/firefox/testPreferences/testSwitchPanes.js
testing/mozmill/tests/firefox/testPrivateBrowsing/files/geolocation.html
testing/mozmill/tests/firefox/testPrivateBrowsing/testAboutPrivateBrowsing.js
testing/mozmill/tests/firefox/testPrivateBrowsing/testDisabledElements.js
testing/mozmill/tests/firefox/testPrivateBrowsing/testDisabledPermissions.js
testing/mozmill/tests/firefox/testPrivateBrowsing/testDownloadManagerClosed.js
testing/mozmill/tests/firefox/testPrivateBrowsing/testGeolocation.js
testing/mozmill/tests/firefox/testPrivateBrowsing/testTabsDismissedOnStop.js
testing/mozmill/tests/firefox/testSearch/testAddMozSearchProvider.js
testing/mozmill/tests/firefox/testSearch/testFocusAndSearch.js
testing/mozmill/tests/firefox/testSearch/testGetMoreSearchEngines.js
testing/mozmill/tests/firefox/testSearch/testOpenSearchAutodiscovery.js
testing/mozmill/tests/firefox/testSearch/testRemoveSearchEngine.js
testing/mozmill/tests/firefox/testSearch/testReorderSearchEngines.js
testing/mozmill/tests/firefox/testSearch/testRestoreDefaults.js
testing/mozmill/tests/firefox/testSearch/testSearchSelection.js
testing/mozmill/tests/firefox/testSearch/testSearchSuggestions.js
testing/mozmill/tests/firefox/testSecurity/testBlueLarry.js
testing/mozmill/tests/firefox/testSecurity/testDefaultPhishingEnabled.js
testing/mozmill/tests/firefox/testSecurity/testDefaultSecurityPrefs.js
testing/mozmill/tests/firefox/testSecurity/testEncryptedPageWarning.js
testing/mozmill/tests/firefox/testSecurity/testGreenLarry.js
testing/mozmill/tests/firefox/testSecurity/testGreyLarry.js
testing/mozmill/tests/firefox/testSecurity/testIdentityPopupOpenClose.js
testing/mozmill/tests/firefox/testSecurity/testSSLDisabledErrorPage.js
testing/mozmill/tests/firefox/testSecurity/testSafeBrowsingNotificationBar.js
testing/mozmill/tests/firefox/testSecurity/testSafeBrowsingWarningPages.js
testing/mozmill/tests/firefox/testSecurity/testSecurityInfoViaPadlock.js
testing/mozmill/tests/firefox/testSecurity/testSecurityNotification.js
testing/mozmill/tests/firefox/testSecurity/testStatusBarSSLDisplay.js
testing/mozmill/tests/firefox/testSecurity/testSubmitUnencryptedInfoWarning.js
testing/mozmill/tests/firefox/testSecurity/testUnknownIssuer.js
testing/mozmill/tests/firefox/testSecurity/testUntrustedConnectionErrorPage.js
testing/mozmill/tests/firefox/testTabbedBrowsing/files/openinnewtab.html
testing/mozmill/tests/firefox/testTabbedBrowsing/files/openinnewtab_target.html
testing/mozmill/tests/firefox/testTabbedBrowsing/testBackgroundTabScrolling.js
testing/mozmill/tests/firefox/testTabbedBrowsing/testCloseTab.js
testing/mozmill/tests/firefox/testTabbedBrowsing/testNewTab.js
testing/mozmill/tests/firefox/testTabbedBrowsing/testNewWindow.js
testing/mozmill/tests/firefox/testTabbedBrowsing/testOpenInBackground.js
testing/mozmill/tests/firefox/testTabbedBrowsing/testOpenInForeground.js
testing/mozmill/tests/readme.txt
testing/mozmill/tests/scripts/libs/install.py
testing/mozmill/tests/scripts/libs/prefs.py
testing/mozmill/tests/scripts/readme.txt
testing/mozmill/tests/scripts/update.py
testing/mozmill/tests/templates/readme.txt
testing/mozmill/tests/templates/testEmptyTest.js
testing/mozmill/tests/templates/testModalDialog.js
testing/mozmill/tests/templates/testPreferencesDialog.js
testing/mozmill/tests/templates/testSharedModules.js
toolkit/mozapps/extensions/test/browser/browser_backgroundupdate_menuitem.js
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -88,37 +88,26 @@ nsIAtom *nsDocAccessible::gLastFocusedFr
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 nsDocAccessible::
   nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
                   nsIWeakReference *aShell) :
-  nsHyperTextAccessibleWrap(aRootContent, aShell), mWnd(nsnull),
+  nsHyperTextAccessibleWrap(aRootContent, aShell),
   mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
 {
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
 
   // For GTK+ native window, we do nothing here.
   if (!mDocument)
     return;
 
-  // Initialize mWnd
-  nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
-  nsIViewManager* vm = shell->GetViewManager();
-  if (vm) {
-    nsCOMPtr<nsIWidget> widget;
-    vm->GetRootWidget(getter_AddRefs(widget));
-    if (widget) {
-      mWnd = widget->GetNativeData(NS_NATIVE_WINDOW);
-    }
-  }
-
   // nsAccDocManager creates document accessible when scrollable frame is
   // available already, it should be safe time to add scroll listener.
   AddScrollListener();
 }
 
 nsDocAccessible::~nsDocAccessible()
 {
 }
@@ -468,17 +457,18 @@ NS_IMETHODIMP nsDocAccessible::GetNameSp
     if (nameSpaceManager)
       return nameSpaceManager->GetNameSpaceURI(aNameSpaceID, aNameSpaceURI);
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
 {
-  *aWindow = mWnd;
+  NS_ENSURE_ARG_POINTER(aWindow);
+  *aWindow = GetNativeWindow();
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::GetWindow(nsIDOMWindow **aDOMWin)
 {
   *aDOMWin = nsnull;
   if (!mDocument) {
     return NS_ERROR_FAILURE;  // Accessible is Shutdown()
@@ -1330,16 +1320,30 @@ nsDocAccessible::HandleAccEvent(AccEvent
   return nsHyperTextAccessible::HandleAccEvent(aAccEvent);
 
 }
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // Public members
 
+void*
+nsDocAccessible::GetNativeWindow() const
+{
+  nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
+  nsIViewManager* vm = shell->GetViewManager();
+  if (vm) {
+    nsCOMPtr<nsIWidget> widget;
+    vm->GetRootWidget(getter_AddRefs(widget));
+    if (widget)
+      return widget->GetNativeData(NS_NATIVE_WINDOW);
+  }
+  return nsnull;
+}
+
 nsAccessible*
 nsDocAccessible::GetCachedAccessibleInSubtree(void* aUniqueID)
 {
   nsAccessible* child = GetCachedAccessible(aUniqueID);
   if (child)
     return child;
 
   PRUint32 childDocCount = mChildDocuments.Length();
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -137,16 +137,21 @@ public:
   /**
    * Marks as loaded, used for error pages as workaround since they do not
    * receive pageshow event and as consequence nsIDocument::IsShowing() returns
    * false.
    */
   void MarkAsLoaded() { mIsLoaded = PR_TRUE; }
 
   /**
+   * Return a native window handler or pointer depending on platform.
+   */
+  virtual void* GetNativeWindow() const;
+
+  /**
    * Return the parent document.
    */
   nsDocAccessible* ParentDocument() const
     { return mParent ? mParent->GetDocAccessible() : nsnull; }
 
   /**
    * Return the child document count.
    */
@@ -358,17 +363,16 @@ protected:
    */
   void FireValueChangeForTextFields(nsAccessible *aAccessible);
 
   /**
    * Cache of accessibles within this document accessible.
    */
   nsAccessibleHashtable mAccessibleCache;
 
-    void *mWnd;
     nsCOMPtr<nsIDocument> mDocument;
     nsCOMPtr<nsITimer> mScrollWatchTimer;
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
 
 protected:
 
   nsRefPtr<nsAccEventQueue> mEventQueue;
 
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -589,19 +589,23 @@ GetNativeFromGeckoAccessible(nsIAccessib
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (NSWindow*)window
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   nsAccessibleWrap *accWrap = static_cast<nsAccessibleWrap*>(mGeckoAccessible);
+
+  // Get a pointer to the native window (NSWindow) we reside in.
   NSWindow *nativeWindow = nil;
-  accWrap->GetNativeWindow ((void**)&nativeWindow);
-  
+  nsDocAccessible* docAcc = accWrap->GetDocAccessible();
+  if (docAcc)
+    nativeWindow = static_cast<NSWindow*>(docAcc->GetNativeWindow());
+
   NSAssert1(nativeWindow, @"Could not get native window for %@", self);
   return nativeWindow;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (void)invalidateChildren
 {
--- a/accessible/src/mac/nsAccessibleWrap.h
+++ b/accessible/src/mac/nsAccessibleWrap.h
@@ -66,20 +66,17 @@ class nsAccessibleWrap : public nsAccess
     
     // get the native obj-c object (mozAccessible)
     NS_IMETHOD GetNativeInterface (void **aOutAccessible);
     
     // the objective-c |Class| type that this accessible's native object
     // should be instantied with.   used on runtime to determine the
     // right type for this accessible's associated native object.
     virtual objc_class* GetNativeType ();
-    
-    // returns a pointer to the native window for this accessible tree.
-    void GetNativeWindow (void **aOutNativeWindow);
-    
+
     virtual void Shutdown ();
     virtual void InvalidateChildren();
 
     virtual nsresult HandleAccEvent(AccEvent* aEvent);
 
     // ignored means that the accessible might still have children, but is not displayed
     // to the user. it also has no native accessible object represented for it.
     PRBool IsIgnored();
--- a/accessible/src/mac/nsAccessibleWrap.mm
+++ b/accessible/src/mac/nsAccessibleWrap.mm
@@ -81,27 +81,16 @@ nsAccessibleWrap::GetNativeInterface (vo
 {
   if (mNativeWrapper) {
     *aOutInterface = (void**)mNativeWrapper->getNativeObject();
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
-// get the native NSWindow we reside in.
-void
-nsAccessibleWrap::GetNativeWindow (void **aOutNativeWindow)
-{
-  *aOutNativeWindow = nsnull;
-
-  nsDocAccessible *docAcc = GetDocAccessible();
-  if (docAcc)
-    docAcc->GetWindowHandle (aOutNativeWindow);
-}
-
 // overridden in subclasses to create the right kind of object. by default we create a generic
 // 'mozAccessible' node.
 objc_class*
 nsAccessibleWrap::GetNativeType () 
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   PRUint32 role = Role();
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -41,16 +41,17 @@
 #include "AccessibleApplication.h"
 #include "ISimpleDOMNode_i.c"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsApplicationAccessibleWrap.h"
 #include "nsCoreUtils.h"
 #include "nsRootAccessible.h"
+#include "nsWinUtils.h"
 
 #include "nsAttrName.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
@@ -58,16 +59,17 @@
 #include "nsIPrefBranch.h"
 #include "nsPIDOMWindow.h"
 #include "nsIServiceManager.h"
 
 /// the accessible library and cached methods
 HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
 HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
 LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
+LPFNLRESULTFROMOBJECT nsAccessNodeWrap::gmLresultFromObject = NULL;
 LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
 LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
 
 PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
 // Used to determine whether an IAccessible2 compatible screen reader is loaded.
 PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
 
 AccTextChangeEvent* nsAccessNodeWrap::gTextEvent = nsnull;
@@ -564,25 +566,37 @@ void nsAccessNodeWrap::InitAccessibility
   if (gmUserLib) {
     if (!gmNotifyWinEvent)
       gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
     if (!gmGetGUIThreadInfo)
       gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
   }
 
   DoATSpecificProcessing();
-  
+
+  // Register window class that'll be used for document accessibles associated
+  // with tabs.
+  if (nsWinUtils::IsWindowEmulationEnabled()) {
+    nsWinUtils::RegisterNativeWindow(kClassNameTabContent);
+    sHWNDCache.Init(4);
+  }
+
   nsAccessNode::InitXPAccessibility();
 }
 
 void nsAccessNodeWrap::ShutdownAccessibility()
 {
   NS_IF_RELEASE(gTextEvent);
   ::DestroyCaret();
 
+  // Unregister window call that's used for document accessibles associated
+  // with tabs.
+  if (nsWinUtils::IsWindowEmulationEnabled())
+    ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
+
   nsAccessNode::ShutdownXPAccessibility();
 }
 
 int nsAccessNodeWrap::FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo)
 {
   if (aCode == EXCEPTION_ACCESS_VIOLATION) {
 #ifdef MOZ_CRASHREPORTER
     // MSAA swallows crashes (because it is COM-based)
@@ -619,17 +633,17 @@ GetHRESULT(nsresult aResult)
 
     default:
       return E_FAIL;
   }
 }
 
 PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
 {
-  HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
+  HMODULE jhookhandle = ::GetModuleHandleW(kJAWSModuleHandle);
   if (!jhookhandle)
     return PR_FALSE;  // No JAWS, or some other screen reader, use IA2
 
   PRUnichar fileName[MAX_PATH];
   ::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
 
   DWORD dummy;
   DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
@@ -650,20 +664,20 @@ PRBool nsAccessNodeWrap::IsOnlyMsaaCompa
 //  DWORD dwRightMost = LOWORD(dwFileVersionLS);
 
   return (dwLeftMost < 8
           || (dwLeftMost == 8 && dwSecondRight < 2173));
 }
 
 void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
 {
-  HMODULE srHandle = ::GetModuleHandleW(L"jhook");
+  HMODULE srHandle = ::GetModuleHandleW(kJAWSModuleHandle);
   if (!srHandle) {
     // No JAWS, try Window-Eyes
-    srHandle = ::GetModuleHandleW(L"gwm32inc");
+    srHandle = ::GetModuleHandleW(kWEModuleHandle);
     if (!srHandle) {
       // no screen reader we're interested in. Bail out.
       return;
     }
   }
 
   // Check to see if the pref for disallowing CtrlTab is already set.
   // If so, bail out.
@@ -689,8 +703,54 @@ void nsAccessNodeWrap::TurnOffNewTabSwit
 void nsAccessNodeWrap::DoATSpecificProcessing()
 {
   if (IsOnlyMsaaCompatibleJawsPresent())
     // All versions below 8.0.2173 are not compatible
     gIsIA2Disabled  = PR_TRUE;
 
   TurnOffNewTabSwitchingForJawsAndWE();
 }
+
+nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> nsAccessNodeWrap::sHWNDCache;
+
+LRESULT CALLBACK
+nsAccessNodeWrap::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+  switch (msg) {
+    case WM_GETOBJECT:
+    {
+      if (lParam == OBJID_CLIENT) {
+        nsDocAccessible* document = sHWNDCache.GetWeak(static_cast<void*>(hWnd));
+        if (document) {
+          IAccessible* msaaAccessible = NULL;
+          document->GetNativeInterface((void**)&msaaAccessible); // does an addref
+          if (msaaAccessible) {
+            LRESULT result = LresultFromObject(IID_IAccessible, wParam,
+                                               msaaAccessible); // does an addref
+            msaaAccessible->Release(); // release extra addref
+            return result;
+          }
+        }
+      }
+      return 0;
+    }
+  }
+
+  return ::DefWindowProcW(hWnd, msg, wParam, lParam);
+}
+
+STDMETHODIMP_(LRESULT)
+nsAccessNodeWrap::LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
+{
+  // open the dll dynamically
+  if (!gmAccLib)
+    gmAccLib =::LoadLibraryW(L"OLEACC.DLL");
+
+  if (gmAccLib) {
+    if (!gmLresultFromObject)
+      gmLresultFromObject = (LPFNLRESULTFROMOBJECT)GetProcAddress(gmAccLib,"LresultFromObject");
+
+    if (gmLresultFromObject)
+      return gmLresultFromObject(riid, wParam, pAcc);
+  }
+
+  return 0;
+}
--- a/accessible/src/msaa/nsAccessNodeWrap.h
+++ b/accessible/src/msaa/nsAccessNodeWrap.h
@@ -63,16 +63,18 @@
 #include <winuser.h>
 #ifndef WINABLEAPI
 #include <winable.h>
 #endif
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #endif
 
+#include "nsRefPtrHashtable.h"
+
 typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
 typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
 
 class AccTextChangeEvent;
 
 class nsAccessNodeWrap :  public nsAccessNode,
                           public nsIWinAccessNode,
                           public ISimpleDOMNode,
@@ -149,27 +151,35 @@ public: // construction, destruction
 
     static void InitAccessibility();
     static void ShutdownAccessibility();
 
     /// the accessible library and cached methods
     static HINSTANCE gmAccLib;
     static HINSTANCE gmUserLib;
     static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
+    static LPFNLRESULTFROMOBJECT gmLresultFromObject;
     static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
     static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
 
     static int FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo);
 
     static PRBool IsOnlyMsaaCompatibleJawsPresent();
 
     static void TurnOffNewTabSwitchingForJawsAndWE();
 
     static void DoATSpecificProcessing();
 
+  static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
+
+  static LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
+                                     WPARAM WParam, LPARAM lParam);
+
+  static nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> sHWNDCache;
+
 protected:
 
   /**
    * Return ISimpleDOMNode instance for existing accessible object or
    * creates new nsAccessNode instance if the accessible doesn't exist.
    *
    * @note ISimpleDOMNode is returned addrefed
    */
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessibleWrap.h"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsRelUtils.h"
+#include "nsWinUtils.h"
 
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIAccessibleWin32Object.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleStates.h"
 
@@ -188,68 +189,33 @@ STDMETHODIMP nsAccessibleWrap::NotifyWin
 
   return E_FAIL;
 }
 
 STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
 {
 __try {
   *ppdispParent = NULL;
-  if (!mWeakShell)
-    return E_FAIL;  // We've been shut down
 
-  nsIFrame *frame = GetFrame();
-  HWND hwnd = 0;
-  if (frame) {
-    nsIView *view = frame->GetViewExternal();
-    if (view) {
-      // This code is essentially our implementation of WindowFromAccessibleObject,
-      // because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
-      // to know where the window for a given accessible is. We must expose the native
-      // window accessible that MSAA creates for us. This must be done for the document
-      // object as well as any layout that creates its own window (e.g. via overflow: scroll)
-      nsIWidget *widget = view->GetWidget();
-      if (widget) {
-        hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
-        NS_ASSERTION(hwnd, "No window handle for window");
-
-        nsIViewManager* viewManager = view->GetViewManager();
-        if (!viewManager)
-          return E_UNEXPECTED;
+  if (IsDefunct())
+    return E_FAIL;
 
-        nsIView *rootView;
-        viewManager->GetRootView(rootView);
-        if (rootView == view) {
-          // If the client accessible (OBJID_CLIENT) has a window but its window
-          // was created by an outer window then we want the native accessible
-          // for that outer window. If the accessible was created for outer
-          // window (if the outer window has inner windows then they share the
-          // same client accessible with it) then return native accessible for
-          // the outer window.
-          HWND parenthwnd = ::GetParent(hwnd);
-          if (parenthwnd)
-            hwnd = parenthwnd;
-
-          NS_ASSERTION(hwnd, "No window handle for window");
-        }
+  nsRefPtr<nsDocAccessible> doc(do_QueryObject(this));
+  if (doc) {
+    // Return window system accessible object for root document and tab document
+    // accessibles.
+    if (!doc->ParentDocument() ||
+        nsWinUtils::IsWindowEmulationEnabled() &&
+        nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
+      HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
+      if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
+                                                       IID_IAccessible,
+                                                       (void**)ppdispParent))) {
+        return S_OK;
       }
-      else {
-        // If a frame is a scrollable frame, then it has one window for the client area,
-        // not an extra parent window for just the scrollbars
-        nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
-        if (scrollFrame) {
-          hwnd = (HWND)scrollFrame->GetScrolledFrame()->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
-          NS_ASSERTION(hwnd, "No window handle for window");
-        }
-      }
-    }
-
-    if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible,
-                                              (void**)ppdispParent))) {
-      return S_OK;
     }
   }
 
   nsAccessible* xpParentAcc = GetParent();
   NS_ASSERTION(xpParentAcc,
                "No parent accessible where we're not direct child of window");
 
   if (!xpParentAcc)
@@ -382,16 +348,19 @@ nsAccessibleWrap::get_accDescription(VAR
 
 STDMETHODIMP nsAccessibleWrap::get_accRole(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
 {
 __try {
   VariantInit(pvarRole);
 
+  if (IsDefunct())
+    return E_FAIL;
+
   nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_FAIL;
 
 #ifdef DEBUG_A11Y
   NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(xpAccessible),
                "Does not support nsIAccessibleText when it should");
 #endif
@@ -1182,16 +1151,19 @@ nsAccessibleWrap::get_relations(long aMa
 }
 
 STDMETHODIMP
 nsAccessibleWrap::role(long *aRole)
 {
 __try {
   *aRole = 0;
 
+  if (IsDefunct())
+    return E_FAIL;
+
   NS_ASSERTION(gWindowsRoleMap[nsIAccessibleRole::ROLE_LAST_ENTRY].ia2Role == ROLE_WINDOWS_LAST_ENTRY,
                "MSAA role map skewed");
 
   PRUint32 xpRole = Role();
   *aRole = gWindowsRoleMap[xpRole].ia2Role;
 
   // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
   // the IA2 role a ROLE_OUTLINEITEM.
@@ -1657,55 +1629,21 @@ PRInt32 nsAccessibleWrap::GetChildIDFor(
   // Yes, this means we're only compatibible with 32 bit
   // MSAA is only available for 32 bit windows, so it's okay
   return - NS_PTR_TO_INT32(uniqueID);
 }
 
 HWND
 nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
 {
-  HWND hWnd = 0;
   if (!aAccessible)
-    return hWnd;
+    return 0;
 
-  nsIFrame *frame = aAccessible->GetFrame();
-  if (frame) {
-    nsIWidget *window = frame->GetNearestWidget();
-    PRBool isVisible;
-    window->IsVisible(isVisible);
-    if (isVisible) {
-      // Short explanation:
-      // If HWND for frame is inside a hidden window, fire the event on the
-      // containing document's visible window.
-      //
-      // Long explanation:
-      // This is really just to fix combo boxes with JAWS. Window-Eyes already
-      // worked with combo boxes because they use the value change event in
-      // the closed combo box case. JAWS will only pay attention to the focus
-      // events on the list items. The JAWS developers haven't fixed that, so
-      // we'll use the focus events to make JAWS work. However, JAWS is
-      // ignoring events on a hidden window. So, in order to fix the bug where
-      // JAWS doesn't echo the current option as it changes in a closed
-      // combo box, we need to use an ensure that we never fire an event with
-      // an HWND for a hidden window.
-      hWnd = (HWND)frame->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
-    }
-  }
-
-  if (!hWnd) {
-    void* handle = nsnull;
-    nsDocAccessible *accessibleDoc = aAccessible->GetDocAccessible();
-    if (!accessibleDoc)
-      return 0;
-
-    accessibleDoc->GetWindowHandle(&handle);
-    hWnd = (HWND)handle;
-  }
-
-  return hWnd;
+  nsDocAccessible* document = aAccessible->GetDocAccessible();
+  return document ? static_cast<HWND>(document->GetNativeWindow()) : 0;
 }
 
 HRESULT
 nsAccessibleWrap::ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
                                          BSTR *aIA2Attributes)
 {
   *aIA2Attributes = NULL;
 
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -34,16 +34,19 @@
  * 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 "nsDocAccessibleWrap.h"
 #include "ISimpleDOMDocument_i.c"
 #include "nsIAccessibilityService.h"
+#include "nsRootAccessible.h"
+#include "nsWinUtils.h"
+
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 #include "nsIViewManager.h"
@@ -55,17 +58,17 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsDocAccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 
 nsDocAccessibleWrap::
   nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
                       nsIWeakReference *aShell) :
-  nsDocAccessible(aDocument, aRootContent, aShell)
+  nsDocAccessible(aDocument, aRootContent, aShell), mHWND(NULL)
 {
 }
 
 nsDocAccessibleWrap::~nsDocAccessibleWrap()
 {
 }
 
 //-----------------------------------------------------
@@ -240,8 +243,58 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
   if (role != nsIAccessibleRole::ROLE_DOCUMENT &&
       role != nsIAccessibleRole::ROLE_APPLICATION &&
       role != nsIAccessibleRole::ROLE_DIALOG &&
       role != nsIAccessibleRole::ROLE_ALERT)
     return hr;
 
   return get_URL(pszValue);
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessNode
+
+PRBool
+nsDocAccessibleWrap::Init()
+{
+  if (nsWinUtils::IsWindowEmulationEnabled()) {
+    // Create window for tab document.
+    if (nsWinUtils::IsTabDocument(mDocument)) {
+      nsRefPtr<nsRootAccessible> root = GetRootAccessible();
+      mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
+                                             static_cast<HWND>(root->GetNativeWindow()));
+
+      nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
+
+    } else {
+      nsDocAccessible* parentDocument = ParentDocument();
+      if (parentDocument)
+        mHWND = parentDocument->GetNativeWindow();
+    }
+  }
+
+  return nsDocAccessible::Init();
+}
+
+void
+nsDocAccessibleWrap::Shutdown()
+{
+  if (nsWinUtils::IsWindowEmulationEnabled()) {
+    // Destroy window created for root document.
+    if (nsWinUtils::IsTabDocument(mDocument)) {
+      nsAccessibleWrap::sHWNDCache.Remove(mHWND);
+      ::DestroyWindow(static_cast<HWND>(mHWND));
+    }
+
+    mHWND = nsnull;
+  }
+
+  nsDocAccessible::Shutdown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsDocAccessible
+
+void*
+nsDocAccessibleWrap::GetNativeWindow() const
+{
+  return mHWND ? mHWND : nsDocAccessible::GetNativeWindow();
+}
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -84,13 +84,23 @@ public:
 
     // IAccessible
 
     // Override get_accValue to provide URL when no other value is available
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( 
         /* [optional][in] */ VARIANT varChild,
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
+  // nsAccessNode
+  virtual PRBool Init();
+  virtual void Shutdown();
+
   // nsAccessibleWrap
   virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
+
+  // nsDocAccessible
+  virtual void* GetNativeWindow() const;
+
+protected:
+  void* mHWND;
 };
 
 #endif
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -38,16 +38,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsWinUtils.h"
 
 #include "nsAccessibleWrap.h"
 #include "nsIWinAccessNode.h"
 #include "nsArrayUtils.h"
+#include "nsIDocShellTreeItem.h"
 
 HRESULT
 nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
                               long *aIA2ArrayLen)
 {
   *aIA2Array = NULL;
   *aIA2ArrayLen = 0;
 
@@ -91,8 +92,62 @@ nsWinUtils::ConvertToIA2Array(nsIArray *
 
     nsMemory::Free(*aIA2Array);
     return GetHRESULT(rv);
   }
 
   *aIA2ArrayLen = length;
   return S_OK;
 }
+
+void
+nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
+{
+  WNDCLASSW wc;
+  wc.style = CS_GLOBALCLASS;
+  wc.lpfnWndProc = nsAccessNodeWrap::WindowProc;
+  wc.cbClsExtra = 0;
+  wc.cbWndExtra = 0;
+  wc.hInstance = GetModuleHandle(NULL);
+  wc.hIcon = NULL;
+  wc.hCursor = NULL;
+  wc.hbrBackground = NULL;
+  wc.lpszMenuName = NULL;
+  wc.lpszClassName = aWindowClass;
+  ::RegisterClassW(&wc);
+}
+
+HWND
+nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd)
+{
+  return ::CreateWindowW(aWindowClass,
+                         L"NetscapeDispatchWnd",
+                         WS_CHILD | WS_VISIBLE,
+                         CW_USEDEFAULT, CW_USEDEFAULT,
+                         0, 0,
+                         aParentWnd,
+                         NULL,
+                         GetModuleHandle(NULL),
+                         NULL);
+}
+
+bool
+nsWinUtils::IsWindowEmulationEnabled()
+{
+  return ::GetModuleHandleW(kJAWSModuleHandle) ||
+    ::GetModuleHandleW(kWEModuleHandle)  ||
+    ::GetModuleHandleW(kDolphnModuleHandle);
+}
+
+bool
+nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode)
+{
+  nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
+
+  nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
+  treeItem->GetParent(getter_AddRefs(parentTreeItem));
+
+  nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
+  treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
+
+  return parentTreeItem == rootTreeItem;
+}
--- a/accessible/src/msaa/nsWinUtils.h
+++ b/accessible/src/msaa/nsWinUtils.h
@@ -39,22 +39,50 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsWinUtils_h_
 #define nsWinUtils_h_
 
 #include "Accessible2.h"
 
 #include "nsIArray.h"
+#include "nsIDocument.h"
+
+const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass";
+const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
+
+const LPCWSTR kJAWSModuleHandle = L"jhook";
+const LPCWSTR kWEModuleHandle = L"gwm32inc";
+const LPCWSTR kDolphnModuleHandle = L"dolwinhk";
 
 class nsWinUtils
 {
 public:
   /**
    * Convert nsIArray array of accessible objects to an array of IUnknown*
    * objects used in IA2 methods.
    */
   static HRESULT ConvertToIA2Array(nsIArray *aCollection,
                                    IUnknown ***aAccessibles, long *aCount);
+
+  /**
+   * Helper to register window class.
+   */
+  static void RegisterNativeWindow(LPCWSTR aWindowClass);
+
+  /**
+   * Helper to create a window.
+   */
+  static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd);
+
+  /**
+   * Return true if window emulation is enabled.
+   */
+  static bool IsWindowEmulationEnabled();
+
+  /**
+   * Return true if the given document node is for tab document accessible.
+   */
+  static bool IsTabDocument(nsIDocument* aDocumentNode);
 };
 
 #endif
 
--- a/accessible/tests/mochitest/tree/test_txtctrl.html
+++ b/accessible/tests/mochitest/tree/test_txtctrl.html
@@ -45,29 +45,17 @@
 
       testAccessibleTree("txc2", accTree);
 
       // textarea
       accTree = {
         role: ROLE_ENTRY,
         children: [
           {
-            role: ROLE_TEXT_LEAF // hello1 text
-          },
-          {
-            role: ROLE_WHITESPACE
-          },
-          {
-            role: ROLE_TEXT_LEAF, // hello2 text
-          },
-          {
-            role: ROLE_WHITESPACE
-          },
-          {
-            role: ROLE_TEXT_LEAF, // whitepsace text
+            role: ROLE_TEXT_LEAF // hello1\nhello2 text
           },
           {
             role: ROLE_WHITESPACE
           }
         ]
       };
 
       testAccessibleTree("txc3", accTree);
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -68,32 +68,39 @@ pref("extensions.webservice.discoverURL"
 pref("extensions.blocklist.enabled", true);
 pref("extensions.blocklist.interval", 86400);
 // Controls what level the blocklist switches from warning about items to forcibly
 // blocking them.
 pref("extensions.blocklist.level", 2);
 pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
 pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
 
+pref("extensions.update.autoUpdateDefault", true);
+
 // Dictionary download preference
 pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/%APP%/dictionaries/");
 
 // Update Timer Manager preferences
 // Interval: When all registered timers should be checked (in milliseconds)
 //           default=10 minutes
 pref("app.update.timer", 600000);
 
 // App-specific update preferences
 
 // The interval to check for updates (app.update.interval) is defined in
 // firefox-branding.js
 
 // Enables some extra Application Update Logging (can reduce performance)
 pref("app.update.log", false);
 
+// The number of general background check failures to allow before notifying the
+// user of the failure. User initiated update checks always notify the user of
+// the failure.
+pref("app.update.backgroundMaxErrors", 10);
+
 // When |app.update.cert.requireBuiltIn| is true or not specified the
 // final certificate and all certificates the connection is redirected to before
 // the final certificate for the url specified in the |app.update.url|
 // preference must be built-in.
 pref("app.update.cert.requireBuiltIn", true);
 
 // When |app.update.cert.checkAttributes| is true or not specified the
 // certificate attributes specified in the |app.update.certs.| preference branch
@@ -788,16 +795,18 @@ pref("browser.sessionstore.privacy_level
 // how many tabs can be reopened (per window)
 pref("browser.sessionstore.max_tabs_undo", 10);
 // how many windows can be reopened (per session) - on non-OS X platforms this
 // pref may be ignored when dealing with pop-up windows to ensure proper startup
 pref("browser.sessionstore.max_windows_undo", 3);
 // number of crashes that can occur before the about:sessionrestore page is displayed
 // (this pref has no effect if more than 6 hours have passed since the last crash)
 pref("browser.sessionstore.max_resumed_crashes", 1);
+// number of tabs to restore concurrently
+pref("browser.sessionstore.max_concurrent_tabs", 3);
 
 // allow META refresh by default
 pref("accessibility.blockautorefresh", false);
 
 // Whether history is enabled or not.
 pref("places.history.enabled", true);
 
 // The percentage of system memory that the Places database can use.  Out of the
--- a/browser/base/content/aboutDialog.css
+++ b/browser/base/content/aboutDialog.css
@@ -1,106 +1,84 @@
 #aboutDialog {
   padding-top: 0;
   -moz-padding-end: 0;
   padding-bottom: 10px;
   -moz-padding-start: 0;
-  width: 299px;
-}
-
-#modes {
-  min-height: 400px;
+  width: 600px;
 }
 
 #clientBox {
-  /* Add a min-width equal to chrome://branding/content/about.png's
-   * width, to maintain the dialog layout on OS X where the dialog is
-   * align="end" to right-align the button.
-   */
-  min-width: 300px;
-  background-image: url("chrome://branding/content/about.png");
-  background-repeat: no-repeat;
-  background-color: #FFFFFF;
-  padding-top: 203px;
-  color: #000000;
+  background-color: #F7F7F7;
+  color: #222222;
 }
 
-#brandName {
-  font-weight: bold; font-size: larger;
+#leftBox {
+  background-image: url("chrome://branding/content/about-logo.png");
+  background-repeat: no-repeat;
+  /* min-width and min-height create room for the logo */
+  min-width: 210px;
+  min-height: 210px;
+  margin-top:20px;
+  -moz-margin-start: 30px;
 }
 
-#userAgent {
-  direction: ltr;
-  margin-top: 10px;
-  -moz-margin-end: 13px;
-  margin-bottom: 0;
-  -moz-margin-start: 13px;
-  background-color: #FFFFFF;
-  color: #000000;
-  padding-top: 1px;
-  -moz-padding-end: 1px;
-  padding-bottom: 1px;
-  -moz-padding-start: 3px;
-  -moz-appearance: none;
-  overflow: hidden;
-  border: 0;
+#rightBox {
+  background-image: url("chrome://branding/content/about-wordmark.png");
+  background-repeat: no-repeat;
+  /* padding-top creates room for the wordmark */
+  padding-top: 38px;
+  margin-top:20px;
+  -moz-margin-end: 30px;
+  -moz-margin-start: 30px;
 }
 
-#groove {
-  margin-top: 0;
+#rightBox:-moz-locale-dir(rtl) {
+  background-position: 100% 0;
 }
 
-#creditsIframe {
-  cursor: default;
-  -moz-user-select: none;
-  border: 0;
+#bottomBox {
+  padding: 15px 10px 0;
 }
 
 #version {
-  font-weight: bold;
-  color: #909090;
-  margin-top: 1em;
-  -moz-margin-end: 0;
-  margin-bottom: 10px;
-  -moz-margin-start: 17px;
+  margin-top: 5px;
 }
 
-#distribution {
-  font-weight: bold;
-  color: #909090;
-  display: none;
-  margin-top: 0;
-  -moz-margin-end: 0;
-  margin-bottom: 0;
-  -moz-margin-start: 17px;
+#released {
+  color: #666666;
 }
 
+#distribution,
 #distributionId {
   font-weight: bold;
-  color: #909090;
   display: none;
   margin-top: 0;
-  -moz-margin-end: 0;
-  margin-bottom: 10px;
-  -moz-margin-start: 17px;
+  margin-bottom: 0;
 }
 
-#copyright {
-  margin-top: 0;
-  -moz-margin-end: 16px;
-  margin-bottom: 3px;
-  -moz-margin-start: 16px;
+#checkForUpdatesButton,
+.text-blurb {
+  margin-bottom: 10px;
+  -moz-margin-start: 0;
+  -moz-padding-start: 0;
 }
 
-button[dlgtype="extra2"] {
-  -moz-margin-start: 13px;
-}
-
-button[dlgtype="accept"] {
-  -moz-margin-end: 13px;
-}
-
+.version-label,
+.trademark-label,
 .text-link,
 .text-link:focus {
   margin: 0px;
   padding: 0px;
-  border: 0px;
+}
+
+.bottom-link,
+.bottom-link:focus {
+  text-align: center;
+  margin: 0 40px;
 }
+
+#trademark {
+  font-size: xx-small;
+  text-align: center;
+  color: #999999;
+  margin-top: 10px;
+}
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -15,105 +15,87 @@
 #
 # The Initial Developer of the Original Code is
 # Blake Ross (blaker@netscape.com).
 # Portions created by the Initial Developer are Copyright (C) 2002
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
+#   Margaret Leibovic <margaret.leibovic@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 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 ***** -->
 
-var gSelectedPage = 0;
+// Services = object with smart getters for common XPCOM services
+Components.utils.import("resource://gre/modules/Services.jsm");
 
 function init(aEvent)
 {
   if (aEvent.target != document)
     return;
 
-  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
-                        .getService(Components.interfaces.nsIPrefBranch);
+  try {
+    var distroId = Services.prefs.getCharPref("distribution.id");
+    if (distroId) {
+      var distroVersion = Services.prefs.getCharPref("distribution.version");
+      var distroAbout = Services.prefs.getComplexValue("distribution.about",
+        Components.interfaces.nsISupportsString);
 
-  try {
-    var distroId = prefs.getCharPref("distribution.id");
-    if (distroId) {
-      var distroVersion = prefs.getCharPref("distribution.version");
-      var distroAbout = prefs.getComplexValue("distribution.about",
-        Components.interfaces.nsISupportsString);
-  
       var distroField = document.getElementById("distribution");
       distroField.value = distroAbout;
       distroField.style.display = "block";
-    
+
       var distroIdField = document.getElementById("distributionId");
       distroIdField.value = distroId + " - " + distroVersion;
       distroIdField.style.display = "block";
     }
   }
   catch (e) {
     // Pref is unset
   }
 
-  var userAgentField = document.getElementById("userAgent");
-  userAgentField.value = navigator.userAgent;
-
-  var button = document.documentElement.getButton("extra2");
-  button.setAttribute("label", document.documentElement.getAttribute("creditslabel"));
-  button.setAttribute("accesskey", document.documentElement.getAttribute("creditsaccesskey"));
-  button.addEventListener("command", switchPage, false);
-
-  var acceptButton = document.documentElement.getButton("accept");
-#ifdef XP_UNIX
-  acceptButton.setAttribute("icon", "close");
+#ifdef MOZ_UPDATER
+  initUpdates();
 #endif
-  acceptButton.focus();
 
 #ifdef XP_MACOSX
   // it may not be sized at this point, and we need its width to calculate its position
   window.sizeToContent();
   window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5);
 #endif
 }
 
-function uninit(aEvent)
+#ifdef MOZ_UPDATER
+/**
+ * Creates "Last Updated" message and sets up "Check for Updates..." button.
+ */
+function initUpdates()
 {
-  if (aEvent.target != document)
-    return;
-  var iframe = document.getElementById("creditsIframe");
-  iframe.setAttribute("src", "");
-}
-
-function switchPage(aEvent)
-{
-  var button = aEvent.target;
-  if (button.localName != "button")
-    return;
+  var um = Components.classes["@mozilla.org/updates/update-manager;1"].
+           getService(Components.interfaces.nsIUpdateManager);
+  var browserBundle = Services.strings.
+                      createBundle("chrome://browser/locale/browser.properties");
 
-  var iframe = document.getElementById("creditsIframe");
-  if (gSelectedPage == 0) {
-    iframe.setAttribute("src", "chrome://browser/content/credits.xhtml");
-    button.setAttribute("label", document.documentElement.getAttribute("aboutlabel"));
-    button.setAttribute("accesskey", document.documentElement.getAttribute("aboutaccesskey"));
-    gSelectedPage = 1;
+  if (um.updateCount) {
+    let buildID = um.getUpdateAt(0).buildID;
+    let released = browserBundle.formatStringFromName("aboutdialog.released", 
+                                                      [buildID.substring(0, 4), 
+                                                       buildID.substring(4, 6), 
+                                                       buildID.substring(6, 8)], 3);
+    document.getElementById("released").setAttribute("value", released);
   }
-  else {
-    iframe.setAttribute("src", ""); 
-    button.setAttribute("label", document.documentElement.getAttribute("creditslabel"));
-    button.setAttribute("accesskey", document.documentElement.getAttribute("creditsaccesskey"));
-    gSelectedPage = 0;
-  }
-  var modes = document.getElementById("modes");
-  modes.setAttribute("selectedIndex", gSelectedPage);
+
+  var checkForUpdates = document.getElementById("checkForUpdatesButton");
+  setupCheckForUpdates(checkForUpdates, browserBundle);
 }
-
+#endif
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -17,16 +17,17 @@
 #
 # The Initial Developer of the Original Code is
 # Blake Ross (blaker@netscape.com).
 # Portions created by the Initial Developer are Copyright (C) 2002
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
+#   Margaret Leibovic <margaret.leibovic@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
@@ -46,60 +47,67 @@
 <!ENTITY % aboutDialogDTD SYSTEM "chrome://browser/locale/aboutDialog.dtd" >
 %aboutDialogDTD;
 ]>
 
 #ifdef XP_MACOSX
 <?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
 #endif
 
-<dialog xmlns:html="http://www.w3.org/1999/xhtml"
+<window xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="aboutDialog"
         windowtype="Browser:About"
-        onload="init(event);" onunload="uninit(event);"
+        onload="init(event);"
 #ifdef XP_MACOSX
         inwindowmenu="false"
-        buttons="extra2"
-        align="end"
 #else
         title="&aboutDialog.title;"
-        buttons="accept,extra2"
-#ifdef XP_UNIX
-        buttonlabelaccept="&closeCmdGNOME.label;"
-        buttonaccesskeyaccept="&closeCmdGNOME.accesskey;"
 #endif
-#endif
-        creditslabel="&copyright;"
-#ifdef XP_UNIX
-        creditsaccesskey="&copyrightGNOME.accesskey;"
-#else
-        creditsaccesskey="&copyright.accesskey;"
-#endif
-        aboutlabel="&aboutLink;"
-        aboutaccesskey="&aboutLink.accesskey;">
-    
+        >
+
+  <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>
 
-  <deck id="modes" flex="1">
-    <vbox flex="1" id="clientBox">
-#expand <label id="version" value="&aboutVersion; __MOZ_APP_VERSION__"/>
-      <label id="distribution"/>
-      <label id="distributionId"/>
-      <description id="copyright">
-        <label
-        class="text-link" href="about:license"
-        >&licenseLinkText;</label>&licenseLinkSuffix;&trademarkInfo;
+  <vbox>
+    <hbox id="clientBox">
+      <vbox id="leftBox" flex="1"/>
+      <vbox id="rightBox" flex="1">
+        <description id="version">
+#expand <label class="version-label" value="__MOZ_APP_VERSION__"/> <label class="version-label" id="released"/>
+        </description>
+        <label id="distribution" class="text-blurb"/>
+        <label id="distributionId" class="text-blurb"/>
+#ifdef MOZ_UPDATER
+        <hbox>
+          <button id="checkForUpdatesButton" oncommand="checkForUpdates();" align="start"/>
+          <spacer flex="1"/>
+        </hbox>
+#endif
+        <description class="text-blurb">
+          &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
+        </description>
+        <description class="text-blurb">
+          &contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
+        </description>
+      </vbox>
+    </hbox>
+    <vbox id="bottomBox">
+      <hbox pack="center">
+        <label class="text-link bottom-link" href="about:license">&bottomLinks.license;</label>
+        <label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
+        <label class="text-link bottom-link" href="http://www.mozilla.com/legal/privacy/">&bottomLinks.privacy;</label>
+      </hbox>
+      <description id="trademark">
+        <label class="trademark-label">&trademarkInfo.part1;</label>
+        <label class="trademark-label">&trademarkInfo.part2;</label>
       </description>
-      <textbox id="userAgent" multiline="true" readonly="true" flex="1"/>
     </vbox>
-    <vbox flex="1" id="creditsBox">
-      <iframe id="creditsIframe" flex="1"/>
-    </vbox>    
-  </deck>
-  <separator class="groove" id="groove"/>
+  </vbox>
+  
+  <keyset>
+    <key keycode="VK_ESCAPE" oncommand="window.close();"/>
+  </keyset>
 
 #ifdef XP_MACOSX
 #include browserMountPoints.inc
 #endif
-
-</dialog>
-
+</window>
--- a/browser/base/content/aboutHome.css
+++ b/browser/base/content/aboutHome.css
@@ -50,17 +50,18 @@ html {
   margin: 1em auto;
   padding: 25px;
   width: 560px;
 }
 
 #brandStart {
   background: -moz-linear-gradient(top, #42607C, #1E4262 30%, #1E4262 80%, #143552 98%, #244665);
   border-radius: 5.6px;
-  padding-bottom: 0.2em;
+  padding-top: 0.1em;
+  padding-bottom: 0.1em;
   -moz-padding-start: 0.5em;
   font-size: 250%;
   font-weight: bold;
   color: #688196;
   margin-top: 18px;
   margin-bottom: 6px;
 }
 #brandStart > span {
--- a/browser/base/content/aboutHome.js
+++ b/browser/base/content/aboutHome.js
@@ -136,17 +136,16 @@ function loadSnippets()
 {
   // Check last snippets update.
   let lastUpdate = localStorage["snippets-last-update"];
   let updateURL = localStorage["snippets-update-url"];
   if (updateURL && (!lastUpdate ||
                     Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
     // Try to update from network.
     let xhr = new XMLHttpRequest();
-    xhr.mozBackgroundRequest = true;
     xhr.open('GET', updateURL, true);
     xhr.onerror = function (event) {
       showSnippets();
     };
     xhr.onload = function (event)
     {
       if (xhr.status == 200) {
         localStorage["snippets"] = xhr.responseText;
--- a/browser/base/content/baseMenuOverlay.xul
+++ b/browser/base/content/baseMenuOverlay.xul
@@ -104,22 +104,24 @@
                   oncommand="openReleaseNotes()"
                   onclick="checkForMiddleClick(this, event);"/>
         <menuitem id="feedbackPage"
                   accesskey="&helpFeedbackPage.accesskey;"
                   label="&helpFeedbackPage.label;"
                   oncommand="openFeedbackPage()"
                   onclick="checkForMiddleClick(this, event);"/>
         <menuseparator id="updateSeparator"/>
+#ifdef XP_MACOSX
 #ifdef MOZ_UPDATER
         <menuitem id="checkForUpdates"
                   label="&updateCmd.label;"
                   class="menuitem-iconic"
                   oncommand="checkForUpdates();"/>
 #endif
+#endif
         <menuseparator id="aboutSeparator"/>
         <menuitem id="aboutName"
                   accesskey="&aboutProduct.accesskey;"
                   label="&aboutProduct.label;"
                   oncommand="openAboutDialog();"/>
       </menupopup>
     </menu>
 
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -14,10 +14,12 @@
 <!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd">
   %customizeToolbarDTD;
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
 #ifdef MOZ_SAFE_BROWSING
 <!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
 %safebrowsingDTD;
 #endif
+<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
+%aboutHomeDTD;
 ]>
 
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -204,18 +204,18 @@
 #endif
               </menupopup>
             </menu>
 
             <menu id="view-menu" label="&viewMenu.label;"
                   accesskey="&viewMenu.accesskey;">
               <menupopup id="menu_viewPopup">
                 <menuitem id="menu_tabview"
-                          label="&showTabView2.label;"
-                          accesskey="&showTabView2.accesskey;"
+                          label="&viewTabGroups.label;"
+                          accesskey="&viewTabGroups.accesskey;"
                           command="Browser:ToggleTabView"/>
                 <menu id="viewToolbarsMenu"
                       label="&viewToolbarsMenu.label;"
                       accesskey="&viewToolbarsMenu.accesskey;">
                   <menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
                     <menuseparator/>
                     <menuitem id="menu_tabsOnTop"
                               command="cmd_ToggleTabsOnTop"
@@ -508,39 +508,23 @@
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
 #ifdef MOZ_SERVICES_SYNC
               <!-- only one of sync-setup or sync-menu will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSetup.label;"
                         accesskey="&syncSetup.accesskey;"
+                        observes="sync-setup-state"
                         oncommand="gSyncUI.openSetup()"/>
-              <menu id="sync-menu"
-                    label="&syncMenu.label;"
-                    accesskey="&syncMenu.accesskey;">
-                <menupopup id="sync-menu-popup"
-                           onpopupshowing="if (event.target == this) gSyncUI.doUpdateMenu(event);">
-                  <menuitem id="sync-loginitem"
-                            label="&syncLogInItem.label;"
-                            accesskey="&syncLogInItem.accesskey;"
-                            oncommand="gSyncUI.doLogin();"/>
-                  <menuitem id="sync-logoutitem"
-                            label="&syncLogOutItem.label;"
-                            accesskey="&syncLogOutItem.accesskey;"
-                            oncommand="gSyncUI.doLogout();"/>
-                  <menuitem id="sync-syncnowitem"
-                            label="&syncSyncNowItem.label;"
-                            accesskey="&syncSyncNowItem.accesskey;"
-                            oncommand="gSyncUI.doSync(event);"/>
-                  <menuseparator id="sync-lastsyncsep" hidden="true"/>
-                  <menuitem id="sync-lastsyncitem"
-                            disabled="true" hidden="true"/>
-                </menupopup>
-              </menu>
+              <menuitem id="sync-syncnowitem"
+                        label="&syncSyncNowItem.label;"
+                        accesskey="&syncSyncNowItem.accesskey;"
+                        observes="sync-syncnow-state"
+                        oncommand="gSyncUI.doSync(event);"/>
 #endif
               <menuseparator id="devToolsSeparator"/>
               <menuitem id="menu_pageinspect"
                         type="checkbox"
                         hidden="true"
                         label="&inspectMenu.label;"
                         accesskey="&inspectMenu.accesskey;"
                         key="key_inspect"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -187,16 +187,20 @@
                  type="checkbox"
                  oncommand="gPopupBlockerObserver.dontShowMessage();"/>
     <broadcaster id="blockedPopupsSeparator"/>
     <broadcaster id="isImage"/>
     <broadcaster id="isFrameImage"/>
     <broadcaster id="singleFeedMenuitemState" disabled="true"/>
     <broadcaster id="multipleFeedsMenuState" hidden="true"/>
     <broadcaster id="tabviewGroupsNumber" groups="0"/>
+#ifdef MOZ_SERVICES_SYNC
+    <broadcaster id="sync-setup-state"/>
+    <broadcaster id="sync-syncnow-state"/>
+#endif
   </broadcasterset>
 
   <keyset id="mainKeyset">
     <key id="key_newNavigator"
          key="&newNavigatorCmd.key;"
          command="cmd_newNavigator"
          modifiers="accel"/>
     <key id="key_newNavigatorTab" key="&tabCmd.commandkey;" modifiers="accel" command="cmd_newNavigatorTab"/>
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -17,16 +17,17 @@
 # Portions created by the Initial Developer are Copyright (C) 2007
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #  Dan Mills <thunder@mozilla.com>
 #  Chris Beard <cbeard@mozilla.com>
 #  Dan Mosedale <dmose@mozilla.org>
 #  Paul O’Shannessy <paul@oshannessy.com>
+#  Philipp von Weitershausen <philipp@weitershausen.de>
 #
 # 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
@@ -51,16 +52,17 @@ let gSyncUI = {
       Services.obs.removeObserver(gSyncUI, "weave:service:ready");
     }, false);
   },
   initUI: function SUI_initUI() {
     let obs = ["weave:service:sync:start",
                "weave:service:sync:finish",
                "weave:service:sync:error",
                "weave:service:sync:delayed",
+               "weave:service:quota:remaining",
                "weave:service:setup-complete",
                "weave:service:login:start",
                "weave:service:login:finish",
                "weave:service:login:error",
                "weave:service:logout:finish",
                "weave:service:start-over"];
 
     // If this is a browser window?
@@ -98,32 +100,30 @@ let gSyncUI = {
   _isLoggedIn: function() {
     if (this._needsSetup())
       return false;
     return Weave.Service.isLoggedIn;
   },
 
   updateUI: function SUI_updateUI() {
     let needsSetup = this._needsSetup();
-    document.getElementById("sync-setup").hidden = !needsSetup;
-    document.getElementById("sync-menu").hidden = needsSetup;
+    document.getElementById("sync-setup-state").hidden = !needsSetup;
+    document.getElementById("sync-syncnow-state").hidden = needsSetup;
+
+    if (!gBrowser)
+      return;
 
-    if (gBrowser) {
-      let showLabel = !this._isLoggedIn() && !needsSetup;
-      let button = document.getElementById("sync-status-button");
-      button.setAttribute("class", showLabel ? "statusbarpanel-iconic-text"
-                                             : "statusbarpanel-iconic");
-      button.image = "chrome://browser/skin/sync-16.png";
+    let button = document.getElementById("sync-button");
+    if (!button)
+      return;
 
-      if (!this._isLoggedIn()) {
-        //XXXzpao When we move the string bundle, we can add more and make this
-        //        say "needs setup" or something similar. (bug 583381)
-        button.removeAttribute("tooltiptext");
-      }
-    }
+    button.removeAttribute("status");
+    this._updateLastSyncTime();
+    if (needsSetup)
+      button.removeAttribute("tooltiptext");
   },
 
   alltabsPopupShowing: function(event) {
     // Should we show the menu item?
     if (!Weave.Service.isLoggedIn || !Weave.Engines.get("tabs").enabled)
       return;
 
     let label = this._stringBundle.GetStringFromName("tabs.fromOtherComputers.label");
@@ -146,20 +146,24 @@ let gSyncUI = {
 
     popup.insertBefore(sep, popup.firstChild);
     popup.insertBefore(menuitem, sep);
   },
 
 
   // Functions called by observers
   onActivityStart: function SUI_onActivityStart() {
-    //XXXzpao Followup: Do this with a class. (bug 583384)
-    if (gBrowser)
-      document.getElementById("sync-status-button").image =
-        "chrome://browser/skin/sync-16-throbber.png";
+    if (!gBrowser)
+      return;
+
+    let button = document.getElementById("sync-button");
+    if (!button)
+      return;
+
+    button.setAttribute("status", "active");
   },
 
   onSyncFinish: function SUI_onSyncFinish() {
     this._onSyncEnd(true);
   },
 
   onSyncError: function SUI_onSyncError() {
     this._onSyncEnd(false);
@@ -175,17 +179,17 @@ let gSyncUI = {
   },
 
   onLoginFinish: function SUI_onLoginFinish() {
     // Clear out any login failure notifications
     let title = this._stringBundle.GetStringFromName("error.login.title");
     Weave.Notifications.removeAll(title);
 
     this.updateUI();
-    this._updateLastSyncItem();
+    this._updateLastSyncTime();
   },
 
   onLoginError: function SUI_onLoginError() {
     // if login fails, any other notifications are essentially moot
     Weave.Notifications.removeAll();
 
     // if we haven't set up the client, don't show errors
     if (this._needsSetup()) {
@@ -213,16 +217,31 @@ let gSyncUI = {
   onLogout: function SUI_onLogout() {
     this.updateUI();
   },
 
   onStartOver: function SUI_onStartOver() {
     this.updateUI();
   },
 
+  onQuotaNotice: function onQuotaNotice(subject, data) {
+    let title = this._stringBundle.GetStringFromName("warning.sync.quota.label");
+    let description = this._stringBundle.GetStringFromName("warning.sync.quota.description");
+    let buttons = [];
+    buttons.push(new Weave.NotificationButton(
+      this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"),
+      this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"),
+      function() { gSyncUI.openQuotaDialog(); return true; }
+    ));
+
+    let notification = new Weave.Notification(
+      title, description, null, Weave.Notifications.PRIORITY_WARNING, buttons);
+    Weave.Notifications.replaceTitle(notification);
+  },
+
   onNotificationAdded: function SUI_onNotificationAdded() {
     if (!gBrowser)
       return;
 
     let notificationsButton = document.getElementById("sync-notifications-button");
     notificationsButton.hidden = false;
     let notification = Weave.Notifications.notifications.reduce(function(prev, cur) {
       return prev.priority > cur.priority ? prev : cur;
@@ -244,120 +263,116 @@ let gSyncUI = {
     }
     else {
       // Display remaining notifications
       this.onNotificationAdded();
     }
   },
 
   // Commands
-  doUpdateMenu: function SUI_doUpdateMenu(event) {
-    this._updateLastSyncItem();
-
-    let loginItem = document.getElementById("sync-loginitem");
-    let logoutItem = document.getElementById("sync-logoutitem");
-    let syncItem = document.getElementById("sync-syncnowitem");
-
-    // Don't allow "login" to be selected in some cases
-    let offline = Services.io.offline;
-    let locked = Weave.Service.locked;
-    let noUser = Weave.Service.username == "";
-    let notReady = offline || locked || noUser;
-    loginItem.setAttribute("disabled", notReady);
-    logoutItem.setAttribute("disabled", notReady);
-
-    // Don't allow "sync now" to be selected in some cases
-    let loggedIn = Weave.Service.isLoggedIn;
-    let noNode = Weave.Status.sync == Weave.NO_SYNC_NODE_FOUND;
-    let disableSync = notReady || !loggedIn || noNode;
-    syncItem.setAttribute("disabled", disableSync);
-
-    // Only show one of login/logout
-    loginItem.setAttribute("hidden", loggedIn);
-    logoutItem.setAttribute("hidden", !loggedIn);
-  },
-
   doLogin: function SUI_doLogin() {
     Weave.Service.login();
   },
 
   doLogout: function SUI_doLogout() {
     Weave.Service.logout();
   },
 
   doSync: function SUI_doSync() {
-    Weave.Service.sync();
+    if (Weave.Service.isLoggedIn || Weave.Service.login())
+      Weave.Service.sync();
   },
 
-  handleStatusbarButton: function SUI_handleStatusbarButton() {
-    if (Weave.Service.isLoggedIn)
-      Weave.Service.sync();
-    else if (this._needsSetup())
+  handleToolbarButton: function SUI_handleStatusbarButton() {
+    if (this._needsSetup())
       this.openSetup();
     else
-      Weave.Service.login();
+      this.doSync();
   },
 
   //XXXzpao should be part of syncCommon.js - which we might want to make a module...
   //        To be fixed in a followup (bug 583366)
   openSetup: function SUI_openSetup() {
     let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
     if (win)
       win.focus();
     else {
       window.openDialog("chrome://browser/content/syncSetup.xul",
                         "weaveSetup", "centerscreen,chrome,resizable=no");
     }
   },
 
+  openQuotaDialog: function SUI_openQuotaDialog() {
+    let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
+    if (win)
+      win.focus();
+    else 
+      Services.ww.activeWindow.openDialog(
+        "chrome://browser/content/syncQuota.xul", "",
+        "centerscreen,chrome,dialog,modal");
+  },
+
   openPrefs: function SUI_openPrefs() {
     openPreferences("paneSync");
   },
 
 
   // Helpers
-  _updateLastSyncItem: function SUI__updateLastSyncItem() {
+  _updateLastSyncTime: function SUI__updateLastSyncTime() {
+    if (!gBrowser)
+      return;
+
+    let syncButton = document.getElementById("sync-button");
+    if (!syncButton)
+      return;
+
     let lastSync;
     try {
       lastSync = Services.prefs.getCharPref("services.sync.lastSync");
     }
     catch (e) { };
-    if (!lastSync)
+    if (!lastSync || this._needsSetup()) {
+      syncButton.removeAttribute("tooltiptext");
       return;
-
-    let lastSyncItem = document.getElementById("sync-lastsyncitem");
+    }
 
     // Show the day-of-week and time (HH:MM) of last sync
     let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
     let lastSyncLabel =
       this._stringBundle.formatStringFromName("lastSync.label", [lastSyncDate], 1);
-    lastSyncItem.setAttribute("label", lastSyncLabel);
-    lastSyncItem.setAttribute("hidden", "false");
-    document.getElementById("sync-lastsyncsep").hidden = false;
 
-    if (gBrowser)
-      document.getElementById("sync-status-button").
-               setAttribute("tooltiptext", lastSyncLabel);
+    syncButton.setAttribute("tooltiptext", lastSyncLabel);
   },
 
   _onSyncEnd: function SUI__onSyncEnd(success) {
     let title = this._stringBundle.GetStringFromName("error.sync.title");
     if (!success) {
       if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
         this.onLoginError();
         return;
       }
       let error = Weave.Utils.getErrorString(Weave.Status.sync);
       let description =
         this._stringBundle.formatStringFromName("error.sync.description", [error], 1);
 
       let priority = Weave.Notifications.PRIORITY_WARNING;
       let buttons = [];
 
-      if (!Weave.Status.enforceBackoff) {
+      if (Weave.Status.sync == Weave.OVER_QUOTA) {
+        description = this._stringBundle.GetStringFromName(
+          "error.sync.quota.description");
+        buttons.push(new Weave.NotificationButton(
+          this._stringBundle.GetStringFromName(
+            "error.sync.viewQuotaButton.label"),
+          this._stringBundle.GetStringFromName(
+            "error.sync.viewQuotaButton.accesskey"),
+          function() { gSyncUI.openQuotaDialog(); return true; } )
+        );
+      }
+      else if (!Weave.Status.enforceBackoff) {
         priority = Weave.Notifications.PRIORITY_INFO;
         buttons.push(new Weave.NotificationButton(
           this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
           this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
           function() { gSyncUI.doSync(); return true; }
         ));
       }
 
@@ -372,33 +387,36 @@ let gSyncUI = {
 
     if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) {
       title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
       Weave.Notifications.removeAll(title);
       this._wasDelayed = false;
     }
 
     this.updateUI();
-    this._updateLastSyncItem();
+    this._updateLastSyncTime();
   },
   
   observe: function SUI_observe(subject, topic, data) {
     switch (topic) {
       case "weave:service:sync:start":
         this.onActivityStart();
         break;
       case "weave:service:sync:finish":
         this.onSyncFinish();
         break;
       case "weave:service:sync:error":
         this.onSyncError();
         break;
       case "weave:service:sync:delayed":
         this.onSyncDelay();
         break;
+      case "weave:service:quota:remaining":
+        this.onQuotaNotice();
+        break;
       case "weave:service:setup-complete":
         this.onLoginFinish();
         break;
       case "weave:service:login:start":
         this.onActivityStart();
         break;
       case "weave:service:login:finish":
         this.onLoginFinish();
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -131,16 +131,30 @@ let TabView = {
 
   // ----------
   toggle: function() {
     if (this.isVisible())
       this.hide();
     else 
       this.show();
   },
+  
+  getActiveGroupName: function Tabview_getActiveGroupName() {
+    // We get the active group this way, instead of querying
+    // GroupItems.getActiveGroupItem() because the tabSelect event
+    // will not have happened by the time the browser tries to
+    // update the title.
+    let activeTab = window.gBrowser.selectedTab;
+    if (activeTab.tabItem && activeTab.tabItem.parent){
+      let groupName = activeTab.tabItem.parent.getTitle();
+      if (groupName)
+        return groupName;
+    }
+    return null;
+  },  
 
   // ----------
   updateContextMenu: function(tab, popup) {
     let separator = document.getElementById("context_tabViewNamedGroups");
     let isEmpty = true;
 
     while (popup.firstChild && popup.firstChild != separator)
       popup.removeChild(popup.firstChild);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -32,41 +32,35 @@ tabbrowser {
   -moz-transition: min-width .2s ease-out, max-width .25s ease-out;
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   max-width: 1px;
   min-width: 1px;
 }
 
-.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-text,
-.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-icon-image,
-.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-close-button {
+.tab-progress:not([fadein]):not([pinned]),
+.tab-label:not([fadein]):not([pinned]),
+.tab-icon-image:not([fadein]):not([pinned]),
+.tab-close-button:not([fadein]):not([pinned]) {
   opacity: 0 !important;
 }
 
-.tabbrowser-tab > .tab-text,
-.tabbrowser-tab > .tab-icon-image,
-.tabbrowser-tab > .tab-close-button {
+.tab-progress,
+.tab-label,
+.tab-icon-image,
+.tab-close-button {
   -moz-transition: opacity .25s;
 }
 
 .tabbrowser-tab[pinned] {
   position: fixed;
   display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
 }
 
-.tabbrowser-tab[pinned] > .tab-text {
-  display: none;
-}
-
-.tabbrowser-tab[pinned] > .tab-icon-image {
-  vertical-align: middle;
-}
-
 #alltabs-popup {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
 }
 
 toolbar[printpreview="true"] {
   -moz-binding: url("chrome://global/content/printPreviewBindings.xml#printpreviewtoolbar");
 }
 
@@ -143,26 +137,79 @@ toolbar[mode="icons"] > #reload-button[d
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-iconic-tooltip");
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
 }
 
+#urlbar-progress {
+  -moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter");
+}
+
 /* Some child nodes want to be ordered based on the locale's direction, while
    everything else should be ltr. */
-#urlbar:-moz-locale-dir(rtl) > .autocomplete-textbox-container > .textbox-input-box {
+.urlbar-input-box:-moz-locale-dir(rtl) {
   direction: rtl;
 }
 
-#urlbar html|*.autocomplete-textbox {
+html|*.urlbar-input {
   direction: ltr;
 }
 
+/* over-link in location bar */
+
+.urlbar-over-link-layer[overlinkstate="fade-in"],
+.urlbar-textbox-container:not([overlinkstate]) {
+  -moz-transition-property: color;
+  -moz-transition-duration: 150ms;
+  -moz-transition-delay: 50ms;
+  -moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
+}
+
+.urlbar-textbox-container[overlinkstate="fade-in"],
+.urlbar-over-link-layer:not([overlinkstate]) {
+  -moz-transition-property: color;
+  -moz-transition-duration: 150ms;
+  -moz-transition-delay: 50ms;
+  -moz-transition-timing-function: linear;
+  color: transparent;
+}
+
+.urlbar-over-link-box[overlinkstate="fade-in"],
+.urlbar-textbox-container-children:not([overlinkstate]) {
+  -moz-transition-property: opacity;
+  -moz-transition-duration: 150ms;
+  -moz-transition-delay: 50ms;
+  -moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
+  opacity: 1;
+}
+
+.urlbar-textbox-container-children[overlinkstate="fade-in"],
+.urlbar-over-link-box:not([overlinkstate]) {
+  -moz-transition-property: opacity;
+  -moz-transition-duration: 150ms;
+  -moz-transition-delay: 50ms;
+  -moz-transition-timing-function: linear;
+  opacity: 0;
+}
+
+.urlbar-textbox-container[overlinkstate="showing"] {
+  color: transparent;
+}
+
+.urlbar-over-link-box[overlinkstate="showing"] {
+  opacity: 1;
+}
+
+.urlbar-textbox-container-children[overlinkstate="showing"] {
+  opacity: 0;
+}
+
 /* For results that are actions, their description text is shown instead of
    the URL - this needs to follow the locale's direction, unlike URLs. */
 richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
   direction: rtl;
 }
 
 #urlbar:not([actiontype]) > #urlbar-display {
   display: none;
@@ -181,25 +228,16 @@ richlistitem[type~="action"]:-moz-locale
   -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;
 }
 
-#feed-button > .button-box > .box-inherit > .button-text,
-#feed-button > .button-box > .button-menu-dropmarker {
-  display: none;
-}
-
-#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) {
-  direction: rtl;
-}
-
 #urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
 #urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
 #urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,
 #urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton,
 #urlbar[pageproxystate="valid"] > #urlbar-go-button,
 #urlbar:not([focused="true"]) > #urlbar-go-button {
   visibility: collapse;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2322,66 +2322,16 @@ function BrowserPageInfo(doc, initialTab
     }
   }
 
   // We didn't find a matching window, so open a new one.
   return openDialog("chrome://browser/content/pageinfo/pageInfo.xul", "",
                     "chrome,toolbar,dialog=no,resizable", args);
 }
 
-#ifdef DEBUG
-// Initialize the LeakDetector class.
-function LeakDetector(verbose)
-{
-  this.verbose = verbose;
-}
-
-const NS_LEAKDETECTOR_CONTRACTID = "@mozilla.org/xpcom/leakdetector;1";
-
-if (NS_LEAKDETECTOR_CONTRACTID in Components.classes) {
-  try {
-    LeakDetector.prototype = Components.classes[NS_LEAKDETECTOR_CONTRACTID]
-                                       .createInstance(Components.interfaces.nsILeakDetector);
-  } catch (err) {
-    LeakDetector.prototype = Object.prototype;
-  }
-} else {
-  LeakDetector.prototype = Object.prototype;
-}
-
-var leakDetector = new LeakDetector(false);
-
-// Dumps current set of memory leaks.
-function dumpMemoryLeaks()
-{
-  leakDetector.dumpLeaks();
-}
-
-// Traces all objects reachable from the chrome document.
-function traceChrome()
-{
-  leakDetector.traceObject(document, leakDetector.verbose);
-}
-
-// Traces all objects reachable from the content document.
-function traceDocument()
-{
-  // keep the chrome document out of the dump.
-  leakDetector.markObject(document, true);
-  leakDetector.traceObject(content, leakDetector.verbose);
-  leakDetector.markObject(document, false);
-}
-
-// Controls whether or not we do verbose tracing.
-function traceVerbose(verbose)
-{
-  leakDetector.verbose = (verbose == "true");
-}
-#endif
-
 function URLBarSetURI(aURI) {
   var value = gBrowser.userTypedValue;
   var valid = false;
 
   if (value == null) {
     let uri = aURI || getWebNavigation().currentURI;
 
     // Replace initial page URIs with an empty string
@@ -2974,18 +2924,16 @@ function openHomeDialog(aURL)
 
   if (pressedVal == 0) {
     try {
       var str = Components.classes["@mozilla.org/supports-string;1"]
                           .createInstance(Components.interfaces.nsISupportsString);
       str.data = aURL;
       gPrefService.setComplexValue("browser.startup.homepage",
                                    Components.interfaces.nsISupportsString, str);
-      var homeButton = document.getElementById("home-button");
-      homeButton.setAttribute("tooltiptext", aURL);
     } catch (ex) {
       dump("Failed to set the home page.\n"+ex+"\n");
     }
   }
 }
 
 var bookmarksButtonObserver = {
   onDrop: function (aEvent)
@@ -3228,42 +3176,18 @@ const BrowserSearch = {
     var engines = (hidden ? browser.hiddenEngines : browser.engines) || [];
 
     engines.push({ uri: engine.href,
                    title: engine.title,
                    icon: iconURL });
 
     if (hidden)
       browser.hiddenEngines = engines;
-    else {
+    else
       browser.engines = engines;
-      if (browser == gBrowser.selectedBrowser)
-        this.updateSearchButton();
-    }
-  },
-
-  /**
-   * Update the browser UI to show whether or not additional engines are
-   * available when a page is loaded or the user switches tabs to a page that
-   * has search engines.
-   */
-  updateSearchButton: function() {
-    var searchBar = this.searchBar;
-
-    // The search bar binding might not be applied even though the element is
-    // in the document (e.g. when the navigation toolbar is hidden), so check
-    // for .searchButton specifically.
-    if (!searchBar || !searchBar.searchButton)
-      return;
-
-    var engines = gBrowser.selectedBrowser.engines;
-    if (engines && engines.length > 0)
-      searchBar.searchButton.setAttribute("addengines", "true");
-    else
-      searchBar.searchButton.removeAttribute("addengines");
   },
 
   /**
    * Gives focus to the search bar, if it is present on the toolbar, or loads
    * the default engine's search form otherwise. For Mac, opens a new window
    * or focuses an existing window, if necessary.
    */
   webSearch: function BrowserSearch_webSearch() {
@@ -4005,17 +3929,16 @@ function mimeTypeIsTextBased(aMimeType)
 }
 
 var XULBrowserWindow = {
   // Stored Status, Link and Loading values
   status: "",
   defaultStatus: "",
   jsStatus: "",
   jsDefaultStatus: "",
-  overLink: "",
   startTime: 0,
   statusText: "",
   isBusy: false,
 
   _progressCollapseTimer: 0,
 
   QueryInterface: function (aIID) {
     if (aIID.equals(Ci.nsIWebProgressListener) ||
@@ -4024,17 +3947,17 @@ var XULBrowserWindow = {
         aIID.equals(Ci.nsIXULBrowserWindow) ||
         aIID.equals(Ci.nsISupports))
       return this;
     throw Cr.NS_NOINTERFACE;
   },
 
   get statusMeter () {
     delete this.statusMeter;
-    return this.statusMeter = document.getElementById("statusbar-icon");
+    return this.statusMeter = document.getElementById("urlbar-progress");
   },
   get stopCommand () {
     delete this.stopCommand;
     return this.stopCommand = document.getElementById("Browser:Stop");
   },
   get reloadCommand () {
     delete this.reloadCommand;
     return this.reloadCommand = document.getElementById("Browser:Reload");
@@ -4088,26 +4011,26 @@ var XULBrowserWindow = {
     this.updateStatusField();
   },
 
   setDefaultStatus: function (status) {
     this.defaultStatus = status;
     this.updateStatusField();
   },
 
-  setOverLink: function (link, b) {
+  setOverLink: function (link) {
     // Encode bidirectional formatting characters.
     // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
-    this.overLink = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
-                                 encodeURIComponent);
-    this.updateStatusField();
+    link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
+                        encodeURIComponent);
+    gURLBar.setOverLink(link);
   },
 
   updateStatusField: function () {
-    var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
+    var text = this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
 
     // check the current value so we don't trigger an attribute change
     // and cause needless (slow!) UI updates
     if (this.statusText != text) {
       this.statusTextField.label = text;
       this.statusText = text;
     }
   },
@@ -4160,17 +4083,17 @@ var XULBrowserWindow = {
 
         // Turn the status meter on.
         this.statusMeter.value = 0;  // be sure to clear the progress bar
         if (this._progressCollapseTimer) {
           clearTimeout(this._progressCollapseTimer);
           this._progressCollapseTimer = 0;
         }
         else
-          this.statusMeter.parentNode.collapsed = false;
+          this.statusMeter.collapsed = false;
 
         // XXX: This needs to be based on window activity...
         this.stopCommand.removeAttribute("disabled");
         CombinedStopReload.switchToStop();
       }
     }
     else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
       if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
@@ -4224,17 +4147,17 @@ var XULBrowserWindow = {
 
       this.isBusy = false;
 
       if (this._busyUI) {
         this._busyUI = false;
 
         // Turn the progress meter and throbber off.
         this._progressCollapseTimer = setTimeout(function (self) {
-          self.statusMeter.parentNode.collapsed = true;
+          self.statusMeter.collapsed = true;
           self._progressCollapseTimer = 0;
         }, 100, this);
 
         if (this.throbberElement)
           this.throbberElement.removeAttribute("busy");
 
         this.stopCommand.setAttribute("disabled", "true");
         CombinedStopReload.switchToReload(aRequest instanceof Ci.nsIRequest);
@@ -4361,17 +4284,16 @@ var XULBrowserWindow = {
     if (aRequest)
       setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0);
     else
       this.asyncUpdateUI();
   },
 
   asyncUpdateUI: function () {
     FeedHandler.updateFeeds();
-    BrowserSearch.updateSearchButton();
   },
 
   onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
     this.status = aMessage;
     this.updateStatusField();
   },
 
   // Properties used to cache security state used to update the UI
@@ -4996,17 +4918,20 @@ var gHomeButton = {
 
   updateTooltip: function (homeButton)
   {
     if (!homeButton)
       homeButton = document.getElementById("home-button");
     if (homeButton) {
       var homePage = this.getHomePage();
       homePage = homePage.replace(/\|/g,', ');
-      homeButton.setAttribute("tooltiptext", homePage);
+      if (homePage.toLowerCase() == "about:home")
+        homeButton.setAttribute("tooltiptext", homeButton.getAttribute("aboutHomeOverrideTooltip"));
+      else
+        homeButton.setAttribute("tooltiptext", homePage);
     }
   },
 
   getHomePage: function ()
   {
     var url;
     try {
       url = gPrefService.getComplexValue(this.prefDomain,
@@ -6700,33 +6625,17 @@ function convertFromUnicode(charset, str
 }
 
 /**
  * The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
  * and shows UI when they are discovered.
  */
 var FeedHandler = {
   /**
-   * The click handler for the Feed icon in the location bar. Opens the
-   * subscription page if user is not given a choice of feeds.
-   * (Otherwise the list of available feeds will be presented to the
-   * user in a popup menu.)
-   */
-  onFeedButtonClick: function(event) {
-    event.stopPropagation();
-
-    if (event.target.hasAttribute("feed") &&
-        event.eventPhase == Event.AT_TARGET &&
-        (event.button == 0 || event.button == 1)) {
-        this.subscribeToFeed(null, event);
-    }
-  },
-
-  /**
-   * Called when the user clicks on the Feed icon in the location bar.
+   * Called when the user clicks on the Subscribe to This Page... menu item.
    * Builds a menu of unique feeds associated with the page, and if there
    * is only one, shows the feed inline in the browser window.
    * @param   menuPopup
    *          The feed list menupopup to be populated.
    * @returns true if the menu should be shown, false if there was only
    *          one feed and the feed should be shown inline in the browser
    *          window (do not show the menupopup).
    */
@@ -6741,23 +6650,16 @@ var FeedHandler = {
       // refuses to work past this point.
       menuPopup.parentNode.removeAttribute("open");
       return false;
     }
 
     while (menuPopup.firstChild)
       menuPopup.removeChild(menuPopup.firstChild);
 
-    if (feeds.length == 1) {
-      var feedButton = document.getElementById("feed-button");
-      if (feedButton)
-        feedButton.setAttribute("feed", feeds[0].href);
-      return false;
-    }
-
     // Build the menu showing the available feed choices for viewing.
     for (var i = 0; i < feeds.length; ++i) {
       var feedInfo = feeds[i];
       var menuItem = document.createElement("menuitem");
       var baseTitle = feedInfo.title || feedInfo.href;
       var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
       menuItem.setAttribute("class", "feed-menuitem");
       menuItem.setAttribute("label", labelStr);
@@ -6819,40 +6721,26 @@ var FeedHandler = {
     return this._feedMenupopup = document.getElementById("multipleFeedsMenuState");
   },
 
   /**
    * Update the browser UI to show whether or not feeds are available when
    * a page is loaded or the user switches tabs to a page that has feeds.
    */
   updateFeeds: function() {
-    var feedButton = document.getElementById("feed-button");
-
     var feeds = gBrowser.selectedBrowser.feeds;
     if (!feeds || feeds.length == 0) {
-      if (feedButton) {
-        feedButton.collapsed = true;
-        feedButton.removeAttribute("feed");
-      }
       this._feedMenuitem.setAttribute("disabled", "true");
       this._feedMenupopup.setAttribute("hidden", "true");
       this._feedMenuitem.removeAttribute("hidden");
     } else {
-      if (feedButton)
-        feedButton.collapsed = false;
-
       if (feeds.length > 1) {
         this._feedMenuitem.setAttribute("hidden", "true");
         this._feedMenupopup.removeAttribute("hidden");
-        if (feedButton)
-          feedButton.removeAttribute("feed");
       } else {
-        if (feedButton)
-          feedButton.setAttribute("feed", feeds[0].href);
-
         this._feedMenuitem.setAttribute("feed", feeds[0].href);
         this._feedMenuitem.removeAttribute("disabled");
         this._feedMenuitem.removeAttribute("hidden");
         this._feedMenupopup.setAttribute("hidden", "true");
       }
     }
   },
 
@@ -6863,22 +6751,16 @@ var FeedHandler = {
       // ignore feeds loaded in subframes (see bug 305472)
       return;
     }
 
     if (!browserForLink.feeds)
       browserForLink.feeds = [];
 
     browserForLink.feeds.push({ href: link.href, title: link.title });
-
-    if (browserForLink == gBrowser.selectedBrowser) {
-      var feedButton = document.getElementById("feed-button");
-      if (feedButton)
-        feedButton.collapsed = false;
-    }
   }
 };
 
 /**
  * Re-open a closed tab.
  * @param aIndex
  *        The index of the tab (via nsSessionStore.getClosedTabData)
  * @returns a reference to the reopened tab.
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -111,35 +111,35 @@
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.reloadAllTabs();"/>
       <menuseparator/>
-      <menuitem id="context_openTabInWindow" label="&openTabInNewWindow.label;"
-                accesskey="&openTabInNewWindow.accesskey;"
-                tbattr="tabbrowser-multiple"
-                oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
       <menuitem id="context_pinTab" label="&pinAppTab.label;"
                 accesskey="&pinAppTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_unpinTab" label="&unpinAppTab.label;" hidden="true"
                 accesskey="&unpinAppTab.accesskey;"
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
       <menu id="context_tabViewMenu" label="&moveToGroup.label;"
             accesskey="&moveToGroup.accesskey;">
         <menupopup id="context_tabViewMenuPopup"
                    onpopupshowing="if (event.target == this) TabView.updateContextMenu(TabContextMenu.contextTab, this);">
           <menuseparator id="context_tabViewNamedGroups" hidden="true"/>
           <menuitem label="&moveToNewGroup.label;"
                     oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
         </menupopup>
       </menu>
+      <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
+                accesskey="&moveToNewWindow.accesskey;"
+                tbattr="tabbrowser-multiple"
+                oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
       <menuseparator/>
       <menuitem id="context_bookmarkAllTabs"
                 label="&bookmarkAllTabs.label;"
                 accesskey="&bookmarkAllTabs.accesskey;"
                 command="Browser:BookmarkAllTabs"/>
       <menuseparator/>
       <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
                 oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
@@ -410,17 +410,17 @@
         <spacer flex="1"/>
         <toolbarbutton class="KUI-panel-closebutton"
                        oncommand="allTabs.close()"
                        tooltiptext="&closeCmd.label;"/>
       </hbox>
       <stack id="allTabs-stack">
         <vbox id="allTabs-container"><hbox/></vbox>
         <toolbarbutton id="allTabs-tab-close-button"
-                       class="tab-close-button"
+                       class="tabs-closebutton"
                        oncommand="allTabs.closeTab(event);"
                        tooltiptext="&closeCmd.label;"
                        style="visibility:hidden"/>
       </stack>
     </panel>
 
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
@@ -436,20 +436,28 @@
   </popupset>
 
 #ifdef MENUBAR_CAN_AUTOHIDE
   <vbox id="titlebar">
   <hbox id="titlebar-content">
   <hbox id="appmenu-button-container" align="start">
   <button id="appmenu-button"
           type="menu"
+#ifdef XP_WIN
           label="&brandShortName;"
+#else
+          label="&appMenuButton.label;"
+#endif
           style="-moz-user-focus: ignore;">
     <menupopup id="appmenu-popup"
+#ifdef MOZ_SERVICES_SYNC
+               onpopupshowing="updateEditUIVisibility();gSyncUI.updateUI();">
+#else
                onpopupshowing="updateEditUIVisibility();">
+#endif
       <hbox>
         <vbox id="appmenuPrimaryPane">
           <hbox flex="1"
                 class="split-menuitem">
             <menuitem id="appmenu_newTab"
                       class="menuitem-tooltip split-menuitem-item"
                       flex="1"
                       label="&tabCmd.label;"
@@ -755,16 +763,28 @@
                             onclick="checkForMiddleClick(this, event);"/>
                   <menuseparator/>
                   <menuitem id="appmenu_about"
                             label="&aboutProduct.label;"
                             oncommand="openAboutDialog();"/>
                 </menupopup>
               </menu>
             </hbox>
+#ifdef MOZ_SERVICES_SYNC
+            <spacer flex="1"/>
+            <!-- only one of sync-setup or sync-syncnow will be showing at once -->
+            <menuitem id="sync-setup-appmenu"
+                      label="&syncSetup.label;"
+                      observes="sync-setup-state"
+                      oncommand="gSyncUI.openSetup()"/>
+            <menuitem id="sync-syncnowitem-appmenu"
+                      label="&syncSyncNowItem.label;"
+                      observes="sync-syncnow-state"
+                      oncommand="gSyncUI.doSync(event);"/>
+#endif
         </vbox>
       </hbox>
     </menupopup>
   </button>
   </hbox>
   <spacer id="titlebar-spacer" flex="1"/>
   <hbox id="titlebar-buttonbox">
     <toolbarbutton id="titlebar-min" oncommand="window.minimize();"/>
@@ -851,17 +871,18 @@
 
       <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      persist="class" removable="true"
                      label="&homeButton.label;"
                      ondragover="homeButtonObserver.onDragOver(event)"
                      ondragenter="homeButtonObserver.onDragOver(event)"
                      ondrop="homeButtonObserver.onDrop(event)"
                      ondragleave="homeButtonObserver.onDragLeave(event)"
-                     onclick="BrowserGoHome(event);"/>
+                     onclick="BrowserGoHome(event);"
+                     aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
 
       <toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true"
                    title="&locationItem.title;" class="chromeclass-location" removable="true">
         <textbox id="urlbar" flex="1"
                  placeholder="&urlbar.placeholder;"
                  type="autocomplete"
                  autocompletesearch="history"
                  autocompletesearchparam="enable-actions"
@@ -906,37 +927,25 @@
               <hbox id="identity-icon-labels">
                 <label id="identity-icon-label" class="plain" flex="1"/>
                 <label id="identity-icon-country-label" class="plain"/>
               </hbox>
             </hbox>
           </box>
           <label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
           <hbox id="urlbar-icons">
-            <button type="menu"
-                    style="-moz-user-focus: none"
-                    class="plain urlbar-icon"
-                    id="feed-button"
-                    collapsed="true"
-                    tooltiptext="&feedButton.tooltip;"
-                    onclick="return FeedHandler.onFeedButtonClick(event);">
-              <menupopup position="after_end"
-                         id="feed-menu"
-                         onpopupshowing="return FeedHandler.buildFeedList(this);"
-                         oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                         onclick="checkForMiddleClick(this, event);"/>
-            </button>
             <image id="star-button"
                    class="urlbar-icon"
                    onclick="PlacesStarButton.onClick(event);"/>
             <image id="go-button"
                    class="urlbar-icon"
                    tooltiptext="&goEndCap.tooltip;"
                    onclick="gURLBar.handleCommand(event);"/>
           </hbox>
+          <progressmeter id="urlbar-progress" mode="normal"/>
           <toolbarbutton id="urlbar-go-button"
                          onclick="gURLBar.handleCommand(event);"
                          tooltiptext="&goEndCap.tooltip;"/>
           <toolbarbutton id="urlbar-reload-button"
                          command="Browser:ReloadOrDuplicate"
                          onclick="checkForMiddleClick(this, event);"
                          tooltiptext="&reloadButton.tooltip;"/>
           <toolbarbutton id="urlbar-stop-button"
@@ -980,16 +989,29 @@
                      context="placesContext"
                      openInTabs="children"
                      oncommand="BookmarksEventHandler.onCommand(event);"
                      onclick="BookmarksEventHandler.onClick(event);"
                      onpopupshowing="BookmarksMenuButton.onPopupShowing(event);
                                      if (!this.parentNode._placesView)
                                        new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
                      tooltip="bhTooltip" popupsinherittooltip="true">
+            <menuitem id="BMB_subscribeToPageMenuitem"
+                      label="&subscribeToPageMenuitem.label;"
+                      oncommand="return FeedHandler.subscribeToFeed(null, event);"
+                      onclick="checkForMiddleClick(this, event);"
+                      observes="singleFeedMenuitemState"/>
+            <menu id="BMB_subscribeToPageMenupopup"
+                  label="&subscribeToPageMenupopup.label;"
+                  observes="multipleFeedsMenuState">
+              <menupopup id="BMB_subscribeToPageSubmenuMenupopup"
+                         onpopupshowing="return FeedHandler.buildFeedList(event.target);"
+                         oncommand="return FeedHandler.subscribeToFeed(null, event);"
+                         onclick="checkForMiddleClick(this, event);"/>
+            </menu>
             <menuitem id="BMB_bookmarkAllTabs"
                       label="&addCurPagesCmd.label;"
                       command="Browser:BookmarkAllTabs"
                       key="bookmarkAllTabsKb"/>
             <menuitem id="BMB_bookmarksShowAll"
                       label="&showAllBookmarks.label;"
                       command="Browser:ShowAllBookmarks"
                       key="manBookmarkKb"/>
@@ -1133,19 +1155,19 @@
                      label="&listAllTabs.label;"
                      tooltiptext="&listAllTabs.label;"
                      removable="true">
         <menupopup id="alltabs-popup"
                    position="after_end"/>
       </toolbarbutton>
 
       <toolbarbutton id="tabview-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&tabViewButton2.label;"
+                     label="&tabGroupsButton.label;"
                      command="Browser:ToggleTabView"
-                     tooltiptext="&tabViewButton2.tooltip;"
+                     tooltiptext="&tabGroupsButton.tooltip;"
                      removable="true"
                      observes="tabviewGroupsNumber"/>
 
       <toolbarbutton id="tabs-closebutton"
                      class="close-button tabs-closebutton"
                      command="cmd_close"
                      label="&closeTab.label;"
                      tooltiptext="&closeTab.label;"/>
@@ -1223,17 +1245,22 @@
                        label="&fullZoomReduceCmd.label;"
                        command="cmd_fullZoomReduce"
                        tooltiptext="&zoomOutButton.tooltip;"/>
         <toolbarbutton id="zoom-in-button" class="toolbarbutton-1"
                        label="&fullZoomEnlargeCmd.label;"
                        command="cmd_fullZoomEnlarge"
                        tooltiptext="&zoomInButton.tooltip;"/>
       </toolbaritem>
-
+#ifdef MOZ_SERVICES_SYNC
+      <toolbarbutton id="sync-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     label="&syncToolbarButton.label;"
+                     oncommand="gSyncUI.handleToolbarButton()"/>
+#endif
     </toolbarpalette>
   </toolbox>
 
   <hbox flex="1" id="browser">
     <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
       <sidebarheader id="sidebar-header" align="center">
         <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
         <image id="sidebar-throbber"/>
@@ -1256,34 +1283,23 @@
 
   <vbox id="browser-bottombox" layer="true">
     <statusbar class="chromeclass-status" id="status-bar"
 #ifdef WINCE
                hidden="true"
 #endif
                >
       <statusbarpanel id="statusbar-display" label="" flex="1"/>
-      <statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
-        <progressmeter class="progressmeter-statusbar" id="statusbar-icon" mode="normal" value="0"/>
-      </statusbarpanel>
       <statusbarpanel id="download-monitor" class="statusbarpanel-iconic-text"
                       tooltiptext="&downloadMonitor2.tooltip;" hidden="true"
                       command="Tools:Downloads"/>
       <statusbarpanel id="security-button" class="statusbarpanel-iconic"
                       hidden="true"
                       onclick="if (event.button == 0 &amp;&amp; event.detail == 1) displaySecurityInfo();"/>
 #ifdef MOZ_SERVICES_SYNC
-      <statusbarpanel id="sync-status-button"
-                      class="statusbarpanel-iconic"
-                      image="chrome://browser/skin/sync-16.png"
-                      label="&syncLogInItem.label;"
-                      oncommand="gSyncUI.handleStatusbarButton();"
-                      onmousedown="event.preventDefault();">
-      </statusbarpanel>
-      <separator class="thin"/>
       <statusbarpanel id="sync-notifications-button"
                       class="statusbarpanel-iconic-text"
                       hidden="true"
                       popup="sync-notifications-panel">
       </statusbarpanel>
       <panel id="sync-notifications-panel" position="before_end">
           <notificationbox id="sync-notifications-box"/>
       </panel>
deleted file mode 100644
--- a/browser/base/content/credits.xhtml
+++ /dev/null
@@ -1,648 +0,0 @@
-<!-- -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Firefox Credits.
-#
-# The Initial Developer of the Original Code is Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2004
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#   David Baron <dbaron@mozilla.org>
-#   Ehsan Akhgari <ehsan.akhgari@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 *****
--->
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-                      "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
-  [
-    <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-    %brandDTD;
-    <!ENTITY % creditsDTD SYSTEM "chrome://browser/locale/credits.dtd">
-    %creditsDTD;
-    <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
-    %globalDTD;
-  ]
->
-
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>&brandFullName; Credits</title>
-
-    <style>
-      html {
-        background-color: white;
-      }
-
-      * {
-        cursor: default;
-        -moz-user-select: none;
-      }
-
-      #titleBox {
-        position: fixed;
-        left: 0px;
-        top: 0px;
-        right: 0px;
-        bottom: auto;
-        z-index: 999;
-      }
-
-      #footerBox {
-        position: fixed;
-        left: 0px;
-        top: auto;
-        right: 0px;
-        bottom: 0px;
-        z-index: 999;
-      }
-
-      #creditsBox {
-        position: absolute;
-        left: 0px;
-        top: 0px;
-        bottom: 8px;
-        overflow: hidden;
-        z-index: 1;
-        width: 280px;
-        margin-left: 10px;
-        margin-right: 10px;
-        font-family: Arial, sans-serif;
-        font-size: small;
-      }
-
-      h3 {
-        font-weight: bold;
-        font-size: small;
-        text-align: center;
-        margin: 15px 0px 5px 0px;
-      }
-
-      .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;
-      }
-
-      .links {
-        font-weight: normal;
-        font-size: small;
-        font-style: italic;
-        text-align: center;
-        margin: 0px 0px 100px 0px;
-      }
-
-      .motto {
-        margin-top: 2px;
-        font-style: italic;
-        font-size: small;
-        font-weight: normal;
-        padding-left: 2em;
-      }
-
-      #gecko {
-        margin-top:    100px;
-        margin-bottom: 100px;
-        font-size: medium;
-      }
-
-      a {
-        color: blue;
-        text-decoration: underline;
-      }
-
-      ul {
-        margin-top: 0px;
-        margin-left: 0px;
-        padding-left: 0px;
-      }
-
-      li {
-        list-style-type: none;
-      }
-
-      .center {
-        text-align: center;
-      }
-    </style>
-
-    <script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
-    <script type="application/javascript">
-    <![CDATA[
-
-      var gCreditsInterval = -1;
-
-      function uninit()
-      {
-        if (gCreditsInterval > -1)
-          clearInterval(gCreditsInterval);
-      }
-
-      function init()
-      {
-        var cb = document.getElementById("creditsBox");
-        cb.scrollTop = 0;
-        setTimeout(runCredits, 3000);
-      }
-
-      function runCredits()
-      {
-        gCreditsInterval = setInterval("creditsCallback()", 25);
-      }
-
-      function creditsCallback()
-      {
-        var cb = document.getElementById("creditsBox");
-        var newtop = cb.scrollTop + 1;
-        cb.scrollTop = newtop;
-        if (cb.scrollTop != newtop) {
-          // we're at the bottom
-          clearInterval(gCreditsInterval);
-          setTimeout(function() { cb.scrollTop = 0 }, 10000);
-        }
-      }
-
-    ]]>
-    </script>
-  </head>
-  <body onload="init();" onunload="uninit();">
-    <div id="titleBox">
-      <img src="chrome://branding/content/aboutCredits.png" />
-    </div>
-
-    <div id="creditsBox">
-        <h2 class="title" dir="&locale.dir;">&brandFullName;&trade;
-          <div class="motto">&brandMotto;</div>
-        </h2>
-        <div class="links" dir="&locale.dir;">
-          &credit.thanks2; <a href="" link="about:credits" onclick="visitLink(event);">&credit.contributors2;</a>
-        </div>
-
-        <div class="creditsGroup">
-          <ul>
-            <li>Josh Aas</li>
-            <li>Robert Accettura</li>
-            <li>Lucas Adamski</li>
-            <li>Raymond Etornam Agbeame</li>
-            <li>Ehsan Akhgari</li>
-            <li>Sean Alamares</li>
-            <li>Pedro Alves</li>
-            <li>David Anderson</li>
-            <li>Harvey Anderson</li>
-            <li>Smokey Ardisson</li>
-            <li>Rob Arnold</li>
-            <li>Tomoya Asai</li>
-            <li>Chris AtLee</li>
-            <li>Dietrich Ayala</li>
-            <li>Mitchell Baker</li>
-            <li>Rhian Baker</li>
-            <li>Jeff Balogh</li>
-            <li>Jan Bambas</li>
-            <li>Rey Bango</li>
-            <li>Mark Banner</li>
-            <li>Jason Barnabe</li>
-            <li>David Baron</li>
-            <li>Colin Barrett</li>
-            <li>Curtis Bartley</li>
-            <li>Bo Bayles</li>
-            <li>Christopher Beard</li>
-            <li>Glen Beasley</li>
-            <li>Juan Becerra</li>
-            <li>Brian Behlendorf</li>
-            <li>Mike Beltzner</li>
-            <li>Mic Berman</li>
-            <li>Uri Bernstein</li>
-            <li>Christian Biesinger</li>
-            <li>Al Billings</li>
-            <li>Seth Bindernagel</li>
-            <li>Lukas Blakk</li>
-            <li>Jim Blandy</li>
-            <li>Chris Blizzard</li>
-            <li>Jamey Boje</li>
-            <li>David Bolter</li>
-            <li>Nelson Bolyard</li>
-            <li>Marco Bonardo</li>
-            <li>Carsten Book</li>
-            <li>Paul Booker</li>
-            <li>Jennifer Boriss</li>
-            <li>Dan Born</li>
-            <li>Arpad Borsos</li>
-            <li>David Boswell</li>
-            <li>Ondřej Brablc</li>
-            <li>Catherine Brady</li>
-            <li>Dave Bragsalla</li>
-            <li>Alex Buchanan</li>
-            <li>Igor Bukanov</li>
-            <li>Simon Bünzli</li>
-            <li>Lapo Calamandrei</li>
-            <li>Dave Camp</li>
-            <li>Rob Campbell</li>
-            <li>Regis Caspar</li>
-            <li>Garrett Casto</li>
-            <li>Tony Chang</li>
-            <li>Wan-Teh Chang</li>
-            <li>Emily Chen</li>
-            <li>Ginn Chen</li>
-            <li>Pascal Chevrel</li>
-            <li>Adam Christian</li>
-            <li>Tony Chung</li>
-            <li>Bob Clary</li>
-            <li>Wil Clouser</li>
-            <li>Mary Colvig</li>
-            <li>Majken Connor</li>
-            <li>Mike Connor</li>
-            <li>Chris Cooper</li>
-            <li>Eric Cooper</li>
-            <li>Paul Craciunoiu</li>
-            <li>Brian Crowder</li>
-            <li>John Daggett</li>
-            <li>David Dahl</li>
-            <li>Michael Davis</li>
-            <li>Neil Deakin</li>
-            <li>Julie Deroche</li>
-            <li>Aakash Desai</li>
-            <li>Ryan Doherty</li>
-            <li>Justin Dolske</li>
-            <li>Stephen Donner</li>
-            <li>Asa Dotzler</li>
-            <li>Chris Double</li>
-            <li>Joe Drew</li>
-            <li>Jason Duell</li>
-            <li>Karsten Düsterloh</li>
-            <li>Brendan Eich</li>
-            <li>Daniel Einspanjer</li>
-            <li>Kai Engert</li>
-            <li>Steve England</li>
-            <li>Madhava Enros</li>
-            <li>Behdad Esfahbod</li>
-            <li>Elika Etemad</li>
-            <li>Anthony Evans</li>
-            <li>Jason Evans</li>
-            <li>Alex Faaborg</li>
-            <li>Jane Finette</li>
-            <li>Mark Finkle</li>
-            <li>Darin Fisher</li>
-            <li>Jayson Fittipaldi</li>
-            <li>Justin Fitzhugh</li>
-            <li>Ryan Flint</li>
-            <li>Alix Franquet</li>
-            <li>Eli Friedman</li>
-            <li>Andreas Gal</li>
-            <li>Steven Garrity</li>
-            <li>Armen Zambrano Gasparnian</li>
-            <li>Serge Gautherie</li>
-            <li>Kevin Gerich</li>
-            <li>Taras Glek</li>
-            <li>Aravind Gottipati</li>
-            <li>Dão Gottwald</li>
-            <li>Zak Greant</li>
-            <li>Matthew Gregan</li>
-            <li>Will Guaraldi</li>
-            <li>Adam Guthrie</li>
-            <li>Mohammad Reza Haghighat</li>
-            <li>Andrei Hajdukewycz</li>
-            <li>Trevor Hardcastle</li>
-            <li>Basil Hashem</li>
-            <li>Ian Hayward</li>
-            <li>Ben Hearsum</li>
-            <li>Axel Hecht</li>
-            <li>Frank Hecker</li>
-            <li>Robert Helmer</li>
-            <li>Stefan Hermes</li>
-            <li>Jon Hicks</li>
-            <li>Graydon Hoare</li>
-            <li>Chris Hofmann</li>
-            <li>Timothy Hogan</li>
-            <li>Daniel Holbert</li>
-            <li>Bobby Holley</li>
-            <li>Mike Hommey</li>
-            <li>Stephen Horlander</li>
-            <li>Barbara Hueppe</li>
-            <li>Anthony Hughes</li>
-            <li>David Humphrey</li>
-            <li>Takeshi Ichimaru</li>
-            <li>Chris Ilias</li>
-            <li>Eri Inoue</li>
-            <li>Joichi Ito</li>
-            <li>Steven Johnson</li>
-            <li>Laurent Jouanneau</li>
-            <li>Robert Kaiser</li>
-            <li>Gen Kanai</li>
-            <li>Masanori Kaneko</li>
-            <li>Blake Kaplan</li>
-            <li>Mike Kaplinskiy</li>
-            <li>Michael Kaply</li>
-            <li>Mitch Kapor</li>
-            <li>Kazuyoshi Kato</li>
-            <li>Tomomi Kato</li>
-            <li>Alfred Kayser</li>
-            <li>Jonathan Kew</li>
-            <li>Paul Kim</li>
-            <li>Masatoshi Kimura</li>
-            <li>Austin King</li>
-            <li>Ria Klaassen</li>
-            <li>Marcia Knous</li>
-            <li>Nelson Ko</li>
-            <li>Michael Kohler</li>
-            <li>Gary Kwong</li>
-            <li>David Lanham</li>
-            <li>Brad Lassey</li>
-            <li>Delphine Lebédel</li>
-            <li>Edward Lee</li>
-            <li>Neil Lee</li>
-            <li>Raymond Lee</li>
-            <li>Garrett LeSage</li>
-            <li>Aaron Leventhal</li>
-            <li>Anne-Julie Ligneau</li>
-            <li>John Lilly</li>
-            <li>Zach Lipton</li>
-            <li>Kai Liu</li>
-            <li>Reed Loden</li>
-            <li>Lars Lohn</li>
-            <li>Robert Longson</li>
-            <li>Bob Lord</li>
-            <li>Phil Machalski</li>
-            <li>Joel Maher</li>
-            <li>Ere Maijala</li>
-            <li>David Mandelin</li>
-            <li>Gervase Markham</li>
-            <li>Sean Martell</li>
-            <li>Jim Mathies</li>
-            <li>Blair McBride</li>
-            <li>Erica McClure</li>
-            <li>Graeme McCutcheon</li>
-            <li>Patrick McManus</li>
-            <li>Heather Meeker</li>
-            <li>Walter Meinl</li>
-            <li>Myk Melez</li>
-            <li>Federico Mena-Quintero</li>
-            <li>Mark Mentovai</li>
-            <li>Laura Mesa</li>
-            <li>Steven Michaud</li>
-            <li>Matthew Middleton</li>
-            <li>Ted Mielczarek</li>
-            <li>Bernd Mielke</li>
-            <li>Dave Miller</li>
-            <li>Dan Mills</li>
-            <li>Michael Monreal</li>
-            <li>Simon Montagu</li>
-            <li>Derek Moore</li>
-            <li>Mike Morgan</li>
-            <li>Tiffney Mortensen</li>
-            <li>Dan Mosedale</li>
-            <li>Michael Moy</li>
-            <li>Jeff Muizelaar</li>
-            <li>Masayuki Nakano</li>
-            <li>Murali Nandigama</li>
-            <li>Marria Nazif</li>
-            <li>Kev Needham</li>
-            <li>Kaori Negoro</li>
-            <li>Nicholas Nethercote</li>
-            <li>Ben Newman</li>
-            <li>Nick Nguyen</li>
-            <li>Johnathan Nightingale</li>
-            <li>Timothy Nikkel</li>
-            <li>Andreas Nilsson</li>
-            <li>Tristan Nitot</li>
-            <li>Alice Nodelman</li>
-            <li>Matthew Noorenberghe</li>
-            <li>Michal Novotny</li>
-            <li>Robert O'Callahan</li>
-            <li>John O'Duinn</li>
-            <li>Paul O'Shannessy</li>
-            <li>Jan Odvárko</li>
-            <li>Tomoyuki Okazaki</li>
-            <li>Les Orchard</li>
-            <li>Jeremy Orem</li>
-            <li>Jason Orendorff</li>
-            <li>Hideo Oshima</li>
-            <li>Mats Palmgren</li>
-            <li>Stuart Parmenter</li>
-            <li>Jay Patel</li>
-            <li>Chris Pearce</li>
-            <li>Javier Pedemonte</li>
-            <li>Alfred Peng</li>
-            <li>Christian Persch</li>
-            <li>Kalle Persson</li>
-            <li>Ulisse Perusin</li>
-            <li>Olli Pettay</li>
-            <li>Julien Pierre</li>
-            <li>Anthony Piraino</li>
-            <li>Alex Polvi</li>
-            <li>Nickolay Ponomarev</li>
-            <li>Dan Portillo</li>
-            <li>Karen Prescott</li>
-            <li>Florian Quèze</li>
-            <li>Krupa Raj</li>
-            <li>Arun Ranganathan</li>
-            <li>Neil Rashbrook</li>
-            <li>Bret Reckard</li>
-            <li>J. Paul Reed</li>
-            <li>Rick Reitmaier</li>
-            <li>Robert Relyea</li>
-            <li>John Resig</li>
-            <li>Deb Richardson</li>
-            <li>Tim Riley</li>
-            <li>Phil Ringnalda</li>
-            <li>Julien Rivaud</li>
-            <li>Mikeal Rogers</li>
-            <li>David Rolnitzky</li>
-            <li>Asaf Romano</li>
-            <li>Oleg Romashin</li>
-            <li>Paul Rouget</li>
-            <li>Tim Rowley</li>
-            <li>Jesse Ruderman</li>
-            <li>Brian Ryner</li>
-            <li>Alexander Sack</li>
-            <li>Hideo Saito</li>
-            <li>Atsushi Sakai</li>
-            <li>Eiko Sakuma</li>
-            <li>Andrei Saprykin</li>
-            <li>Aki Sasaki</li>
-            <li>Ken Saunders</li>
-            <li>Robert Sayre</li>
-            <li>Mike Schroepfer</li>
-            <li>Kurt Schultz</li>
-            <li>Keith Schwarz</li>
-            <li>Justin Scott</li>
-            <li>Hiroshi Sekiya</li>
-            <li>Tara Shahian</li>
-            <li>Melissa Shapiro</li>
-            <li>Gavin Sharp</li>
-            <li>Mike Shaver</li>
-            <li>Eric Shepherd</li>
-            <li>Hiroshi Shimoda</li>
-            <li>Atsushi Shimono</li>
-            <li>Jungshik Shin</li>
-            <li>Jonas Sicking</li>
-            <li>Damon Sicore</li>
-            <li>Roger B. Sidje</li>
-            <li>Samuel Sidler</li>
-            <li>Henrik Skupin</li>
-            <li>John Slater</li>
-            <li>Benjamin Smedberg</li>
-            <li>Andrew Smith</li>
-            <li>Edwin Smith</li>
-            <li>Mark Smith</li>
-            <li>Window Snyder</li>
-            <li>Josh Soref</li>
-            <li>Nochum Sossonko</li>
-            <li>Ian Spence</li>
-            <li>Seth Spitzer</li>
-            <li>Markus Stange</li>
-            <li>Jakub Steiner</li>
-            <li>Johnny Stenback</li>
-            <li>Brandon Sterne</li>
-            <li>Rob Stradling</li>
-            <li>Robert Strong</li>
-            <li>Jay Sullivan</li>
-            <li>Vicky Sun</li>
-            <li>Alexander Surkov</li>
-            <li>Mark Surman</li>
-            <li>Andrew Sutherland</li>
-            <li>Clint Talbert</li>
-            <li>Margaret Tallman</li>
-            <li>David Tenser</li>
-            <li>Chris Thomas</li>
-            <li>Nick Thomas</li>
-            <li>Laura Thomson</li>
-            <li>Karl Tomlinson</li>
-            <li>Dave Townsend</li>
-            <li>Aaron Train</li>
-            <li>Phong Tran</li>
-            <li>Ben Turner</li>
-            <li>Doug Turner</li>
-            <li>Amié Tyrrel</li>
-            <li>Peter Van der Beken</li>
-            <li>Peter van der Woude</li>
-            <li>Teune van Steeg</li>
-            <li>Ryan VanderMeulen</li>
-            <li>Daniel Veditz</li>
-            <li>Michael Ventnor</li>
-            <li>Alexei Volkov</li>
-            <li>Vladimir Vukićević</li>
-            <li>Håkan Waara</li>
-            <li>Jeff Walden</li>
-            <li>Tracy Walker</li>
-            <li>Cheng Wang</li>
-            <li>Martijn Wargers</li>
-            <li>Jonathan Watt</li>
-            <li>Peter Weilbacher</li>
-            <li>Zack Weinberg</li>
-            <li>Frédéric Wenzel</li>
-            <li>Steffen Wilberg</li>
-            <li>Drew Willcoxon</li>
-            <li>Shawn Wilsher</li>
-            <li>Kathleen Wilson</li>
-            <li>Dan Witte</li>
-            <li>John Wolfe</li>
-            <li>Steve Won</li>
-            <li>Justin Wood</li>
-            <li>Michael Wu</li>
-            <li>Masahiro Yamada</li>
-            <li>Satoko Takita Yamaguchi (Chibi)</li>
-            <li>Christine Yen</li>
-            <li>Kohei Yoshino</li>
-            <li>Shigeru Yoshitake</li>
-            <li>Tanner M. Young</li>
-            <li>Boris Zbarsky</li>
-            <li>Marco Zehe</li>
-            <li>Matthew Zeier</li>
-          </ul>
-
-          <div dir="&locale.dir;">
-            &credit.translation;
-          </div>
-        </div>
-
-        <!-- organizational supporters -->
-        <div class="creditsGroup">
-          <h3 dir="&locale.dir;">&credit.thanks;</h3>
-          <ul>
-            <li>Google</li>
-            <li>Yahoo!</li>
-            <li>IBM</li>
-            <li>Sun Microsystems</li>
-            <li>Red Hat</li>
-            <li></li>
-            <li>Oregon State University - Open Source Lab</li>
-            <li></li>
-            <li>Global Netoptex, Inc</li>
-            <li>Internet Software Consortium</li>
-            <li></li>
-            <li>Cooley Godward, LLP</li>
-            <li>Greenburg Traurig, LLP</li>
-            <li></li>
-            <li>OutCast Communications</li>
-            <li></li>
-            <li>The Royal Order of Experience Design</li>
-            <li>Nobox</li>
-            <li>silverorange</li>
-            <li>Glaxstar</li>
-            <li></li>
-            <li>MozillaZine Community</li>
-          </ul>
-        </div>
-
-        <p id="gecko" class="center" dir="&locale.dir;">&credit.poweredByGeckoReg;</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. 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
-          Software with only those rights set forth herein.</p>
-
-    </div>
-
-    <div id="footerBox">
-      <img src="chrome://branding/content/aboutFooter.png" />
-    </div>
-  </body>
-</html>
-
--- a/browser/base/content/syncGenericChange.js
+++ b/browser/base/content/syncGenericChange.js
@@ -100,17 +100,17 @@ let Change = {
         else {
           let pp = Weave.Service.passphrase;
           if (pp.length == 20)
             pp = gSyncUtils.hyphenatePassphrase(pp);
           document.getElementById("passphraseBox").value = pp;
           document.title = this._str("change.synckey.title");
           introText.innerHTML = this._str("change.synckey.introText");
           introText2.innerHTML = this._str("change.synckey.introText2");
-          warningText.innerHTML = this._str("change.synckey.warningText");
+          warningText.innerHTML = this._str("change.synckey2.warningText");
           this._dialog.getButton("accept")
               .setAttribute("label", this._str("change.synckey.acceptButton"));
         }
         break;
       case "ChangePassword":
         document.getElementById("passphraseRow").hidden = true;
         document.getElementById("passphraseBackupButtons").hidden = true;
         let box1label = document.getElementById("textBox1Label");
@@ -122,17 +122,17 @@ let Change = {
           introText.textContent = this._str("new.password.introText");
           this._dialog.getButton("accept")
               .setAttribute("label", this._str("new.password.acceptButton"));
           document.getElementById("textBox2Row").hidden = true;
         }
         else {
           document.title = this._str("change.password.title");
           box2label.value = this._str("new.password.confirm");
-          introText.textContent = this._str("change.password.introText");
+          introText.textContent = this._str("change.password2.introText");
           warningText.textContent = this._str("change.password.warningText");
           this._dialog.getButton("accept")
               .setAttribute("label", this._str("change.password.acceptButton"));
         }
         break;
     }
   },
 
@@ -176,30 +176,30 @@ let Change = {
     this._dialog.getButton("accept").disabled = false;
   },
 
   doChangePassphrase: function Change_doChangePassphrase() {
     let pp = gSyncUtils.normalizePassphrase(this._passphraseBox.value);
     if (this._updatingPassphrase) {
       Weave.Service.passphrase = pp;
       if (Weave.Service.login()) {
-        this._updateStatus("change.synckey.success", "success");
+        this._updateStatus("change.synckey2.success", "success");
         Weave.Service.persistLogin();
       }
       else {
         this._updateStatus("new.passphrase.status.incorrect", "error");
       }
     }
     else {
       this._updateStatus("change.synckey.label", "active");
 
       if (Weave.Service.changePassphrase(pp))
-        this._updateStatus("change.synckey.success", "success");
+        this._updateStatus("change.synckey2.success", "success");
       else
-        this._updateStatus("change.synckey.error", "error");
+        this._updateStatus("change.synckey2.error", "error");
     }
 
     return false;
   },
 
   doChangePassword: function Change_doChangePassword() {
     if (this._currentPasswordInvalid) {
       Weave.Service.password = this._firstBox.value;
--- a/browser/base/content/syncKey.xhtml
+++ b/browser/base/content/syncKey.xhtml
@@ -35,28 +35,49 @@
 # 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 html [
   <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
   %htmlDTD;
-  <!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
-  %syncSetupDTD;
+  <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
+  %syncBrandDTD;
+  <!ENTITY % syncKeyDTD SYSTEM "chrome://browser/locale/syncKey.dtd">
+  %syncKeyDTD;
 ]>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-  <title>&page.syncKeyBackup.title;</title>
+  <title>&syncKey.page.title;</title>
   <style type="text/css">
     #synckey { font-size: 150% }
+    footer { font-size: 70% }
+# Bug 575675: Need to have an a:visited rule in a chrome document.
+    a:visited { color: purple; }
   </style>
 </head>
 
 <body>
-<h1>&page.syncKeyBackup.title;</h1>
+<h1>&syncKey.page.title;</h1>
 
 <p id="synckey">SYNCKEY</p>
 
-<p>&page.syncKeyBackup.descr;</p>
+<p>&syncKey.page.description;</p>
+
+<div id="column1">
+  <h2>&syncKey.keepItSecret.heading;</h2>
+  <p>&syncKey.keepItSecret.description;</p>
+</div>
+
+<div id="column2">
+  <h2>&syncKey.keepItSafe.heading;</h2>
+  <p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4.description;</p>
+</div>
+
+<p>&syncKey.findOutMore1.label;<a href="https://services.mozilla.com">https://services.mozilla.com</a>&syncKey.findOutMore2.label;</p>
+
+<footer>
+ &syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label;
+</footer>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/syncQuota.js
@@ -0,0 +1,282 @@
+/* ***** 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 Firefox Sync.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Philipp von Weitershausen <philipp@weitershausen.de>
+ *
+ * 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 ***** */
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://services-sync/main.js");
+Cu.import("resource://gre/modules/DownloadUtils.jsm");
+
+let gSyncQuota = {
+
+  init: function init() {
+    this.bundle = document.getElementById("quotaStrings");
+    let caption = document.getElementById("treeCaption");
+    caption.firstChild.nodeValue = this.bundle.getString("quota.treeCaption.label");
+
+    gUsageTreeView.init();
+    this.tree = document.getElementById("usageTree");
+    this.tree.view = gUsageTreeView;
+
+    this.loadData();
+  },
+
+  loadData: function loadData() {
+    window.setTimeout(function() {
+      let usage = Weave.Service.getCollectionUsage();
+      gUsageTreeView.displayUsageData(usage);
+    }, 0);
+
+    let usageLabel = document.getElementById("usageLabel");
+    let bundle = this.bundle;
+    window.setTimeout(function() {
+      let quota = Weave.Service.getQuota();
+      if (!quota) {
+        usageLabel.value = bundle.getString("quota.usageError.label");
+        return;
+      }
+      let used = gSyncQuota.convertKB(quota[0]);
+      if (!quota[1]) {
+        // No quota on the server.
+        usageLabel.value = bundle.getFormattedString(
+          "quota.usageNoQuota.label", used);
+        return;
+      }
+      let percent = Math.round(100 * quota[0] / quota[1]);
+      let total = gSyncQuota.convertKB(quota[1]);
+      usageLabel.value = bundle.getFormattedString(
+        "quota.usagePercentage.label", [percent].concat(used).concat(total));
+    }, 0);
+  },
+
+  onAccept: function onAccept() {
+    let engines = gUsageTreeView.getEnginesToDisable();
+    for each (let engine in engines) {
+      Weave.Engines.get(engine).enabled = false;
+    }
+    if (engines.length) {
+      // The 'Weave' object will disappear once the window closes.
+      let Service = Weave.Service;
+      Weave.Utils.delay(function() Service.sync(), 0);
+    }
+    return true;
+  },
+
+  convertKB: function convertKB(value) {
+    return DownloadUtils.convertByteUnits(value * 1024);
+  }
+
+};
+
+let gUsageTreeView = {
+
+  _ignored: {keys: true,
+             meta: true,
+             clients: true},
+
+  /*
+   * Internal data structures underlaying the tree.
+   */
+  _collections: [],
+  _byname: {},
+
+  init: function init() {
+    let retrievingLabel = gSyncQuota.bundle.getString("quota.retrieving.label");
+    for each (let engine in Weave.Engines.getEnabled()) {
+      if (this._ignored[engine.name])
+        continue;
+
+      // Some engines use the same pref, which means they can only be turned on
+      // and off together. We need to combine them here as well.
+      let existing = this._byname[engine.prefName];
+      if (existing) {
+        existing.engines.push(engine.name);
+        continue;
+      }
+
+      let obj = {name: engine.prefName,
+                 title: this._collectionTitle(engine),
+                 engines: [engine.name],
+                 enabled: true,
+                 sizeLabel: retrievingLabel};
+      this._collections.push(obj);
+      this._byname[engine.prefName] = obj;
+    }
+  },
+
+  _collectionTitle: function _collectionTitle(engine) {
+    try {
+      return gSyncQuota.bundle.getString(
+        "collection." + engine.prefName + ".label");
+    } catch (ex) {
+      return engine.Name;
+    }
+  },
+
+  /*
+   * Process the quota information as returned by info/collection_usage.
+   */
+  displayUsageData: function displayUsageData(data) {
+    data = data || {};
+    for each (let coll in this._collections) {
+      coll.size = 0;
+      for each (let engineName in coll.engines)
+        coll.size += data[engineName] || 0;
+      let sizeLabel = "";
+      if (coll.size)
+        sizeLabel = gSyncQuota.bundle.getFormattedString(
+          "quota.sizeValueUnit.label", gSyncQuota.convertKB(coll.size));
+      coll.sizeLabel = sizeLabel;
+    }
+    let sizeColumn = this.treeBox.columns.getNamedColumn("size");
+    this.treeBox.invalidateColumn(sizeColumn);
+  },
+
+  /*
+   * Handle click events on the tree.
+   */
+  onTreeClick: function onTreeClick(event) {
+    if (event.button == 2)
+      return;
+
+    let row = {}, col = {};
+    this.treeBox.getCellAt(event.clientX, event.clientY, row, col, {});
+    if (col.value && col.value.id == "enabled")
+      this.toggle(row.value);
+  },
+
+  /*
+   * Toggle enabled state of an engine.
+   */
+  toggle: function toggle(row) {
+    // Update the tree
+    let collection = this._collections[row];
+    collection.enabled = !collection.enabled;
+    this.treeBox.invalidateRow(row);
+
+    // Display which ones will be removed 
+    let freeup = 0;
+    let toremove = [];
+    for each (collection in this._collections) {
+      if (collection.enabled)
+        continue;
+      toremove.push(collection.name);
+      freeup += collection.size;
+    }
+
+    let caption = document.getElementById("treeCaption");
+    if (!toremove.length) {
+      caption.className = "";
+      caption.firstChild.nodeValue = gSyncQuota.bundle.getString(
+        "quota.treeCaption.label");
+      return;
+    }
+
+    toremove = [this._byname[coll].title for each (coll in toremove)];
+    toremove = toremove.join(gSyncQuota.bundle.getString("quota.list.separator"));
+    caption.firstChild.nodeValue = gSyncQuota.bundle.getFormattedString(
+      "quota.removal.label", [toremove]);
+    if (freeup)
+      caption.firstChild.nodeValue += gSyncQuota.bundle.getFormattedString(
+        "quota.freeup.label", gSyncQuota.convertKB(freeup));
+    caption.className = "captionWarning";
+  },
+
+  /*
+   * Return a list of engines (or rather their pref names) that should be
+   * disabled.
+   */
+  getEnginesToDisable: function getEnginesToDisable() {
+    return [coll.name for each (coll in this._collections) if (!coll.enabled)];
+  },
+
+  // nsITreeView
+
+  get rowCount() {
+    return this._collections.length;
+  },
+
+  getRowProperties: function(index, properties) {},
+  getCellProperties: function(row, col, properties) {},
+  getColumnProperties: function(col, properties) {},
+  isContainer: function(index) { return false; },
+  isContainerOpen: function(index) { return false; },
+  isContainerEmpty: function(index) { return false; },
+  isSeparator: function(index) { return false; },
+  isSorted: function() { return false; },
+  canDrop: function(index, orientation, dataTransfer) { return false; },
+  drop: function(row, orientation, dataTransfer) {},
+  getParentIndex: function(rowIndex) {},
+  hasNextSibling: function(rowIndex, afterIndex) { return false; },
+  getLevel: function(index) { return 0; },
+  getImageSrc: function(row, col) {},
+
+  getCellValue: function(row, col) {
+    return this._collections[row].enabled;
+  },
+
+  getCellText: function getCellText(row, col) {
+    let collection = this._collections[row];
+    switch (col.id) {
+      case "collection":
+        return collection.title;
+      case "size":
+        return collection.sizeLabel;
+      default:
+        return "";
+    }
+  },
+
+  setTree: function setTree(tree) {
+    this.treeBox = tree;
+  },
+
+  toggleOpenState: function(index) {},
+  cycleHeader: function(col) {},
+  selectionChanged: function() {},
+  cycleCell: function(row, col) {},
+  isEditable: function(row, col) { return false; },
+  isSelectable: function (row, col) { return false; },
+  setCellValue: function(row, col, value) {},
+  setCellText: function(row, col, value) {},
+  performAction: function(action) {},
+  performActionOnRow: function(action, row) {},
+  performActionOnCell: function(action, row, col) {}
+
+};
new file mode 100644
--- /dev/null
+++ b/browser/base/content/syncQuota.xul
@@ -0,0 +1,97 @@
+<?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 Firefox Sync.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Philipp von Weitershausen <philipp@weitershausen.de>
+#
+# 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 *****
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/syncQuota.css"?>
+
+<!DOCTYPE dialog [
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
+<!ENTITY % syncQuotaDTD SYSTEM "chrome://browser/locale/syncQuota.dtd">
+%brandDTD;
+%syncBrandDTD;
+%syncQuotaDTD;
+]>
+<dialog id="quotaDialog"
+        windowtype="Sync:ViewQuota"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns:html="http://www.w3.org/1999/xhtml"
+        onload="gSyncQuota.init()"
+        buttons="accept,cancel"
+        title="&quota.dialogTitle.label;"
+        ondialogcancel="return true;"
+        ondialogaccept="return gSyncQuota.onAccept();">
+
+  <script type="application/javascript"
+          src="chrome://browser/content/syncQuota.js"/>
+
+  <stringbundleset id="stringbundleset">
+    <stringbundle id="quotaStrings"
+                  src="chrome://browser/locale/syncQuota.properties"/>
+  </stringbundleset>
+
+  <vbox flex="1">
+    <label id="usageLabel"
+           value="&quota.retrievingInfo.label;"/>
+    <separator/>
+    <tree id="usageTree"
+          seltype="single"
+          hidecolumnpicker="true"
+          onclick="gUsageTreeView.onTreeClick(event);"
+          flex="1">
+      <treecols>
+        <treecol id="enabled"
+                 type="checkbox"
+                 fixed="true"/>
+        <splitter class="tree-splitter"/>
+        <treecol id="collection"
+                 label="Type"
+                 flex="1"/>
+        <splitter class="tree-splitter"/>
+        <treecol id="size"
+                 label="Size"
+                 flex="1"/>
+      </treecols>
+      <treechildren flex="1"/>
+    </tree>
+    <separator/>
+    <description id="treeCaption"> </description>
+  </vbox>
+
+</dialog>
--- a/browser/base/content/syncSetup.js
+++ b/browser/base/content/syncSetup.js
@@ -66,17 +66,16 @@ var gSyncSetup = {
                                          Ci.nsISupportsWeakReference]),
 
   captchaBrowser: null,
   wizard: null,
   _disabledSites: [],
   _remoteSites: [Weave.Service.serverURL, "https://api-secure.recaptcha.net"],
 
   status: {
-    username: false,
     password: false,
     email: false,
     server: false
   },
   _haveSyncKeyBackup: false,
 
   get _usingMainServers() {
     if (this._settingUpNew)
@@ -216,56 +215,69 @@ var gSyncSetup = {
         }
         if (this._usingMainServers)
           return document.getElementById("tos").checked;
 
         return true;
       case NEW_ACCOUNT_PP_PAGE:
         return this._haveSyncKeyBackup && this.checkPassphrase();
       case EXISTING_ACCOUNT_LOGIN_PAGE:
-        let hasUser = document.getElementById("existingUsername").value != "";
+        let hasUser = document.getElementById("existingAccountName").value != "";
         let hasPass = document.getElementById("existingPassword").value != "";
         if (hasUser && hasPass) {
           if (this._usingMainServers)
             return true;
 
           if (this._validateServer(document.getElementById("existingServerURL"), false))
             return true;
         }
         return false;
       case EXISTING_ACCOUNT_PP_PAGE:
         return document.getElementById("existingPassphrase").value != "";
     }
     // we probably shouldn't get here
     return true;
   },
 
-  onUsernameChange: function () {
-    let feedback = document.getElementById("usernameFeedbackRow");
-    let val = document.getElementById("weaveUsername").value;
-    let availCheck = "", str = "";
-    let available = true;
-    if (val) {
-      availCheck = Weave.Service.checkUsername(val);
-      available = availCheck == "available";
+  onEmailChange: function () {
+    let value = document.getElementById("weaveEmail").value;
+    if (!value) {
+      this.status.email = false;
+      this.checkFields();
+      return;
+    }
+    // Do this async to avoid blocking the widget while we go to the server.
+    window.setTimeout(function() {
+      gSyncSetup.checkAccount(value);
+    }, 0);
+  },
+
+  checkAccount: function(value) {
+    let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+    let feedback = document.getElementById("emailFeedbackRow");
+    let valid = re.test(value);
+
+    let str = "";
+    if (!valid) {
+      str = "invalidEmail.label";
+    } else {
+      let availCheck = Weave.Service.checkAccount(value);
+      valid = availCheck == "available";
+      if (!valid) {
+        if (availCheck == "notAvailable")
+          str = "usernameNotAvailable.label";
+        else
+          str = availCheck;
+      }
     }
 
-    if (!available) {
-      if (availCheck == "notAvailable")
-        str = "usernameNotAvailable.label";
-      else
-        str = availCheck;
-    }
-
-    this._setFeedbackMessage(feedback, available, str);
-
-    this.status.username = val && available;
-    if (available)
-      Weave.Service.username = val;
-
+    this._setFeedbackMessage(feedback, valid, str);
+    this.status.email = valid;
+    if (valid)
+      Weave.Service.account = value;
     this.checkFields();
   },
 
   onPasswordChange: function () {
     let password = document.getElementById("weavePassword");
     let valid, str;
     if (password.value == document.getElementById("weavePassphrase").value) {
       // xxxmpc - hack, sigh
@@ -279,32 +291,29 @@ var gSyncSetup = {
 
     let feedback = document.getElementById("passwordFeedbackRow");
     this._setFeedback(feedback, valid, errorString);
 
     this.status.password = valid;
     this.checkFields();
   },
 
-  onEmailChange: function () {
-    //XXXzpao Not sure about this regex. Look into it in followup (bug 583650)
-    let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
-    this.status.email = re.test(document.getElementById("weaveEmail").value);
+  onPassphraseChange: function () {
+    // Ignore if there's no actual change from the generated one.
+    let el = document.getElementById("weavePassphrase");
+    if (gSyncUtils.normalizePassphrase(el.value) == Weave.Service.passphrase) {
+      el = document.getElementById("generatePassphraseButton");
+      el.hidden = true;
+      this._haveCustomSyncKey = false;
+      return;
+    }
 
-    this._setFeedbackMessage(document.getElementById("emailFeedbackRow"),
-                             this.status.email,
-                             "invalidEmail.label");
-
-    this.checkFields();
-  },
-
-  onPassphraseChange: function () {
     this._haveSyncKeyBackup = true;
     this._haveCustomSyncKey = true;
-    let el = document.getElementById("generatePassphraseButton");
+    el = document.getElementById("generatePassphraseButton");
     el.hidden = false;
     this.checkFields();
   },
 
   onPassphraseGenerate: function () {
     let passphrase = gSyncUtils.generatePassphrase();
     Weave.Service.passphrase = passphrase;
     let el = document.getElementById("weavePassphrase");
@@ -415,27 +424,26 @@ var gSyncSetup = {
         // Display throbber
         let feedback = document.getElementById("captchaFeedback");
         let image = feedback.firstChild;
         let label = image.nextSibling;
         image.setAttribute("status", "active");
         label.value = this._stringBundle.GetStringFromName("verifying.label");
         feedback.hidden = false;
 
-        let username = document.getElementById("weaveUsername").value;
         let password = document.getElementById("weavePassword").value;
         let email    = document.getElementById("weaveEmail").value;
         let challenge = getField("challenge");
         let response = getField("response");
 
-        let error = Weave.Service.createAccount(username, password, email,
+        let error = Weave.Service.createAccount(email, password,
                                                 challenge, response);
 
         if (error == null) {
-          Weave.Service.username = username;
+          Weave.Service.account = email;
           Weave.Service.password = password;
           this._handleNoScript(false);
           this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
           return false;
         }
 
         image.setAttribute("status", "error");
         label.value = Weave.Utils.getErrorString(error);
@@ -444,17 +452,17 @@ var gSyncSetup = {
         if (this._haveCustomSyncKey)
           Weave.Service.passphrase = document.getElementById("weavePassphrase").value;
         // Time to load the captcha.
         // First check for NoScript and whitelist the right sites.
         this._handleNoScript(true);
         this.captchaBrowser.loadURI(Weave.Service.miscAPI + "captcha_html");
         break;
       case EXISTING_ACCOUNT_LOGIN_PAGE:
-        Weave.Service.username = document.getElementById("existingUsername").value;
+        Weave.Service.account = document.getElementById("existingAccountName").value;
         Weave.Service.password = document.getElementById("existingPassword").value;
         Weave.Service.passphrase = document.getElementById("existingPassphrase").value;
         // verifyLogin() will likely return false because we probably don't
         // have a passphrase yet (unless the user already entered it
         // and hit the back button).
         if (!Weave.Service.verifyLogin()
             && Weave.Status.login != Weave.LOGIN_FAILED_NO_PASSPHRASE
             && Weave.Status.login != Weave.LOGIN_FAILED_INVALID_PASSPHRASE) {
@@ -617,19 +625,19 @@ var gSyncSetup = {
         valid = this._validateServer(el, true);
         let str = valid ? "" : "serverInvalid.label";
         this._setFeedbackMessage(feedback, valid, str);
       }
       else
         this._setFeedbackMessage(feedback, true);
     }
 
-    // recheck username against the new server
+    // Recheck account against the new server.
     if (valid)
-      this.onUsernameChange();
+      this.onEmailChange();
 
     this.status.server = valid;
     this.checkFields();
   },
 
   // xxxmpc - checkRemote is a hack, we can't verify a minimal server is live
   // without auth, so we won't validate in the existing-server case.
   _validateServer: function (element, checkRemote) {
@@ -641,17 +649,17 @@ var gSyncSetup = {
     let uri = Weave.Utils.makeURI(val);
 
     if (!uri)
       uri = Weave.Utils.makeURI("https://" + val);
 
     if (uri && checkRemote) {
       function isValid(uri) {
         Weave.Service.serverURL = uri.spec;
-        let check = Weave.Service.checkUsername("a");
+        let check = Weave.Service.checkAccount("a");
         return (check == "available" || check == "notAvailable");
       }
 
       if (uri.schemeIs("http")) {
         uri.scheme = "https";
         if (isValid(uri))
           valid = true;
         else
@@ -716,39 +724,39 @@ var gSyncSetup = {
               ")/1000000 " +
             ")/86400) AS daysOfHistory ");
 
         if (stm.step())
           daysOfHistory = stm.getInt32(0);
         document.getElementById("historyCount").value =
           PluralForm.get(daysOfHistory,
                          this._stringBundle.GetStringFromName("historyDaysCount.label"))
-                             .replace("#1", daysOfHistory);
+                             .replace("%S", daysOfHistory);
 
         // bookmarks
         let bookmarks = 0;
         stm = db.createStatement(
           "SELECT count(*) AS bookmarks " +
           "FROM moz_bookmarks b " +
           "LEFT JOIN moz_bookmarks t ON " +
           "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
         stm.params.tag = Weave.Svc.Bookmark.tagsFolder;
         if (stm.executeStep())
           bookmarks = stm.row.bookmarks;
         document.getElementById("bookmarkCount").value =
           PluralForm.get(bookmarks,
                          this._stringBundle.GetStringFromName("bookmarksCount.label"))
-                             .replace("#1", bookmarks);
+                             .replace("%S", bookmarks);
 
         // passwords
         let logins = Weave.Svc.Login.getAllLogins({});
         document.getElementById("passwordCount").value =
           PluralForm.get(logins.length,
                          this._stringBundle.GetStringFromName("passwordsCount.label"))
-                             .replace("#1", logins.length);
+                             .replace("%S", logins.length);
         this._case1Setup = true;
         break;
       case 2:
         if (this._case2Setup)
           break;
         let count = 0;
         function appendNode(label) {
           let box = document.getElementById("clientList");
@@ -766,17 +774,17 @@ var gSyncSetup = {
           // Only show the first several client names
           if (++count <= 5)
             appendNode(name);
         }
         if (count > 5) {
           let label =
             PluralForm.get(count - 5,
                            this._stringBundle.GetStringFromName("additionalClientCount.label"))
-                               .replace("#1", count - 5);
+                               .replace("%S", count - 5);
           appendNode(label);
         }
         this._case2Setup = true;
         break;
     }
 
     return true;
   },
--- a/browser/base/content/syncSetup.xul
+++ b/browser/base/content/syncSetup.xul
@@ -102,26 +102,24 @@
               onextra1="gSyncSetup.onSyncOptions()"
               onpageshow="gSyncSetup.onPageShow();">
     <grid>
       <columns>
         <column/>
         <column class="inputColumn" flex="1"/>
       </columns>
       <rows>
-        <row id="usernameRow" align="center">
-          <label value="&signIn.username.label;"
-                 accesskey="&signIn.username.accesskey;"
-                 control="weaveUsername"/>
-          <textbox id="weaveUsername"
-                   onchange="gSyncSetup.onUsernameChange()"/>
+        <row id="emailRow" align="center">
+          <label value="&setup.emailAddress.label;"
+                 accesskey="&setup.emailAddress.accesskey;"
+                 control="weaveEmail"/>
+          <textbox id="weaveEmail"
+                   onchange="gSyncSetup.onEmailChange()"/>
         </row>
-        <row id="usernameFeedbackRow"
-              align="center"
-              hidden="true">
+        <row id="emailFeedbackRow" align="center" hidden="true">
           <spacer/>
           <hbox>
             <image class="statusIcon"/>
             <label class="status" value=" "/>
           </hbox>
         </row>
         <row id="passwordRow" align="center">
           <label value="&signIn.password.label;"
@@ -141,30 +139,16 @@
         </row>
         <row id="passwordFeedbackRow" align="center" hidden="true">
           <spacer/>
           <hbox>
             <image class="statusIcon"/>
             <label class="status" value=" "/>
           </hbox>
         </row>
-        <row id="emailRow" align="center">
-          <label value="&setup.emailAddress.label;"
-                 accesskey="&setup.emailAddress.accesskey;"
-                 control="weaveEmail"/>
-          <textbox id="weaveEmail"
-                   onchange="gSyncSetup.onEmailChange()"/>
-        </row>
-        <row id="emailFeedbackRow" align="center" hidden="true">
-          <spacer/>
-          <hbox>
-            <image class="statusIcon"/>
-            <label class="status" value=" "/>
-          </hbox>
-        </row>
         <row align="center">
           <label control="serverType"
                  value="&server.label;"/>
           <menulist id="serverType" oncommand="gSyncSetup.onServerChange()">
             <menupopup>
               <menuitem label="&serverType.main.label;"
                         value="main"/>
               <menuitem label="&serverType.custom.label;"
@@ -303,26 +287,26 @@
           <row id="existingServerRow" hidden="true" align="center">
             <label id="existingServerURLLabel"
                    value="&signIn.serverURL.label;"
                    accesskey="&signIn.serverURL.accesskey;"
                    control="existingServerURL"/>
             <textbox id="existingServerURL"
                      onchange="gSyncSetup.checkFields(event)"/>
           </row>
-          <row id="existingUsernameRow" align="center">
-            <label id="existingUsernameLabel"
-                   value="&signIn.username.label;"
-                   accesskey="&signIn.username.accesskey;"
-                   control="existingUsername"/>
-            <textbox id="existingUsername"
+          <row id="existingAccountRow" align="center">
+            <label id="existingAccountLabel"
+                   value="&signIn.account.label;"
+                   accesskey="&signIn.account.accesskey;"
+                   control="existingAccount"/>
+            <textbox id="existingAccountName"
                      oninput="gSyncSetup.checkFields(event)"
                      onchange="gSyncSetup.checkFields(event)"/>
           </row>
-          <row id="existingUsernameFeedbackRow" align="center" hidden="true">
+          <row id="existingAccountFeedbackRow" align="center" hidden="true">
             <spacer/>
             <hbox>
               <image class="statusIcon"/>
               <label class="status" value=" "/>
             </hbox>
           </row>
           <row id="existingPasswordRow" align="center">
             <label id="existingPasswordLabel"
--- a/browser/base/content/syncUtils.js
+++ b/browser/base/content/syncUtils.js
@@ -148,19 +148,29 @@ let gSyncUtils = {
 
   /**
    * Trigger the mailto protocol handler to send a passphrase backup email.
    * 
    * @param elid : ID of the form element containing the passphrase.
    */
   passphraseEmail: function(elid) {
     let pp = document.getElementById(elid).value;
-    let subject = this.bundle.GetStringFromName("email.synckey.subject");
-    let body = this.bundle.formatStringFromName("email.synckey.body", [pp], 1);
-    let uri = Weave.Utils.makeURI("mailto:?subject=" + subject + "&body=" + body);
+    let subject = this.bundle.GetStringFromName("email.syncKey.subject");
+    let label = this.bundle.formatStringFromName("email.syncKey.label", [pp], 1);
+    let body = "&body=" + label + "%0A%0A" +
+               this.bundle.GetStringFromName("email.syncKey.description")
+               + "%0A%0A" +
+               this.bundle.GetStringFromName("email.keepItSecret.label") +
+               this.bundle.GetStringFromName("email.keepItSecret.description")
+               + "%0A%0A" +
+               this.bundle.GetStringFromName("email.keepItSafe.label") +
+               this.bundle.GetStringFromName("email.keepItSafe.description")
+               + "%0A%0A" +
+               this.bundle.GetStringFromName("email.findOutMore.label");
+    let uri = Weave.Utils.makeURI("mailto:?subject=" + subject + body);
     let protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
                      .getService(Ci.nsIExternalProtocolService);
     protoSvc.loadURI(uri);
   },
 
   /**
    * Prepare an invisible iframe with the passphrase backup document.
    * Used by both the print and saving methods.
@@ -178,16 +188,27 @@ let gSyncUtils = {
     document.documentElement.appendChild(iframe);
     iframe.contentWindow.addEventListener("load", function() {
       iframe.contentWindow.removeEventListener("load", arguments.callee, false);
 
       // Insert the Sync Key into the page.
       let el = iframe.contentDocument.getElementById("synckey");
       el.firstChild.nodeValue = pp;
 
+      // Insert the TOS and Privacy Policy URLs into the page.
+      let termsURL = Weave.Svc.Prefs.get("termsURL");
+      el = iframe.contentDocument.getElementById("tosLink");
+      el.setAttribute("href", termsURL);
+      el.firstChild.nodeValue = termsURL;
+
+      let privacyURL = Weave.Svc.Prefs.get("privacyURL");
+      el = iframe.contentDocument.getElementById("ppLink");
+      el.setAttribute("href", privacyURL);
+      el.firstChild.nodeValue = privacyURL;
+
       callback(iframe);
     }, false);
   },
 
   /**
    * Print passphrase backup document.
    * 
    * @param elid : ID of the form element containing the passphrase.
@@ -232,16 +253,19 @@ let gSyncUtils = {
       if (rv == Ci.nsIFilePicker.returnOK
           || rv == Ci.nsIFilePicker.returnReplace) {
         let stream = Cc["@mozilla.org/network/file-output-stream;1"]
                        .createInstance(Ci.nsIFileOutputStream);
         stream.init(filepicker.file, -1, -1, 0);
 
         let serializer = new XMLSerializer();
         let output = serializer.serializeToString(iframe.contentDocument);
+        output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
+          '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
+          '"DTD/xhtml1-strict.dtd">');
         output = Weave.Utils.encodeUTF8(output);
         stream.write(output, output.length);
       }
       return false;
     });
   },
 
   /**
@@ -257,16 +281,18 @@ let gSyncUtils = {
     let val1 = el1.value;
     let val2 = el2 ? el2.value : "";
     let error = "";
 
     if (!el2)
       valid = val1.length >= Weave.MIN_PASS_LENGTH;
     else if (val1 && val1 == Weave.Service.username)
       error = "change.password.pwSameAsUsername";
+    else if (val1 && val1 == Weave.Service.account)
+      error = "change.password.pwSameAsEmail";
     else if (val1 && val1 == Weave.Service.password)
       error = "change.password.pwSameAsPassword";
     else if (val1 && val1 == Weave.Service.passphrase)
       error = "change.password.pwSameAsSyncKey";
     else if (val1 && val2) {
       if (val1 == val2 && val1.length >= Weave.MIN_PASS_LENGTH)
         valid = true;
       else if (val1.length < Weave.MIN_PASS_LENGTH)
@@ -288,16 +314,18 @@ let gSyncUtils = {
    */
   validatePassphrase: function (el, change) {
     let valid = false;
     let val = el.value;
     let error = "";
 
     if (val == Weave.Service.username)
       error = "change.synckey.sameAsUsername";
+    else if (val == Weave.Service.account)
+      error = "change.synckey.sameAsEmail";
     else if (val == Weave.Service.password)
       error = "change.synckey.sameAsPassword";
     else if (change && val == Weave.Service.passphrase)
       error = "change.synckey.sameAsSyncKey";
     else if (val.length < Weave.MIN_PP_LENGTH)
       error = "change.synckey.tooShort";
     else
       valid = true;
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -6,21 +6,52 @@
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox");
 }
 
 .tab-close-button {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
   display: none;
 }
 
-.tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > .tabbrowser-tab[selected="true"]:not([pinned]) > .tab-close-button,
-.tabbrowser-tabs[closebuttons="alltabs"] > .tabbrowser-tab:not([pinned]) > .tab-close-button {
+.tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > * > * > * .tab-close-button:not([pinned])[selected="true"],
+.tabbrowser-tabs[closebuttons="alltabs"] > * > * > * > .tab-close-button:not([pinned]) {
   display: -moz-box;
 }
 
+.tab-close-button[selected="true"] {
+  /* Make this button focusable so clicking on it will not focus the tab while
+     it's getting closed */
+  -moz-user-focus: normal;
+}
+
+.tab-label[pinned] {
+  display: none;
+}
+
+.tab-stack {
+  vertical-align: middle; /* for pinned tabs */
+}
+
 tabpanels {
   background-color: white;
 }
 
 .tab-drop-indicator {
   position: relative;
   z-index: 1;
 }
+
+/* tab progress */
+
+.tab-progress {
+  -moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter") !important;
+  margin: 0;
+  min-width: 0;
+}
+
+.tab-progress[selected],
+.tab-progress:not([busy]) {
+  display: none;
+}
+
+.tab-progress-container {
+  -moz-box-pack: start;
+}
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -367,23 +367,18 @@
                                         aCurSelfProgress, aMaxSelfProgress,
                                         aCurTotalProgress, aMaxTotalProgress) {
               this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
 
               if (this.mBlank)
                 return;
 
               if (this.mTotalProgress) {
-                const STATES = 8;
-                let state = Math.ceil(STATES * this.mTotalProgress);
-                if (state != this.mTab.getAttribute("progress")) {
-                  this.mTab.setAttribute("progress", state);
-                  this.mTab.removeAttribute("stalled");
-                  this._startStalledTimer();
-                }
+                let value = Math.ceil(this.mTotalProgress * 100);
+                this.mTab.setAttribute("progresspercent", value);
               }
 
               this._callProgressListeners("onProgressChange",
                                           [aWebProgress, aRequest,
                                            aCurSelfProgress, aMaxSelfProgress,
                                            aCurTotalProgress, aMaxTotalProgress]);
             },
 
@@ -430,16 +425,17 @@
                 // cancelled a pending load which would have cleared
                 // its anchor scroll detection temporary increment.
                 if (aWebProgress.DOMWindow == this.mBrowser.contentWindow)
                   this.mBrowser.userTypedClear += 2;
 
                 if (!this.mBlank) {
                   if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
                     this.mTab.setAttribute("busy", "true");
+                    this.mTab.setAttribute("progresspercent", "0");
                     this._startStalledTimer();
                     this.mTabBrowser.updateIcon(this.mTab);
                     this.mTabBrowser.setTabTitleLoading(this.mTab);
                   }
 
                   if (this.mTab.selected)
                     this.mTabBrowser.mIsBusy = true;
                 }
@@ -457,17 +453,17 @@
                   if (!this.mBrowser.mIconURL)
                     this.mTabBrowser.useDefaultIcon(this.mTab);
                 }
 
                 if (this.mBlank)
                   this.mBlank = false;
 
                 this.mTab.removeAttribute("busy");
-                this.mTab.removeAttribute("progress");
+                this.mTab.removeAttribute("progresspercent");
                 this.mTab.removeAttribute("stalled");
                 this._cancelStalledTimer();
                 this.mTabBrowser.updateIcon(this.mTab);
 
                 var location = aRequest.QueryInterface(nsIChannel).URI;
 
                 // For keyword URIs clear the user typed value since they will be changed into real URIs
                 if (location.scheme == "keyword")
@@ -728,29 +724,36 @@
                             aBrowser.currentURI);
                 if (uri.scheme == "about")
                   newTitle = uri.spec + sep + newTitle;
                 else
                   newTitle = uri.prePath + sep + newTitle;
               }
             } catch (e) {}
 
+            if (window.TabView) {
+              let groupName = TabView.getActiveGroupName();
+              if (groupName)
+                newTitle = groupName + sep + newTitle;
+            }
+
             return newTitle;
           ]]>
         </body>
       </method>
 
       <method name="updateTitlebar">
         <body>
           <![CDATA[
             if (window.TabView && TabView.isVisible()) {
               // ToDo: this will be removed when we gain ability to draw to the menu bar.
               // Bug 586175
               this.ownerDocument.title = TabView.windowTitle;
-            } else {
+            }
+            else {
               this.ownerDocument.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
             }
           ]]>
         </body>
       </method>
 
       <method name="updateCurrentBrowser">
         <parameter name="aForceUpdate"/>
@@ -3317,27 +3320,36 @@
 
   <binding id="tabbrowser-tab" display="xul:hbox"
            extends="chrome://global/content/bindings/tabbox.xml#tab">
     <resources>
       <stylesheet src="chrome://browser/content/tabbrowser.css"/>
     </resources>
 
     <content context="tabContextMenu" closetabtext="&closeTab.label;">
-      <xul:image xbl:inherits="validate,src=image"
-                 class="tab-icon-image"
-                 role="presentation"/>
-      <xul:label flex="1"
-                 xbl:inherits="value=label,crop,accesskey"
-                 class="tab-text"
-                 role="presentation"/>
-      <xul:toolbarbutton anonid="close-button"
-                         tabindex="-1"
-                         clickthrough="never"
-                         class="tab-close-button"/>
+      <xul:stack class="tab-stack" flex="1">
+        <xul:vbox class="tab-progress-container">
+          <xul:progressmeter class="tab-progress" mode="normal"
+                             xbl:inherits="value=progresspercent,busy,stalled,fadein,selected"/>
+        </xul:vbox>
+        <xul:hbox class="tab-content" align="center">
+          <xul:image xbl:inherits="validate,src=image,fadein,pinned,busy,stalled,selected"
+                     class="tab-icon-image"
+                     role="presentation"/>
+          <xul:label flex="1"
+                     xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
+                     class="tab-text tab-label"
+                     role="presentation"/>
+          <xul:toolbarbutton anonid="close-button"
+                             xbl:inherits="fadein,pinned,selected"
+                             tabindex="-1"
+                             clickthrough="never"
+                             class="tab-close-button"/>
+        </xul:hbox>
+      </xul:stack>
     </content>
 
     <implementation>
       <property name="pinned" readonly="true">
         <getter>
           return this.getAttribute("pinned") == "true";
         </getter>
       </property>
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -785,17 +785,24 @@ GroupItem.prototype = Utils.extend(new I
           self.remove(item);
         });
 
         item.setParent(this);
 
         if (typeof item.setResizable == 'function')
           item.setResizable(false);
 
-        if (item.tab == gBrowser.selectedTab)
+        // if it is visually active, set it as the active tab.
+        if (iQ(item.container).hasClass("focus"))
+          this.setActiveTab(item);
+
+        // if it matches the selected tab or no active tab and the browser 
+        // tab is hidden, the active group item would be set.
+        if (item.tab == gBrowser.selectedTab || 
+            (!GroupItems.getActiveGroupItem() && !item.tab.hidden))
           GroupItems.setActiveGroupItem(this);
       }
 
       if (!options.dontArrange) {
         this.arrange();
       }
 
       this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
@@ -830,17 +837,17 @@ GroupItem.prototype = Utils.extend(new I
       if (typeof options == 'undefined')
         options = {};
 
       var index = this._children.indexOf(item);
       if (index != -1)
         this._children.splice(index, 1);
 
       if (item == this._activeTab) {
-        if (this._children.length)
+        if (this._children.length > 0)
           this._activeTab = this._children[0];
         else
           this._activeTab = null;
       }
 
       item.setParent(null);
       item.removeClass("tabInGroupItem");
       item.removeClass("stacked");
@@ -877,39 +884,60 @@ GroupItem.prototype = Utils.extend(new I
     });
   },
 
   // ----------
   // Adds the given xul:tab as an app tab in this group's apptab tray
   addAppTab: function GroupItem_addAppTab(xulTab) {
     let self = this;
 
+    // add the icon
     let icon = xulTab.image || Utils.defaultFaviconURL;
     let $appTab = iQ("<img>")
       .addClass("appTabIcon")
       .attr("src", icon)
       .data("xulTab", xulTab)
       .appendTo(this.$appTabTray)
       .click(function(event) {
         if (Utils.isRightClick(event))
           return;
 
         GroupItems.setActiveGroupItem(self);
         GroupItems._updateTabBar();
         UI.goToTab(iQ(this).data("xulTab"));
       });
 
+    // adjust the tray
     let columnWidth = $appTab.width();
     if (parseInt(this.$appTabTray.css("width")) != columnWidth) {
       this.$appTabTray.css({width: columnWidth});
       this.arrange();
     }
   },
 
   // ----------
+  // Removes the given xul:tab as an app tab in this group's apptab tray
+  removeAppTab: function GroupItem_removeAppTab(xulTab) {
+    // remove the icon
+    iQ(".appTabIcon", this.$appTabTray).each(function(icon) {
+      let $icon = iQ(icon);
+      if ($icon.data("xulTab") != xulTab)
+        return;
+        
+      $icon.remove();
+    });
+    
+    // adjust the tray
+    if (!iQ(".appTabIcon", this.$appTabTray).length) {
+      this.$appTabTray.css({width: 0});
+      this.arrange();
+    }
+  },
+
+  // ----------
   // Function: hideExpandControl
   // Hide the control which expands a stacked groupItem into a quick-look view.
   hideExpandControl: function GroupItem_hideExpandControl() {
     this.$expander.hide();
   },
 
   // ----------
   // Function: showExpandControl
@@ -1497,22 +1525,24 @@ let GroupItems = {
     this._cleanupFunctions.push(function() {
       AllTabs.unregister("attrModified", handleAttrModified);
     });
   },
 
   // ----------
   // Function: uninit
   uninit : function GroupItems_uninit () {
+    // call our cleanup functions
     this._cleanupFunctions.forEach(function(func) {
       func();
     });
 
     this._cleanupFunctions = [];
 
+    // additional clean up
     this.groupItems = null;
   },
 
   // ----------
   // watch for icon changes on app tabs
   _handleAttrModified: function GroupItems__handleAttrModified(xulTab) {
     if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
       return;
@@ -1526,16 +1556,32 @@ let GroupItems = {
 
         if (iconUrl != $icon.attr("src"))
           $icon.attr("src", iconUrl);
       });
     });
   },
 
   // ----------
+  // when a tab becomes pinned, add it to the app tab tray in all groups
+  handleTabPin: function GroupItems_handleTabPin(xulTab) {
+    this.groupItems.forEach(function(groupItem) {
+      groupItem.addAppTab(xulTab);
+    });
+  },
+
+  // ----------
+  // when a tab becomes unpinned, remove it from the app tab tray in all groups
+  handleTabUnpin: function GroupItems_handleTabUnpin(xulTab) {
+    this.groupItems.forEach(function(groupItem) {
+      groupItem.removeAppTab(xulTab);
+    });
+  },
+
+  // ----------
   // Function: getNextID
   // Returns the next unused groupItem ID.
   getNextID: function GroupItems_getNextID() {
     var result = this.nextID;
     this.nextID++;
     this.save();
     return result;
   },
--- a/browser/base/content/tabview/search.js
+++ b/browser/base/content/tabview/search.js
@@ -329,43 +329,47 @@ var TabHandlers = {
   
   _mouseDownLocation: null
 };
 
 function hideSearch(event){
   iQ("#searchbox").val("");
   iQ("#search").hide();
   
-  iQ("#searchbutton").css({top: 0, left: 0, opacity:.8});
+  iQ("#searchbutton").css({ opacity:.8 });
   
   var mainWindow = gWindow.document.getElementById("main-window");    
   mainWindow.setAttribute("activetitlebarcolor", "#C4C4C4");
 
   performSearch();
   SearchEventHandler.switchToBeforeMode();
 
   if (event){
     event.preventDefault();
     event.stopPropagation();
   }
 
   let newEvent = document.createEvent("Events");
   newEvent.initEvent("tabviewsearchdisabled", false, false);
   dispatchEvent(newEvent);
+
+  // Return focus to the tab window
+  UI.blurAll();
+  gTabViewFrame.contentWindow.focus();
 }
 
 function performSearch() {
   var matcher = new TabMatcher(iQ("#searchbox").val());
   matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch);
 }
 
 function ensureSearchShown(event){
   var $search = iQ("#search");
   var $searchbox = iQ("#searchbox");
-  iQ("#searchbutton").css({top: -78, left: -300, opacity: 1});
+  iQ("#searchbutton").css({ opacity: 1 });
   
   
   if ($search.css("display") == "none") {
     $search.show();
     var mainWindow = gWindow.document.getElementById("main-window");
     mainWindow.setAttribute("activetitlebarcolor", "#717171");       
         
     // Marshal the focusing, otherwise you end up with
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -484,16 +484,19 @@ TabItem.prototype = Utils.extend(new Ite
     }
   },
 
   // ----------
   // Function: makeActive
   // Updates this item to visually indicate that it's active.
   makeActive: function TabItem_makeActive() {
     iQ(this.container).addClass("focus");
+
+    if (this.parent)
+      this.parent.setActiveTab(this);
   },
 
   // ----------
   // Function: makeDeactive
   // Updates this item to visually indicate that it's not active.
   makeDeactive: function TabItem_makeDeactive() {
     iQ(this.container).removeClass("focus");
   },
@@ -826,18 +829,18 @@ let TabItems = {
   },
 
   // ----------
   // Function: unlink
   // Takes in a xul:tab and destroys the TabItem associated with it. 
   unlink: function TabItems_unlink(tab) {
     try {
       Utils.assertThrow(tab, "tab");
-      Utils.assertThrow(!tab.pinned, "shouldn't be an app tab");
       Utils.assertThrow(tab.tabItem, "should already be linked");
+      // note that it's ok to unlink an app tab; see .handleTabUnpin
 
       this.unregister(tab.tabItem);
       tab.tabItem._sendToSubscribers("close");
       iQ(tab.tabItem.container).remove();
       tab.tabItem.removeTrenches();
       Items.unsquish(null, tab.tabItem);
 
       tab.tabItem = null;
@@ -847,16 +850,29 @@ let TabItems = {
       if (index != -1)
         this._tabsWaitingForUpdate.splice(index, 1);
     } catch(e) {
       Utils.log(e);
     }
   },
 
   // ----------
+  // when a tab becomes pinned, destroy its TabItem
+  handleTabPin: function TabItems_handleTabPin(xulTab) {
+    this.unlink(xulTab);
+  },
+
+  // ----------
+  // when a tab becomes unpinned, create a TabItem for it
+  handleTabUnpin: function TabItems_handleTabUnpin(xulTab) {
+    this.link(xulTab);
+    this.update(xulTab);
+  },
+
+  // ----------
   // Function: heartbeat
   // Allows us to spreadout update calls over a period of time.
   heartbeat: function TabItems_heartbeat() {
     if (!this._heartbeatOn)
       return;
 
     if (this._tabsWaitingForUpdate.length) {
       this._update(this._tabsWaitingForUpdate[0]);
@@ -988,17 +1004,20 @@ let TabItems = {
         if (Utils.isPoint(tabData.userSize))
           item.userSize = new Point(tabData.userSize);
 
         if (tabData.groupID) {
           var groupItem = GroupItems.groupItem(tabData.groupID);
           if (groupItem) {
             groupItem.add(item);
 
-            if (item.tab == gBrowser.selectedTab)
+            // if it matches the selected tab or no active tab and the browser 
+            // tab is hidden, the active group item would be set.
+            if (item.tab == gBrowser.selectedTab || 
+                (!GroupItems.getActiveGroupItem() && !item.tab.hidden))
               GroupItems.setActiveGroupItem(item.parent);
           }
         }
 
         if (tabData.imageData) {
           item.showCachedData(tabData);
           // the code in the progress listener doesn't fire sometimes because
           // tab is being restored so need to catch that.
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -19,16 +19,17 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  * Ian Gilman <ian@iangilman.com>
  * Aza Raskin <aza@mozilla.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  * Ehsan Akhgari <ehsan@mozilla.com>
  * Raymond Lee <raymond@appcoast.com>
+ * Sean Dunn <seanedunn@yahoo.com>
  *
  * 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
@@ -43,19 +44,19 @@
 // Title: ui.js
 
 let Keys = { meta: false };
 
 // ##########
 // Class: UI
 // Singleton top-level UI manager.
 let UI = {
-  // Variable: _frameInitalized
+  // Variable: _frameInitialized
   // True if the Tab View UI frame has been initialized.
-  _frameInitalized: false,
+  _frameInitialized: false,
 
   // Variable: _pageBounds
   // Stores the page bounds.
   _pageBounds : null,
 
   // Variable: _closedLastVisibleTab
   // If true, the last visible tab has just been closed in the tab strip.
   _closedLastVisibleTab : false,
@@ -78,16 +79,20 @@ let UI = {
   // Keeps track of which xul:tab we are currently on.
   // Used to facilitate zooming down from a previous tab.
   _currentTab : null,
 
   // Variable: _eventListeners
   // Keeps track of event listeners added to the AllTabs object.
   _eventListeners: {},
 
+  // Variable: _cleanupFunctions
+  // An array of functions to be called at uninit time
+  _cleanupFunctions: [],
+
   // ----------
   // Function: init
   // Must be called after the object is created.
   init: function UI_init() {
     try {
       let self = this;
 
       // ___ storage
@@ -220,33 +225,57 @@ let UI = {
             }
             self._save();
           }
         }
       };
       Services.obs.addObserver(observer, "quit-application-requested", false);
 
       // ___ Done
-      this._frameInitalized = true;
+      this._frameInitialized = true;
       this._save();
+
+      // fire an iframe initialized event so everyone knows tab view is 
+      // initialized.
+      let event = document.createEvent("Events");
+      event.initEvent("tabviewframeinitialized", true, false);
+      dispatchEvent(event);
     } catch(e) {
       Utils.log(e);
     }
   },
 
   uninit: function UI_uninit() {
+    // call our cleanup functions
+    this._cleanupFunctions.forEach(function(func) {
+      func();
+    });
+
+    this._cleanupFunctions = [];
+
+    // additional clean up
     TabItems.uninit();
     GroupItems.uninit();
     Storage.uninit();
 
     this._removeTabActionHandlers();
     this._currentTab = null;
     this._pageBounds = null;
     this._reorderTabItemsOnShow = null;
     this._reorderTabsOnHide = null;
+    this._frameInitialized = false;
+  },
+
+  // Function: blurAll
+  // Blurs any currently focused element
+  //
+  blurAll: function UI_blurAll() {
+    iQ(":focus").each(function(element) {
+      element.blur();
+    });
   },
 
   // ----------
   // Function: getActiveTab
   // Returns the currently active tab as a <TabItem>
   //
   getActiveTab: function UI_getActiveTab() {
     return this._activeTab;
@@ -414,27 +443,34 @@ let UI = {
 
       if (self._isTabViewVisible()) {
         // just closed the selected tab in the TabView interface.
         if (self._currentTab == tab)
           self._closedSelectedTabInTabView = true;
       } else {
         // if not closing the last tab
         if (gBrowser.tabs.length > 1) {
+          // Don't return to TabView if there are any app tabs
+          for (let a = 0; a < gBrowser.tabs.length; a++) {
+            let theTab = gBrowser.tabs[a]; 
+            if (theTab.pinned && gBrowser._removingTabs.indexOf(theTab) == -1) 
+              return;
+          }
+
           var groupItem = GroupItems.getActiveGroupItem();
 
           // 1) Only go back to the TabView tab when there you close the last
           // tab of a groupItem.
           // 2) Take care of the case where you've closed the last tab in
           // an un-named groupItem, which means that the groupItem is gone (null) and
           // there are no visible tabs.
           // Can't use timeout here because user would see a flicker of
           // switching to another tab before the TabView interface shows up.
           if ((groupItem && groupItem._children.length == 1) ||
-              (groupItem == null && gBrowser.visibleTabs.length == 1)) {
+              (groupItem == null && gBrowser.visibleTabs.length <= 1)) {
             // for the tab focus event to pick up.
             self._closedLastVisibleTab = true;
             // remove the zoom prep.
             if (tab && tab.tabItem)
               tab.tabItem.setZoomPrep(false);
             self.showTabView();
           }
         }
@@ -454,16 +490,38 @@ let UI = {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
       self.onTabSelect(tab);
     };
 
     for (let name in this._eventListeners)
       AllTabs.register(name, this._eventListeners[name]);
+
+    // Start watching for tab pin events, and set up our uninit for same.
+    function handleTabPin(event) {
+      TabItems.handleTabPin(event.originalTarget);
+      GroupItems.handleTabPin(event.originalTarget);
+    }
+
+    gBrowser.tabContainer.addEventListener("TabPinned", handleTabPin, false);
+    this._cleanupFunctions.push(function() {
+      gBrowser.tabContainer.removeEventListener("TabPinned", handleTabPin, false);
+    });
+
+    // Start watching for tab unpin events, and set up our uninit for same.
+    function handleTabUnpin(event) {
+      TabItems.handleTabUnpin(event.originalTarget);
+      GroupItems.handleTabUnpin(event.originalTarget);
+    }
+
+    gBrowser.tabContainer.addEventListener("TabUnpinned", handleTabUnpin, false);
+    this._cleanupFunctions.push(function() {
+      gBrowser.tabContainer.removeEventListener("TabUnpinned", handleTabUnpin, false);
+    });
   },
 
   // ----------
   // Function: _removeTabActionHandlers
   // Removes handlers to handle tab actions.
   _removeTabActionHandlers: function UI__removeTabActionHandlers() {
     for (let name in this._eventListeners)
       AllTabs.unregister(name, this._eventListeners[name]);
@@ -577,17 +635,17 @@ let UI = {
           event.stopPropagation();
           event.preventDefault();
         }
         return;
       }
 
       function getClosestTabBy(norm) {
         var centers =
-          [[item.bounds.center(), item] 
+          [[item.bounds.center(), item]
              for each(item in TabItems.getItems()) if (!item.parent || !item.parent.hidden)];
         var myCenter = self.getActiveTab().bounds.center();
         var matches = centers
           .filter(function(item){return norm(item[0], myCenter)})
           .sort(function(a,b){
             return myCenter.distance(a[0]) - myCenter.distance(b[0]);
           });
         if (matches.length > 0)
@@ -895,16 +953,18 @@ let UI = {
   // Function: onExitButtonPressed
   // Exits TabView UI.
   onExitButtonPressed: function() {
     let activeTab = this.getActiveTab();
     if (!activeTab)
       activeTab = gBrowser.selectedTab.tabItem;
     if (activeTab)
       activeTab.zoomIn();
+    
+    this.blurAll();
   },
 
   // ----------
   // Function: _addDevMenu
   // Fills out the "dev menu" in the TabView UI.
   _addDevMenu: function UI__addDevMenu() {
     try {
       var self = this;
@@ -992,17 +1052,17 @@ let UI = {
 
     return true;
   },
 
   // ----------
   // Function: _save
   // Saves the data for this object to persistent storage
   _save: function UI__save() {
-    if (!this._frameInitalized)
+    if (!this._frameInitialized)
       return;
 
     var data = {
       pageBounds: this._pageBounds
     };
 
     if (this._storageSanity(data))
       Storage.saveUIData(gWindow, data);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -89,16 +89,17 @@ endif
 # browser_sanitizeDialog_treeView.js is disabled until the tree view is added
 # back to the clear recent history dialog (santize.xul), if it ever is (bug
 # 480169)
 
 # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 
 _BROWSER_FILES = \
                  browser_typeAheadFind.js \
+                 browser_keywordSearch.js \
                  browser_NetworkPrioritizer.js \
                  browser_allTabsPanel.js \
                  browser_alltabslistener.js \
                  browser_bug304198.js \
                  browser_bug321000.js \
                  title_test.svg \
                  browser_bug329212.js \
                  browser_bug356571.js \
@@ -178,16 +179,19 @@ endif
                  browser_popupUI.js \
                  browser_relatedTabs.js \
                  browser_sanitize-passwordDisabledHosts.js \
                  browser_sanitize-sitepermissions.js \
                  browser_sanitize-timespans.js \
                  browser_sanitizeDialog.js \
                  browser_scope.js \
                  browser_selectTabAtIndex.js \
+                 browser_tab_dragdrop.js \
+                 browser_tab_dragdrop2.js \
+                 browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_owner.js \
                  browser_visibleTabs.js \
                  browser_visibleTabs_contextMenu.js \
                  browser_visibleTabs_bookmarkAllPages.js \
                  browser_visibleTabs_bookmarkAllTabs.js \
                  browser_visibleTabs_tabPreview.js \
                  bug592338.html \
@@ -203,16 +207,18 @@ endif
                  plugin_both.html \
                  plugin_both2.html \
                  alltabslistener.html \
                  zoom_test.html \
                  dummy_page.html \
                  browser_tabMatchesInAwesomebar.js \
                  file_bug550565_popup.html \
                  file_bug550565_favicon.ico \
+                 browser_overLinkInLocationBar.js \
+                 browser_overLinkInLocationBar.html \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
--- a/browser/base/content/test/browser_bug386835.js
+++ b/browser/base/content/test/browser_bug386835.js
@@ -67,39 +67,41 @@ function imageZoomSwitch() {
     navigate(FORWARD, function () {
       zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
 
       afterZoom(function() {
         zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
         finishTest();
       });
       gBrowser.selectedTab = gTab2;
-
-      finishTest();
     });
   });
 }
 
+var finishTestStarted  = false;
 function finishTest() {
+  ok(!finishTestStarted, "finishTest called more than once");
+  finishTestStarted = true;
   gBrowser.selectedTab = gTab1;
   FullZoom.reset();
   gBrowser.removeTab(gTab1);
   FullZoom.reset();
   gBrowser.removeTab(gTab2);
   FullZoom.reset();
   gBrowser.removeTab(gTab3);
   finish();
 }
 
 function zoomTest(tab, val, msg) {
   is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
 }
 
 function load(tab, url, cb) {
-  let didLoad = didZoom = false;
+  let didLoad = false;
+  let didZoom = false;
   tab.linkedBrowser.addEventListener("load", function (event) {
     event.currentTarget.removeEventListener("load", arguments.callee, true);
     didLoad = true;
     if (didZoom)
       executeSoon(cb);
   }, true);
 
   afterZoom(function() {
@@ -107,17 +109,18 @@ function load(tab, url, cb) {
     if (didLoad)
       executeSoon(cb);
   });
 
   tab.linkedBrowser.loadURI(url);
 }
 
 function navigate(direction, cb) {
-  let didPs = didZoom = false;
+  let didPs = false;
+  let didZoom = false;
   gBrowser.addEventListener("pageshow", function (event) {
     gBrowser.removeEventListener("pageshow", arguments.callee, true);
     didPs = true;
     if (didZoom)
       executeSoon(cb);
   }, true);
 
   afterZoom(function() {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_keywordSearch.js
@@ -0,0 +1,60 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ **/
+
+function test() {
+  waitForExplicitFinish();
+
+  let tab = gBrowser.selectedTab = gBrowser.addTab();
+  let searchText = "test search";
+
+  let listener = {
+    onStateChange: function onLocationChange(webProgress, req, flags, status) {
+      ok(flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT, "only notified for document");
+
+      // Only care about starts
+      if (!(flags & Ci.nsIWebProgressListener.STATE_START))
+        return;
+
+      ok(req instanceof Ci.nsIChannel, "req is a channel");
+
+      let searchURL = Services.search.originalDefaultEngine.getSubmission(searchText).uri.spec;
+      is(req.originalURI.spec, searchURL, "search URL was loaded");
+      info("Actual URI: " + req.URI.spec);
+
+      Services.ww.unregisterNotification(observer);
+      gBrowser.removeProgressListener(this);
+      executeSoon(function () {
+        gBrowser.removeTab(tab);
+        finish();
+      });
+    }
+  }
+  gBrowser.addProgressListener(listener, Ci.nsIWebProgressListener.NOTIFY_STATE_DOCUMENT);
+
+  let observer = {
+    observe: function(aSubject, aTopic, aData) {
+      if (aTopic == "domwindowopened") {
+        ok(false, "Alert window opened");
+        let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
+        win.addEventListener("load", function() {
+          win.removeEventListener("load", arguments.callee, false);
+          win.close();
+        }, false);
+        gBrowser.removeProgressListener(listener);
+        executeSoon(function () {
+          gBrowser.removeTab(tab);
+          finish();
+        });
+      }
+      Services.ww.unregisterNotification(this);
+    }
+  };
+  Services.ww.registerNotification(observer);
+
+  // Simulate a user entering search terms
+  gURLBar.value = searchText;
+  gURLBar.focus();
+  EventUtils.synthesizeKey("VK_RETURN", {});
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_overLinkInLocationBar.html
@@ -0,0 +1,7 @@
+<html>
+  <body>
+    <p>
+      <a href="http://example.com/" id="link">LINK</a>
+    </p>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_overLinkInLocationBar.js
@@ -0,0 +1,177 @@
+/* ***** 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 browser test code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Drew Willcoxon <adw@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This tests the "over-link" that appears in the location bar when the user
+ * mouses over a link.  See bug 587908.
+ */
+
+const TEST_URL = "http://mochi.test:8888/browser/browser/base/content/test/browser_overLinkInLocationBar.html";
+
+var gTestIter;
+
+// TESTS //////////////////////////////////////////////////////////////////////
+
+function smokeTestGenerator() {
+  let tab = openTestPage();
+  yield;
+
+  let contentDoc = gBrowser.contentDocument;
+  let link = contentDoc.getElementById("link");
+
+  mouseover(link);
+  yield;
+  checkURLBar(true);
+
+  mouseout(link);
+  yield;
+  checkURLBar(false);
+
+  gBrowser.removeTab(tab);
+}
+
+function test() {
+  waitForExplicitFinish();
+  gTestIter = smokeTestGenerator();
+  cont();
+}
+
+// HELPERS ////////////////////////////////////////////////////////////////////
+
+/**
+ * Advances the test iterator.  When all iterations have completed, the entire
+ * suite is finish()ed.
+ */
+function cont() {
+  try {
+    gTestIter.next();
+  }
+  catch (err if err instanceof StopIteration) {
+    finish();
+  }
+}
+
+/**
+ * Asserts that the location bar looks like it should.
+ *
+ * @param shouldShowOverLink
+ *        True if you expect the over-link to be showing and false otherwise.
+ */
+function checkURLBar(shouldShowOverLink) {
+  let overLink = window.getComputedStyle(gURLBar._overLinkBox, null);
+  let origin = window.getComputedStyle(gURLBar._originLabel, null);
+  let editLayer = window.getComputedStyle(gURLBar._textboxContainer, null);
+  if (shouldShowOverLink) {
+    isnot(origin.color, "transparent",
+          "Origin color in over-link layer should not be transparent");
+    is(overLink.opacity, 1, "Over-link should be opaque");
+    is(editLayer.color, "transparent",
+       "Edit layer color should be transparent");
+  }
+  else {
+    is(origin.color, "transparent",
+       "Origin color in over-link layer should be transparent");
+    is(overLink.opacity, 0, "Over-link should be transparent");
+    isnot(editLayer.color, "transparent",
+          "Edit layer color should not be transparent");
+  }
+}
+
+/**
+ * Opens the test URL in a new foreground tab.  When the page has finished
+ * loading, the test iterator is advanced, so you should yield after calling.
+ *
+ * @return The opened <tab>.
+ */
+function openTestPage() {
+  gBrowser.addEventListener("load", function onLoad(event) {
+    if (event.target.URL == TEST_URL) {
+      gBrowser.removeEventListener("load", onLoad, true);
+      cont();
+    }
+  }, true);
+  return gBrowser.loadOneTab(TEST_URL, { inBackground: false });
+}
+
+/**
+ * Sends a mouseover event to a given anchor node.  When the over-link fade-in
+ * transition has completed, the test iterator is advanced, so you should yield
+ * after calling.
+ *
+ * @param anchorNode
+ *        An anchor node.
+ */
+function mouseover(anchorNode) {
+  mouseAnchorNode(anchorNode, true);
+}
+
+/**
+ * Sends a mouseout event to a given anchor node.  When the over-link fade-out
+ * transition has completed, the test iterator is advanced, so you should yield
+ * after calling.
+ *
+ * @param anchorNode
+ *        An anchor node.
+ */
+function mouseout(anchorNode) {
+  mouseAnchorNode(anchorNode, false);
+}
+
+/**
+ * Helper for mouseover and mouseout.  Sends a mouse event to a given node.
+ * When the over-link fade-in or -out transition has completed, the test
+ * iterator is advanced, so you should yield after calling.
+ *
+ * @param node
+ *        An anchor node in a content document.
+ * @param over
+ *        True for "mouseover" and false for "mouseout".
+ */
+function mouseAnchorNode(node, over) {
+  let overLink = gURLBar._overLinkBox;
+  overLink.addEventListener("transitionend", function onTrans(event) {
+    if (event.target == overLink) {
+      overLink.removeEventListener("transitionend", onTrans, false);
+      cont();
+    }
+  }, false);
+  let offset = over ? 0 : -1;
+  let eventType = over ? "mouseover" : "mouseout";
+  EventUtils.synthesizeMouse(node, offset, offset,
+                             { type: eventType, clickCount: 0 },
+                             node.ownerDocument.defaultView);
+}
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -15,16 +15,17 @@
  *
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Gavin Sharp <gavin@gavinsharp.com>
+ *   Sylvain Pasche <sylvain.pasche@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
@@ -137,16 +138,35 @@ function basicNotification() {
     {
       label: "Secondary Action",
       accessKey: "S",
       callback: function () {
         self.secondaryActionClicked = true;
       }
     }
   ];
+  this.options = {
+    eventCallback: function (eventName) {
+      switch (eventName) {
+        case "dismissed":
+          self.dismissalCallbackTriggered = true;
+          break;
+        case "shown":
+          self.shownCallbackTriggered = true;
+          break;
+        case "removed":
+          self.removedCallbackTriggered = true;
+          break;
+      }
+    }
+  };
+  this.addOptions = function(options) {
+    for (let [name, value] in Iterator(options))
+      self.options[name] = value;
+  }
 }
 
 var wrongBrowserNotificationObject = new basicNotification();
 var wrongBrowserNotification;
 
 var tests = [
   { // Test #0
     run: function () {
@@ -179,31 +199,34 @@ var tests = [
       this.notifyObj = new basicNotification(),
       this.notification = showNotification(this.notifyObj);
     },
     onShown: function (popup) {
       checkPopup(popup, this.notifyObj);
       dismissNotification(popup);
     },
     onHidden: function (popup) {
+      ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
       this.notification.remove();
+      ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
     }
   },
   // test opening a notification for a background browser
   { // Test #3
     run: function () {
       gNewTab = gBrowser.addTab("about:blank");
       isnot(gBrowser.selectedTab, gNewTab, "new tab isn't selected");
       wrongBrowserNotificationObject.browser = gBrowser.getBrowserForTab(gNewTab);
       wrongBrowserNotification = showNotification(wrongBrowserNotificationObject);
     },
     backgroundShow: function () {
       is(PopupNotifications.isPanelOpen, false, "panel isn't open");
       ok(!wrongBrowserNotificationObject.mainActionClicked, "main action wasn't clicked");
       ok(!wrongBrowserNotificationObject.secondaryActionClicked, "secondary action wasn't clicked");
+      ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called");
     }
   },
   // now select that browser and test to see that the notification appeared
   { // Test #4
     run: function () {
       this.oldSelectedTab = gBrowser.selectedTab;
       gBrowser.selectedTab = gNewTab;
     },
@@ -212,17 +235,20 @@ var tests = [
       is(PopupNotifications.isPanelOpen, true, "isPanelOpen getter doesn't lie");
 
       // switch back to the old browser
       gBrowser.selectedTab = this.oldSelectedTab;
 
     },
     onHidden: function (popup) {
       // actually remove the notification to prevent it from reappearing
+      ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called");
       wrongBrowserNotification.remove();
+      ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called after remove()");
+      ok(wrongBrowserNotificationObject.removedCallbackTriggered, "removed callback triggered");
       wrongBrowserNotification = null;
     }
   },
   // test that the removed notification isn't shown on browser re-select
   { // Test #5
     run: function () {
       gBrowser.selectedTab = gNewTab;
     },
@@ -265,19 +291,21 @@ var tests = [
       // triggering is async.
       triggerMainCommand(popup);
       is(popup.childNodes.length, 1, "only one notification left");
       triggerSecondaryCommand(popup, 0);
     },
     onHidden: function (popup) {
       ok(this.testNotif1.mainActionClicked, "main action #1 was clicked");
       ok(!this.testNotif1.secondaryActionClicked, "secondary action #1 wasn't clicked");
+      ok(!this.testNotif1.dismissalCallbackTriggered, "dismissal callback #1 wasn't called");
 
       ok(!this.testNotif2.mainActionClicked, "main action #2 wasn't clicked");
       ok(this.testNotif2.secondaryActionClicked, "secondary action #2 was clicked");
+      ok(!this.testNotif2.dismissalCallbackTriggered, "dismissal callback #2 wasn't called");
     }
   },
   // Test notification without mainAction
   { // Test #8
     run: function () {
       this.notifyObj = new basicNotification(),
       this.notifyObj.mainAction = null;
       showNotification(this.notifyObj);
@@ -305,31 +333,34 @@ var tests = [
       checkPopup(popup, this.notifyObj2);
       is(document.getElementById("geo-notification-icon").boxObject.width, 0,
          "geo anchor shouldn't be visible");
       dismissNotification(popup);
     },
     onHidden: function (popup) {
       // Remove the first notification
       this.firstNotification.remove();
+      ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
     }
   },
   // Test optional params
   { // Test #10
     run: function () {
       this.notifyObj = new basicNotification();
       this.notifyObj.secondaryActions = undefined;
       this.notification = showNotification(this.notifyObj);
     },
     onShown: function (popup) {
       checkPopup(popup, this.notifyObj);
       dismissNotification(popup);
     },
     onHidden: function (popup) {
+      ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
       this.notification.remove();
+      ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
     }
   },
   // Test that icons appear
   { // Test #11
     run: function () {
       this.notifyObj = new basicNotification();
       this.notifyObj.id = "geolocation";
       this.notifyObj.anchorID = "geo-notification-icon";
@@ -349,19 +380,19 @@ var tests = [
   { // Test #12
     run: function () {
       this.oldSelectedTab = gBrowser.selectedTab;
       gBrowser.selectedTab = gBrowser.addTab("about:blank");
 
       let self = this;
       loadURI("http://example.com/", function() {
         self.notifyObj = new basicNotification();
-        self.notifyObj.options = {
+        self.notifyObj.addOptions({
           persistence: 2
-        };
+        });
         self.notification = showNotification(self.notifyObj);
       });
     },
     onShown: function (popup) {
       this.complete = false;
 
       let self = this;
       loadURI("http://example.org/", function() {
@@ -386,19 +417,19 @@ var tests = [
     run: function () {
       this.oldSelectedTab = gBrowser.selectedTab;
       gBrowser.selectedTab = gBrowser.addTab("about:blank");
 
       let self = this;
       loadURI("http://example.com/", function() {
         self.notifyObj = new basicNotification();
         // Set a timeout of 10 minutes that should never be hit
-        self.notifyObj.options = {
+        self.notifyObj.addOptions({
           timeout: Date.now() + 600000
-        };
+        });
         self.notification = showNotification(self.notifyObj);
       });
     },
     onShown: function (popup) {
       this.complete = false;
 
       let self = this;
       loadURI("http://example.org/", function() {
@@ -428,17 +459,17 @@ var tests = [
 
       let button = document.createElement("button");
       button.setAttribute("label", "Please click me!");
       this.box.appendChild(button);
 
       // The notification should open up on the box
       this.notifyObj = new basicNotification();
       this.notifyObj.anchorID = this.box.id = "nested-box";
-      this.notifyObj.options = {dismissed: true};
+      this.notifyObj.addOptions({dismissed: true});
       this.notification = showNotification(this.notifyObj);
 
       EventUtils.synthesizeMouse(button, 1, 1, {});
     },
     onShown: function(popup) {
       checkPopup(popup, this.notifyObj);
       dismissNotification(popup);
     },
@@ -447,17 +478,17 @@ var tests = [
       this.box.parentNode.removeChild(this.box);
     }
   },
   // Test that popupnotifications without popups have anchor icons shown
   { // Test #15
     run: function() {
       let notifyObj = new basicNotification();
       notifyObj.anchorID = "geo-notification-icon";
-      notifyObj.options = {neverShow: true};
+      notifyObj.addOptions({neverShow: true});
       showNotification(notifyObj);
     },
     updateNotShowing: function() {
       isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
             "geo anchor should be visible");
     }
   },
 ];
@@ -469,18 +500,20 @@ function showNotification(notifyObj) {
                                  notifyObj.anchorID,
                                  notifyObj.mainAction,
                                  notifyObj.secondaryActions,
                                  notifyObj.options);
 }
 
 function checkPopup(popup, notificationObj) {
   info("[Test #" + gTestIndex + "] checking popup");
+
+  ok(notificationObj.shownCallbackTriggered, "shown callback was triggered");
+
   let notifications = popup.childNodes;
-
   is(notifications.length, 1, "only one notification displayed");
   let notification = notifications[0];
   let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
   if (notificationObj.id == "geolocation")
     isnot(icon.boxObject.width, 0, "icon for geo displayed");
   is(notification.getAttribute("label"), notificationObj.message, "message matches");
   is(notification.id, notificationObj.id + "-notification", "id matches");
   if (notificationObj.mainAction) {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tab_dragdrop.js
@@ -0,0 +1,114 @@
+function test()
+{
+  var embed = '<embed type="application/x-test" allowscriptaccess="always" allowfullscreen="true" wmode="window" width="640" height="480"></embed>'
+
+  waitForExplicitFinish();
+
+  // create a few tabs
+  var tabs = [
+    gBrowser.tabs[0],
+    gBrowser.addTab("about:blank", {skipAnimation: true}),
+    gBrowser.addTab("about:blank", {skipAnimation: true}),
+    gBrowser.addTab("about:blank", {skipAnimation: true}),
+    gBrowser.addTab("about:blank", {skipAnimation: true})
+  ];
+
+  function setLocation(i, url) {
+    gBrowser.getBrowserForTab(tabs[i]).contentWindow.location = url;
+  }
+  function moveTabTo(a, b) {
+    gBrowser.swapBrowsersAndCloseOther(gBrowser.tabs[b], gBrowser.tabs[a]);
+  }
+  function clickTest(doc, win) {
+    var clicks = doc.defaultView.clicks;
+    EventUtils.synthesizeMouse(doc.body, 100, 600, {}, win);
+    is(doc.defaultView.clicks, clicks+1, "adding 1 more click on BODY");
+  }
+  function test1() {
+    moveTabTo(2, 3); // now: 0 1 2 4
+    is(gBrowser.tabs[1], tabs[1], "tab1");
+    is(gBrowser.tabs[2], tabs[3], "tab3");
+
+    var plugin = gBrowser.getBrowserForTab(tabs[4]).docShell.contentViewer.DOMDocument.wrappedJSObject.body.firstChild;
+    var tab4_plugin_object = plugin.getObjectValue();
+
+    gBrowser.selectedTab = gBrowser.tabs[2];
+    moveTabTo(3, 2); // now: 0 1 4
+    gBrowser.selectedTab = tabs[4];
+    var doc = gBrowser.getBrowserForTab(gBrowser.tabs[2]).docShell.contentViewer.DOMDocument.wrappedJSObject;
+    plugin = doc.body.firstChild;
+    ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
+    is(gBrowser.tabs[1], tabs[1], "tab1");
+    is(gBrowser.tabs[2], tabs[3], "tab4");
+    is(doc.defaultView.clicks, 0, "no click on BODY so far");
+    clickTest(doc, window);
+
+    moveTabTo(2, 1); // now: 0 4
+    is(gBrowser.tabs[1], tabs[1], "tab1");
+    doc = gBrowser.getBrowserForTab(gBrowser.tabs[1]).docShell.contentViewer.DOMDocument.wrappedJSObject;
+    plugin = doc.body.firstChild;
+    ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
+    clickTest(doc, window);
+
+    // Load a new document (about:blank) in tab4, then detach that tab into a new window.
+    // In the new window, navigate back to the original document and click on its <body>,
+    // verify that its onclick was called.
+    var t = tabs[1];
+    var b = gBrowser.getBrowserForTab(t);
+    gBrowser.selectedTab = t;
+    b.addEventListener("load", function() {
+      b.removeEventListener("load", arguments.callee, true);
+
+      executeSoon(function () {
+        var win = gBrowser.replaceTabWithWindow(t);
+        win.addEventListener("load", function () {
+          win.removeEventListener("load", arguments.callee, true);
+
+          // Verify that the original window now only has the initial tab left in it.
+          is(gBrowser.tabs[0], tabs[0], "tab0");
+          is(gBrowser.getBrowserForTab(gBrowser.tabs[0]).contentWindow.location, "about:blank", "tab0 uri");
+
+          executeSoon(function () {
+            win.gBrowser.addEventListener("pageshow", function () {
+              win.gBrowser.removeEventListener("pageshow", arguments.callee, false);
+              executeSoon(function () {
+                t = win.gBrowser.tabs[0];
+                b = win.gBrowser.getBrowserForTab(t);
+                var doc = b.docShell.contentViewer.DOMDocument.wrappedJSObject;
+                clickTest(doc, win);
+                win.close();
+                finish();
+              });
+            }, false);
+            win.gBrowser.goBack();
+          });
+        }, true);
+      });
+    }, true);
+    b.loadURI("about:blank");
+
+  }
+
+  var loads = 0;
+  function waitForLoad(tab) {
+    gBrowser.getBrowserForTab(gBrowser.tabs[tab]).removeEventListener("load", arguments.callee, true);
+    ++loads;
+    if (loads == tabs.length - 1) {
+      executeSoon(test1);
+    }
+  }
+
+  function fn(f, arg) {
+    return function () { return f(arg); };
+  }
+  for (var i = 1; i < tabs.length; ++i) {
+    gBrowser.getBrowserForTab(tabs[i]).addEventListener("load", fn(waitForLoad,i), true);
+  }
+
+  setLocation(1, "data:text/html,<title>tab1</title><body>tab1<iframe>");
+  setLocation(2, "data:text/plain,tab2");
+  setLocation(3, "data:text/html,<title>tab3</title><body>tab3<iframe>");
+  setLocation(4, "data:text/html,<body onload='clicks=0' onclick='++clicks'>"+embed);
+  gBrowser.selectedTab = tabs[3];
+
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tab_dragdrop2.js
@@ -0,0 +1,53 @@
+function test()
+{
+  waitForExplicitFinish();
+
+  var level1 = false;
+  var level2 = false;
+  function test1() {
+    // Load the following URI (which runs some child popup tests) in a new window (B),
+    // then add a blank tab to B and call replaceTabWithWindow to detach the URI tab
+    // into yet a new window (C), then close B.
+    // Now run the tests again and then close C.
+    // The test results does not matter, all this is just to exercise some code to
+    // catch assertions or crashes.
+    var uri = "chrome://mochikit/content/browser/" +
+              "browser/base/content/test/browser_tab_dragdrop2_frame1.xul";
+    let window_B = openDialog(location, "_blank", "chrome,all,dialog=no,left=200,top=200,width=200,height=200", uri);
+    window_B.addEventListener("load", function(aEvent) {
+      window_B.removeEventListener("load", arguments.callee, false);
+      if (level1) return; level1=true;
+      executeSoon(function () {
+        window_B.gBrowser.addEventListener("load", function(aEvent) {
+          window_B.removeEventListener("load", arguments.callee, true);
+          if (level2) return; level2=true;
+          is(window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location, uri, "sanity check");
+          //alert("1:"+window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
+          var windowB_tab2 = window_B.gBrowser.addTab("about:blank", {skipAnimation: true});
+          setTimeout(function () {
+            //alert("2:"+window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
+            window_B.gBrowser.addEventListener("pagehide", function(aEvent) {
+              window_B.gBrowser.removeEventListener("pagehide", arguments.callee, true);
+              executeSoon(function () {
+                // alert("closing window_B which has "+ window_B.gBrowser.tabs.length+" tabs\n"+
+                //      window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
+                window_B.close();
+
+                var doc = window_C.gBrowser.getBrowserForTab(window_C.gBrowser.tabs[0])
+                            .docShell.contentViewer.DOMDocument.wrappedJSObject;
+                var elems = document.documentElement.childNodes;
+                var calls = doc.defaultView.test_panels();
+                window_C.close();
+                finish();
+              });
+            }, true);
+            window_B.gBrowser.selectedTab = window_B.gBrowser.tabs[0];
+            var window_C = window_B.gBrowser.replaceTabWithWindow(window_B.gBrowser.tabs[0]);
+            }, 1000);  // 1 second to allow the tests to create the popups
+        }, true);
+      });
+    }, false);
+  }
+
+  test1();
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tab_dragdrop2_frame1.xul
@@ -0,0 +1,170 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+  XUL Widget Test for panels
+  -->
+<window title="Titlebar" width="200" height="200"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+<tree id="tree" seltype="single" width="100" height="100">
+  <treecols>
+    <treecol flex="1"/>
+    <treecol flex="1"/>
+  </treecols>
+  <treechildren id="treechildren">
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+    <treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
+  </treechildren>
+</tree>
+
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+SimpleTest.waitForExplicitFinish();
+
+var currentTest = null;
+
+var i = 0;
+var my_debug = false;
+function test_panels()
+{
+  checkTreeCoords();
+
+  addEventListener("popupshown", popupShown, false);
+  addEventListener("popuphidden", nextTest, false);
+  return nextTest();
+}
+
+function nextTest()
+{
+  ok(true,"popuphidden " + i)
+  if (i == tests.length) {
+    SimpleTest.finish();
+    return i;
+  }
+
+  currentTest = tests[i];
+  var panel = createPanel(currentTest.attrs);
+  currentTest.test(panel);
+  return i;
+}
+
+var waitSteps = 0;
+function popupShown(event)
+{
+  var panel = event.target;
+  if (waitSteps > 0 && navigator.platform.indexOf("Linux") >= 0 &&
+      panel.boxObject.screenY == 210) {
+    waitSteps--;
+    setTimeout(popupShown, 10, event);
+    return;
+  }
+  ++i;
+
+  currentTest.result(currentTest.testname + " ", panel);
+  panel.hidePopup();
+}
+
+function createPanel(attrs)
+{
+  var panel = document.createElement("panel");
+  for (var a in attrs) {
+    panel.setAttribute(a, attrs[a]);
+  }
+
+  var button = document.createElement("button");
+  panel.appendChild(button);
+  button.label = "OK";
+  button.width = 120;
+  button.height = 40;
+  button.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
+  panel.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
+  return document.documentElement.appendChild(panel);
+}
+
+function checkTreeCoords()
+{
+  var tree = $("tree");
+  var treechildren = $("treechildren");
+  tree.currentIndex = 0;
+  tree.treeBoxObject.scrollToRow(0);
+  synthesizeMouse(treechildren, 10, tree.treeBoxObject.rowHeight + 2, { });
+
+  tree.treeBoxObject.scrollToRow(2);
+  synthesizeMouse(treechildren, 10, tree.treeBoxObject.rowHeight + 2, { });
+}
+
+var tests = [
+  {
+    testname: "normal panel",
+    attrs: { },
+    test: function(panel) {
+      panel.openPopupAtScreen(200, 210);
+    },
+    result: function(testname, panel) {
+      if (my_debug) alert(testname);
+      var panelrect = panel.getBoundingClientRect();
+    }
+  },
+  {
+    // only noautohide panels support titlebars, so one shouldn't be shown here
+    testname: "autohide panel with titlebar",
+    attrs: { titlebar: "normal" },
+    test: function(panel) {
+      panel.openPopupAtScreen(200, 210);
+    },
+    result: function(testname, panel) {
+      if (my_debug) alert(testname);
+      var panelrect = panel.getBoundingClientRect();
+    }
+  },
+  {
+    testname: "noautohide panel with titlebar",
+    attrs: { noautohide: true, titlebar: "normal" },
+    test: function(panel) {
+      waitSteps = 25;
+      panel.openPopupAtScreen(200, 210);
+    },
+    result: function(testname, panel) {
+      if (my_debug) alert(testname);
+      var panelrect = panel.getBoundingClientRect();
+
+      var gotMouseEvent = false;
+      function mouseMoved(event)
+      {
+        gotMouseEvent = true;
+      }
+
+      panel.addEventListener("mousemove", mouseMoved, true);
+      synthesizeMouse(panel, 10, 10, { type: "mousemove" });
+      panel.removeEventListener("mousemove", mouseMoved, true);
+
+      var tree = $("tree");
+      tree.currentIndex = 0;
+      panel.appendChild(tree);
+      checkTreeCoords();
+    }
+  }
+];
+
+SimpleTest.waitForFocus(test_panels);
+
+]]>
+</script>
+
+</window>
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -39,21 +39,26 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/base/content/test/tabview
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
-                 browser_tabview_launch.js \
+                 browser_tabview_apptabs.js \
+                 browser_tabview_bug587040.js \
+                 browser_tabview_bug587990.js \
+                 browser_tabview_bug591706.js \
+                 browser_tabview_bug595191.js \
+                 browser_tabview_bug595518.js \
+                 browser_tabview_bug595943.js \
                  browser_tabview_dragdrop.js \
+                 browser_tabview_exit_button.js \
                  browser_tabview_group.js \
+                 browser_tabview_launch.js \
                  browser_tabview_search.js \
                  browser_tabview_snapping.js \
-                 browser_tabview_bug591706.js \
-                 browser_tabview_apptabs.js \
                  browser_tabview_undo_group.js \
-                 browser_tabview_exit_button.js \
                  $(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/base/content/test/tabview/browser_tabview_apptabs.js
+++ b/browser/base/content/test/tabview/browser_tabview_apptabs.js
@@ -47,43 +47,82 @@ function onTabViewWindowLoaded() {
   window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
   ok(TabView.isVisible(), "Tab View is visible");
 
   let contentWindow = document.getElementById("tab-view").contentWindow;
 
   // establish initial state
   is(contentWindow.GroupItems.groupItems.length, 1, "we start with one group (the default)"); 
   is(gBrowser.tabs.length, 1, "we start with one tab");
+  let originalTab = gBrowser.tabs[0];
   
-  // create an app tab
-  let appXulTab = gBrowser.loadOneTab("about:blank");
-  gBrowser.pinTab(appXulTab);
+  // create a group 
+  let box = new contentWindow.Rect(20, 20, 180, 180);
+  let groupItemOne = new contentWindow.GroupItem([], { bounds: box, title: "test1" });
+  is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
+  contentWindow.GroupItems.setActiveGroupItem(groupItemOne);
+  
+  // create a tab
+  let xulTab = gBrowser.loadOneTab("about:blank");
   is(gBrowser.tabs.length, 2, "we now have two tabs");
+  is(groupItemOne._children.length, 1, "the new tab was added to the group");
+  
+  // make sure the group has no app tabs
+  let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
+  is(appTabIcons.length, 0, "there are no app tab icons");
   
-  // Create a group 
-  let box = new contentWindow.Rect(20, 20, 180, 180);
-  let groupItem = new contentWindow.GroupItem([], { bounds: box });
-  is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
+  // pin the tab, make sure the TabItem goes away and the icon comes on
+  gBrowser.pinTab(xulTab);
+
+  is(groupItemOne._children.length, 0, "the app tab's TabItem was removed from the group");
+
+  appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
+  is(appTabIcons.length, 1, "there's now one app tab icon");
+
+  // create a second group and make sure it gets the icon too
+  box.offset(box.width + 20, 0);
+  let groupItemTwo = new contentWindow.GroupItem([], { bounds: box, title: "test2" });
+  is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
+  appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
+  is(appTabIcons.length, 1, "there's an app tab icon in the second group");
   
+  // unpin the tab, make sure the icon goes away and the TabItem comes on
+  gBrowser.unpinTab(xulTab);
+
+  is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
+
+  appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
+  is(appTabIcons.length, 0, "the icon is gone from group one");
+
+  appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
+  is(appTabIcons.length, 0, "the icon is gone from group 2");
+  
+  // pin the tab again
+  gBrowser.pinTab(xulTab);
+
+  // close the second group
+  groupItemTwo.close();
+
   // find app tab in group and hit it
   let onTabViewHidden = function() {
     window.removeEventListener("tabviewhidden", onTabViewHidden, false);
     ok(!TabView.isVisible(), "Tab View is hidden because we clicked on the app tab");
     
     // clean up
-    gBrowser.unpinTab(appXulTab);
-    gBrowser.removeTab(appXulTab);
+    gBrowser.selectedTab = originalTab;
+    
+    gBrowser.unpinTab(xulTab);
+    gBrowser.removeTab(xulTab);
     is(gBrowser.tabs.length, 1, "we finish with one tab");
   
-    groupItem.close();
+    groupItemOne.close();
     is(contentWindow.GroupItems.groupItems.length, 1, "we finish with one group");
     
-    ok(!TabView.isVisible(), "Tab View is not visible");
+    ok(!TabView.isVisible(), "we finish with Tab View not visible");
     
     finish();
   };
 
   window.addEventListener("tabviewhidden", onTabViewHidden, false);
 
-  let appTabButtons = groupItem.$appTabTray[0].getElementsByTagName("img");
-  ok(appTabButtons.length == 1, "there is one app tab button");
-  EventUtils.sendMouseEvent({ type: "click" }, appTabButtons[0], contentWindow);
+  appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
+  EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug587040.js
@@ -0,0 +1,150 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is tabview test for bug 587040.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Raymond Lee <raymond@appcoast.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  waitForExplicitFinish();
+
+  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
+  TabView.toggle();
+}
+
+function onTabViewWindowLoaded() {
+  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
+
+  ok(TabView.isVisible(), "Tab View is visible");
+
+  let [originalTab] = gBrowser.visibleTabs;
+  let contentWindow = document.getElementById("tab-view").contentWindow;
+
+  // create a group
+  let box = new contentWindow.Rect(20, 20, 300, 300);
+  let groupItem = new contentWindow.GroupItem([], { bounds: box });
+
+  let onTabViewShown = function() {
+    window.removeEventListener("tabviewshown", onTabViewShown, false);
+
+    is(groupItem.getChildren().length, 2, "The new group has two tab items");
+    // start the test
+    testSameTabItemAndClickGroup(contentWindow, groupItem);
+  };
+
+  // create a tab item in the new group
+  let onTabViewHidden = function() {
+    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
+
+    ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
+
+    let anotherTab = gBrowser.addTab("http://mochi.test:8888/");
+    let browser = gBrowser.getBrowserForTab(anotherTab);
+    let onLoad = function() {
+      browser.removeEventListener("load", onLoad, true);
+    
+      window.addEventListener("tabviewshown", onTabViewShown, false);
+      TabView.toggle();
+    }
+    browser.addEventListener("load", onLoad, true);
+  };
+  window.addEventListener("tabviewhidden", onTabViewHidden, false);
+
+  // click on the + button to create a blank tab
+  let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
+  ok(newTabButton[0], "New tab button exists");
+
+  EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
+}
+
+function testSameTabItemAndClickGroup(contentWindow, groupItem, originalTab) {
+  let activeTabItem = groupItem.getActiveTab();
+  ok(activeTabItem, "Has active item");
+
+  let onTabViewHidden = function() {
+    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
+
+    is(activeTabItem.tab, gBrowser.selectedTab, "The correct tab is selected");
+    TabView.toggle();
+  };
+
+  let onTabViewShown = function() {
+    window.removeEventListener("tabviewshown", onTabViewShown, false);
+
+    testDifferentTabItemAndClickGroup(contentWindow, groupItem, originalTab);
+  };
+  window.addEventListener("tabviewhidden", onTabViewHidden, false);
+  window.addEventListener("tabviewshown", onTabViewShown, false);
+  
+  let groupElement = groupItem.container;
+  EventUtils.sendMouseEvent({ type: "mousedown" }, groupElement, contentWindow);
+  EventUtils.sendMouseEvent({ type: "mouseup" }, groupElement, contentWindow);
+}
+
+function testDifferentTabItemAndClickGroup(contentWindow, groupItem, originalTab) {
+  let activeTabItem = groupItem.getActiveTab();
+  ok(activeTabItem, "Has old active item");
+
+  // press tab
+  EventUtils.synthesizeKey("VK_TAB", {}, contentWindow);
+
+  let newActiveTabItem = groupItem.getActiveTab();
+  ok(newActiveTabItem, "Has new active item");
+
+  isnot(newActiveTabItem, activeTabItem, "The old and new active items are different");
+
+  let onTabViewHidden = function() {
+    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
+
+    is(newActiveTabItem.tab, gBrowser.selectedTab, "The correct tab is selected");
+    
+    // clean up and finish the test
+    groupItem.addSubscriber(groupItem, "close", function() {
+      groupItem.removeSubscriber(groupItem, "close");
+      finish();  
+    });
+    gBrowser.selectedTab = originalTab;
+
+    groupItem.closeAll();
+    // close undo group
+    let closeButton = groupItem.$undoContainer.find(".close");
+    EventUtils.sendMouseEvent(
+      { type: "click" }, closeButton[0], contentWindow);
+  };
+  window.addEventListener("tabviewhidden", onTabViewHidden, false);
+
+  // press the group Item  
+  let groupElement = groupItem.container;
+  EventUtils.sendMouseEvent({ type: "mousedown" }, groupElement, contentWindow);
+  EventUtils.sendMouseEvent({ type: "mouseup" }, groupElement, contentWindow);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug587990.js
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is bug 587990 test.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Raymond Lee <raymond@appcoast.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let newTab;
+let win;
+
+function test() {
+  waitForExplicitFinish();
+
+  win = window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", "about:blank");
+
+  let onLoad = function() {
+    win.removeEventListener("load", onLoad, false);
+
+    newTab = win.gBrowser.addTab();
+
+    let onTabViewFrameInitialized = function() {
+      win.removeEventListener(
+        "tabviewframeinitialized", onTabViewFrameInitialized, false);
+
+      win.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
+      win.TabView.toggle();
+    }
+    win.addEventListener(
+      "tabviewframeinitialized", onTabViewFrameInitialized, false);
+    win.TabView.updateContextMenu(
+      newTab, win.document.getElementById("context_tabViewMenuPopup"));
+  }
+  win.addEventListener("load", onLoad, false);
+}
+
+function onTabViewWindowLoaded() {
+  win.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
+
+  ok(win.TabView.isVisible(), "Tab View is visible");
+
+  let contentWindow = win.document.getElementById("tab-view").contentWindow;
+
+  is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
+
+  let groupItem = contentWindow.GroupItems.groupItems[0];
+  let tabItems = groupItem.getChildren();
+
+  is(tabItems[tabItems.length - 1].tab, newTab, "The new tab exists in the group");
+
+  win.gBrowser.removeTab(newTab);
+  whenWindowObservesOnce(win, "domwindowclosed", function() {
+    finish();
+  });
+  win.close();
+}
+
+function whenWindowObservesOnce(win, topic, func) {
+    let windowWatcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+      .getService(Compo