merge m-c to devtools, conflict in inspector.js
authorRob Campbell <rcampbell@mozilla.com>
Fri, 24 Jun 2011 15:50:35 -0300
changeset 71679 0421a3198a3c559876581fdfcb6fcfaac47d4766
parent 71678 674f0bd87a13288be2780062a469afac42c1c5d5 (current diff)
parent 71666 0577771f2065856eb91202a6087badd3331cd8b5 (diff)
child 71680 c1ec764b3cd6ff1d10d65278794dda8ab505ef3d
push id20589
push userrcampbell@mozilla.com
push dateFri, 24 Jun 2011 18:55:12 +0000
treeherdermozilla-central@0421a3198a3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge m-c to devtools, conflict in inspector.js
browser/app/profile/firefox.js
browser/base/content/inspector.js
browser/base/content/test/Makefile.in
browser/base/jar.mn
browser/components/places/tests/perf/Makefile.in
browser/components/places/tests/perf/browser_ui_000_data.js
browser/components/places/tests/perf/browser_ui_bookmarks_sidebar.js
browser/components/places/tests/perf/browser_ui_history_menu.js
browser/components/places/tests/perf/browser_ui_history_sidebar.js
browser/components/places/tests/perf/browser_ui_history_sidebar_2.js
browser/components/places/tests/perf/browser_ui_history_sidebar_3.js
browser/components/places/tests/perf/browser_ui_locationbar.js
browser/components/places/tests/perf/perf_large_delete.xul
config/installcfunc.pl
config/installchrome.pl
content/base/public/nsISyncLoadDOMService.idl
content/base/src/nsLoadListenerProxy.cpp
content/base/src/nsLoadListenerProxy.h
content/base/test/test_bug574596.html
content/events/public/nsIEventListenerManager.h
content/events/public/nsPIDOMEventTarget.h
content/events/src/nsDOMEventGroup.cpp
content/events/src/nsDOMEventGroup.h
content/events/src/nsDOMOrientationEvent.cpp
content/events/src/nsDOMOrientationEvent.h
content/html/content/test/test_bug344615.html
content/html/content/test/test_bug345512.html
content/html/content/test/test_bug345822.html
content/html/content/test/test_bug346485.html
content/html/content/test/test_bug555559.html
content/html/content/test/test_bug556013.html
content/html/content/test/test_bug562932.html
content/html/content/test/test_bug565538.html
content/html/content/test/test_bug566160.html
content/html/content/test/test_bug589696.html
dom/interfaces/base/nsIDOMNSFeatureFactory.idl
dom/interfaces/base/nsIDOMWindow2.idl
dom/interfaces/core/nsIDOM3Node.idl
dom/interfaces/events/nsIDOM3EventTarget.idl
dom/interfaces/events/nsIDOMEventGroup.idl
dom/interfaces/events/nsIDOMNSEventTarget.idl
dom/interfaces/html/nsIDOMNSHTMLTextAreaElement.idl
dom/locales/en-US/chrome/storage.properties
dom/system/android/nsAccelerometerSystem.cpp
dom/system/android/nsAccelerometerSystem.h
dom/system/cocoa/nsAccelerometerSystem.h
dom/system/cocoa/nsAccelerometerSystem.mm
dom/system/nsAccelerometer.cpp
dom/system/nsAccelerometer.h
dom/system/unix/nsAccelerometerSystem.cpp
dom/system/unix/nsAccelerometerSystem.h
dom/system/windows/nsAccelerometerSystem.cpp
dom/system/windows/nsAccelerometerSystem.h
embedding/browser/activex/src/Makefile.in
embedding/browser/activex/src/common/CPMozillaControl.h
embedding/browser/activex/src/common/ControlEventSink.cpp
embedding/browser/activex/src/common/ControlEventSink.h
embedding/browser/activex/src/common/ControlSite.cpp
embedding/browser/activex/src/common/ControlSite.h
embedding/browser/activex/src/common/ControlSiteIPFrame.cpp
embedding/browser/activex/src/common/ControlSiteIPFrame.h
embedding/browser/activex/src/common/IEHtmlButtonElement.cpp
embedding/browser/activex/src/common/IEHtmlButtonElement.h
embedding/browser/activex/src/common/IEHtmlElement.cpp
embedding/browser/activex/src/common/IEHtmlElement.h
embedding/browser/activex/src/common/IEHtmlElementCollection.cpp
embedding/browser/activex/src/common/IEHtmlElementCollection.h
embedding/browser/activex/src/common/IEHtmlNode.cpp
embedding/browser/activex/src/common/IEHtmlNode.h
embedding/browser/activex/src/common/IEHtmlSelectionObject.cpp
embedding/browser/activex/src/common/IEHtmlSelectionObject.h
embedding/browser/activex/src/common/IEHtmlTxtRange.cpp
embedding/browser/activex/src/common/IEHtmlTxtRange.h
embedding/browser/activex/src/common/IHTMLLocationImpl.h
embedding/browser/activex/src/common/IOleCommandTargetImpl.h
embedding/browser/activex/src/common/IWebBrowserImpl.h
embedding/browser/activex/src/common/ItemContainer.cpp
embedding/browser/activex/src/common/ItemContainer.h
embedding/browser/activex/src/common/Makefile.in
embedding/browser/activex/src/common/PropertyBag.cpp
embedding/browser/activex/src/common/PropertyBag.h
embedding/browser/activex/src/common/PropertyList.h
embedding/browser/activex/src/common/StdAfx.h
embedding/browser/activex/src/control/ActiveScriptSite.cpp
embedding/browser/activex/src/control/ActiveScriptSite.h
embedding/browser/activex/src/control/ActiveXTypes.h
embedding/browser/activex/src/control/BrowserDiagnostics.h
embedding/browser/activex/src/control/DHTMLCmdIds.h
embedding/browser/activex/src/control/DropTarget.cpp
embedding/browser/activex/src/control/DropTarget.h
embedding/browser/activex/src/control/HelperAppDlg.cpp
embedding/browser/activex/src/control/HelperAppDlg.h
embedding/browser/activex/src/control/IEHtmlDocument.cpp
embedding/browser/activex/src/control/IEHtmlDocument.h
embedding/browser/activex/src/control/Makefile.in
embedding/browser/activex/src/control/Master.dsp
embedding/browser/activex/src/control/Master.dsw
embedding/browser/activex/src/control/MozillaBrowser.cpp
embedding/browser/activex/src/control/MozillaBrowser.h
embedding/browser/activex/src/control/MozillaBrowser.ico
embedding/browser/activex/src/control/MozillaBrowser.rgs
embedding/browser/activex/src/control/MozillaControl.cpp
embedding/browser/activex/src/control/MozillaControl.dsp
embedding/browser/activex/src/control/MozillaControl.idl
embedding/browser/activex/src/control/MozillaControl.rc
embedding/browser/activex/src/control/PageSetupDlg.h
embedding/browser/activex/src/control/PromptService.cpp
embedding/browser/activex/src/control/PromptService.h
embedding/browser/activex/src/control/PropertyDlg.cpp
embedding/browser/activex/src/control/PropertyDlg.h
embedding/browser/activex/src/control/StdAfx.cpp
embedding/browser/activex/src/control/StdAfx.h
embedding/browser/activex/src/control/WebBrowserContainer.cpp
embedding/browser/activex/src/control/WebBrowserContainer.h
embedding/browser/activex/src/control/WindowCreator.cpp
embedding/browser/activex/src/control/WindowCreator.h
embedding/browser/activex/src/control/mkctldef.bat
embedding/browser/activex/src/control/mkctldef.sh
embedding/browser/activex/src/control/resource.h
embedding/browser/activex/src/control_kicker/Makefile.in
embedding/browser/activex/src/control_kicker/ReadMe.txt
embedding/browser/activex/src/control_kicker/StdAfx.cpp
embedding/browser/activex/src/control_kicker/StdAfx.h
embedding/browser/activex/src/control_kicker/control_kicker.cpp
embedding/browser/activex/src/control_kicker/control_kicker.dsp
embedding/browser/activex/src/control_kicker/control_kicker.h
embedding/browser/activex/src/control_kicker/mozctlx.def
embedding/browser/activex/src/plugin/LegacyPlugin.cpp
embedding/browser/activex/src/plugin/LegacyPlugin.h
embedding/browser/activex/src/plugin/Makefile.in
embedding/browser/activex/src/plugin/MozActiveX.cpp
embedding/browser/activex/src/plugin/MozActiveX.rc
embedding/browser/activex/src/plugin/MozAxPlugin.java
embedding/browser/activex/src/plugin/PrefObserver.cpp
embedding/browser/activex/src/plugin/StdAfx.cpp
embedding/browser/activex/src/plugin/StdAfx.h
embedding/browser/activex/src/plugin/XPCBrowser.cpp
embedding/browser/activex/src/plugin/XPCBrowser.h
embedding/browser/activex/src/plugin/XPCDocument.cpp
embedding/browser/activex/src/plugin/XPConnect.cpp
embedding/browser/activex/src/plugin/XPConnect.h
embedding/browser/activex/src/plugin/activex.js
embedding/browser/activex/src/plugin/install.js
embedding/browser/activex/src/plugin/npwin.cpp
embedding/browser/activex/src/plugin/nsAxSecurityPolicy.js
embedding/browser/activex/src/plugin/nsIMozAxPlugin.idl
embedding/browser/activex/src/plugin/plugin.sln
embedding/browser/activex/src/plugin/plugin.vcproj
embedding/browser/activex/src/plugin/resource.h
embedding/browser/activex/src/plugin/test.htm
embedding/browser/activex/src/pluginhostctrl/PluginHostCtrl.rgs
embedding/browser/activex/src/pluginhostctrl/README.txt
embedding/browser/activex/src/pluginhostctrl/StdAfx.cpp
embedding/browser/activex/src/pluginhostctrl/StdAfx.h
embedding/browser/activex/src/pluginhostctrl/cab/README.txt
embedding/browser/activex/src/pluginhostctrl/cab/makecab.bat
embedding/browser/activex/src/pluginhostctrl/cab/pluginhostctrl.inf
embedding/browser/activex/src/pluginhostctrl/cab/redist/ATL.DLL
embedding/browser/activex/src/pluginhostctrl/cab/verify.htm
embedding/browser/activex/src/pluginhostctrl/npn.cpp
embedding/browser/activex/src/pluginhostctrl/npn.h
embedding/browser/activex/src/pluginhostctrl/nsPluginHostCtrl.cpp
embedding/browser/activex/src/pluginhostctrl/nsPluginHostCtrl.h
embedding/browser/activex/src/pluginhostctrl/nsPluginHostWnd.cpp
embedding/browser/activex/src/pluginhostctrl/nsPluginHostWnd.h
embedding/browser/activex/src/pluginhostctrl/nsPluginWnd.cpp
embedding/browser/activex/src/pluginhostctrl/nsPluginWnd.h
embedding/browser/activex/src/pluginhostctrl/nsURLDataCallback.cpp
embedding/browser/activex/src/pluginhostctrl/nsURLDataCallback.h
embedding/browser/activex/src/pluginhostctrl/pluginho.bmp
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.cpp
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.def
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.dsp
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.idl
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.rc
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.sln
embedding/browser/activex/src/pluginhostctrl/pluginhostctrl.vcproj
embedding/browser/activex/src/pluginhostctrl/pluginhostctrlps.def
embedding/browser/activex/src/pluginhostctrl/pluginhostctrlps.mk
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/jni.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/jni_md.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/jri.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/jri_md.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/jritypes.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/npapi.h
embedding/browser/activex/src/pluginhostctrl/pluginsdk_include/npupp.h
embedding/browser/activex/src/pluginhostctrl/resource.h
embedding/browser/activex/src/pluginhostctrl/tests/ns4x_reference_test3.htm
embedding/browser/activex/src/pluginhostctrl/tests/test1.htm
embedding/browser/activex/src/pluginhostctrl/tests/test10.htm
embedding/browser/activex/src/pluginhostctrl/tests/test11.htm
embedding/browser/activex/src/pluginhostctrl/tests/test2.htm
embedding/browser/activex/src/pluginhostctrl/tests/test3.htm
embedding/browser/activex/src/pluginhostctrl/tests/test4.htm
embedding/browser/activex/src/pluginhostctrl/tests/test5.htm
embedding/browser/activex/src/pluginhostctrl/tests/test6.htm
embedding/browser/activex/src/pluginhostctrl/tests/test7.htm
embedding/browser/activex/src/pluginhostctrl/tests/test8.htm
embedding/browser/activex/src/pluginhostctrl/tests/test9.htm
embedding/browser/activex/src/xml/ParseExpat.cpp
embedding/browser/activex/src/xml/StdAfx.cpp
embedding/browser/activex/src/xml/StdAfx.h
embedding/browser/activex/src/xml/XMLDocument.cpp
embedding/browser/activex/src/xml/XMLDocument.h
embedding/browser/activex/src/xml/XMLDocument.rgs
embedding/browser/activex/src/xml/XMLElement.cpp
embedding/browser/activex/src/xml/XMLElement.h
embedding/browser/activex/src/xml/XMLElement.rgs
embedding/browser/activex/src/xml/XMLElementCollection.cpp
embedding/browser/activex/src/xml/XMLElementCollection.h
embedding/browser/activex/src/xml/XMLElementCollection.rgs
embedding/browser/activex/src/xml/activexml.cpp
embedding/browser/activex/src/xml/activexml.def
embedding/browser/activex/src/xml/activexml.dsp
embedding/browser/activex/src/xml/activexml.idl
embedding/browser/activex/src/xml/activexml.rc
embedding/browser/activex/src/xml/activexmlps.def
embedding/browser/activex/src/xml/resource.h
embedding/browser/activex/tests/IEPatcher/DlgProxy.cpp
embedding/browser/activex/tests/IEPatcher/DlgProxy.h
embedding/browser/activex/tests/IEPatcher/IEPatcher.cpp
embedding/browser/activex/tests/IEPatcher/IEPatcher.dsp
embedding/browser/activex/tests/IEPatcher/IEPatcher.h
embedding/browser/activex/tests/IEPatcher/IEPatcher.odl
embedding/browser/activex/tests/IEPatcher/IEPatcher.rc
embedding/browser/activex/tests/IEPatcher/IEPatcher.reg
embedding/browser/activex/tests/IEPatcher/IEPatcherDlg.cpp
embedding/browser/activex/tests/IEPatcher/IEPatcherDlg.h
embedding/browser/activex/tests/IEPatcher/ScanForFilesDlg.cpp
embedding/browser/activex/tests/IEPatcher/ScanForFilesDlg.h
embedding/browser/activex/tests/IEPatcher/ScannerThread.cpp
embedding/browser/activex/tests/IEPatcher/ScannerThread.h
embedding/browser/activex/tests/IEPatcher/ScannerWnd.cpp
embedding/browser/activex/tests/IEPatcher/ScannerWnd.h
embedding/browser/activex/tests/IEPatcher/StdAfx.cpp
embedding/browser/activex/tests/IEPatcher/StdAfx.h
embedding/browser/activex/tests/IEPatcher/res/IEPatcher.ico
embedding/browser/activex/tests/IEPatcher/res/IEPatcher.rc2
embedding/browser/activex/tests/IEPatcher/res/containsie.ico
embedding/browser/activex/tests/IEPatcher/res/containsmozilla.ico
embedding/browser/activex/tests/IEPatcher/res/doesntcontainie.ico
embedding/browser/activex/tests/IEPatcher/res/unknownstatus.ico
embedding/browser/activex/tests/IEPatcher/resource.h
embedding/browser/activex/tests/RegMozCtl/MozillaBrowser.ico
embedding/browser/activex/tests/RegMozCtl/ReadMe.txt
embedding/browser/activex/tests/RegMozCtl/RegMozCtl.cpp
embedding/browser/activex/tests/RegMozCtl/RegMozCtl.dsp
embedding/browser/activex/tests/RegMozCtl/RegMozCtl.h
embedding/browser/activex/tests/RegMozCtl/RegMozCtl.rc
embedding/browser/activex/tests/RegMozCtl/RegMozCtlDlg.cpp
embedding/browser/activex/tests/RegMozCtl/RegMozCtlDlg.h
embedding/browser/activex/tests/RegMozCtl/RegTask.cpp
embedding/browser/activex/tests/RegMozCtl/RegTask.h
embedding/browser/activex/tests/RegMozCtl/RegTaskManager.cpp
embedding/browser/activex/tests/RegMozCtl/RegTaskManager.h
embedding/browser/activex/tests/RegMozCtl/StdAfx.cpp
embedding/browser/activex/tests/RegMozCtl/StdAfx.h
embedding/browser/activex/tests/RegMozCtl/res/RegMozCtl.ico
embedding/browser/activex/tests/RegMozCtl/res/RegMozCtl.rc2
embedding/browser/activex/tests/RegMozCtl/resource.h
embedding/browser/activex/tests/cbrowse/CBrowseDlg.cpp
embedding/browser/activex/tests/cbrowse/CBrowseDlg.h
embedding/browser/activex/tests/cbrowse/CBrowserCtlSite.cpp
embedding/browser/activex/tests/cbrowse/CBrowserCtlSite.h
embedding/browser/activex/tests/cbrowse/CBrowserCtlSite.rgs
embedding/browser/activex/tests/cbrowse/Cbrowse.idl
embedding/browser/activex/tests/cbrowse/Cbrowse.rgs
embedding/browser/activex/tests/cbrowse/ControlEventSink.cpp
embedding/browser/activex/tests/cbrowse/ControlEventSink.h
embedding/browser/activex/tests/cbrowse/ControlEventSink.rgs
embedding/browser/activex/tests/cbrowse/EditToolBar.cpp
embedding/browser/activex/tests/cbrowse/EditToolBar.h
embedding/browser/activex/tests/cbrowse/Html/main.htm
embedding/browser/activex/tests/cbrowse/PickerDlg.cpp
embedding/browser/activex/tests/cbrowse/PickerDlg.h
embedding/browser/activex/tests/cbrowse/Scripts/Basic.vbs
embedding/browser/activex/tests/cbrowse/Scripts/NewWindow.vbs
embedding/browser/activex/tests/cbrowse/Scripts/Post.vbs
embedding/browser/activex/tests/cbrowse/StdAfx.cpp
embedding/browser/activex/tests/cbrowse/StdAfx.h
embedding/browser/activex/tests/cbrowse/TabDOM.cpp
embedding/browser/activex/tests/cbrowse/TabDOM.h
embedding/browser/activex/tests/cbrowse/TabMessages.cpp
embedding/browser/activex/tests/cbrowse/TabMessages.h
embedding/browser/activex/tests/cbrowse/TabTests.cpp
embedding/browser/activex/tests/cbrowse/TabTests.h
embedding/browser/activex/tests/cbrowse/TestScriptHelper.cpp
embedding/browser/activex/tests/cbrowse/TestScriptHelper.h
embedding/browser/activex/tests/cbrowse/TestScriptHelper.rgs
embedding/browser/activex/tests/cbrowse/Tests.cpp
embedding/browser/activex/tests/cbrowse/Tests.h
embedding/browser/activex/tests/cbrowse/cbrowse.cpp
embedding/browser/activex/tests/cbrowse/cbrowse.dsp
embedding/browser/activex/tests/cbrowse/cbrowse.h
embedding/browser/activex/tests/cbrowse/cbrowse.rc
embedding/browser/activex/tests/cbrowse/cbrowse.sln
embedding/browser/activex/tests/cbrowse/res/cbrowse.ico
embedding/browser/activex/tests/cbrowse/res/cbrowse.rc2
embedding/browser/activex/tests/cbrowse/res/closedfolder.ico
embedding/browser/activex/tests/cbrowse/res/openfolder.ico
embedding/browser/activex/tests/cbrowse/res/test.ico
embedding/browser/activex/tests/cbrowse/res/testfailed.ico
embedding/browser/activex/tests/cbrowse/res/testpartial.ico
embedding/browser/activex/tests/cbrowse/res/testpassed.ico
embedding/browser/activex/tests/cbrowse/res/toolbar1.bmp
embedding/browser/activex/tests/cbrowse/resource.h
embedding/browser/activex/tests/csbrowse/App.ico
embedding/browser/activex/tests/csbrowse/AssemblyInfo.cs
embedding/browser/activex/tests/csbrowse/CSBrowse.csproj
embedding/browser/activex/tests/csbrowse/CSBrowse.sln
embedding/browser/activex/tests/csbrowse/Form1.cs
embedding/browser/activex/tests/csbrowse/Form1.resx
embedding/browser/activex/tests/csbrowse/back.bmp
embedding/browser/activex/tests/csbrowse/forward.bmp
embedding/browser/activex/tests/csbrowse/home.bmp
embedding/browser/activex/tests/csbrowse/reload.bmp
embedding/browser/activex/tests/csbrowse/stop.bmp
embedding/browser/activex/tests/dbrowse/form.dcu
embedding/browser/activex/tests/dbrowse/form.dfm
embedding/browser/activex/tests/dbrowse/form.pas
embedding/browser/activex/tests/dbrowse/webbrowser.dof
embedding/browser/activex/tests/dbrowse/webbrowser.dpr
embedding/browser/activex/tests/plugin/calendar.html
embedding/browser/activex/tests/plugin/calendar_scripted.htm
embedding/browser/activex/tests/vbrowse/VBrowse.vbp
embedding/browser/activex/tests/vbrowse/browser.frm
embedding/browser/activex/tests/vbrowse/browser.frx
embedding/browser/activex/tests/vbrowse/frmExplorer.frm
embedding/browser/activex/tests/vbrowse/frmToolBar.frm
embedding/browser/activex/tests/vbrowse/frmToolBar.frx
embedding/browser/activex/tests/vbxml/test.xml
embedding/browser/activex/tests/vbxml/xml.frm
embedding/browser/activex/tests/vbxml/xml.vbp
embedding/browser/activex/tests/vbxml/xml.vbw
gfx/angle/src/libGLESv2/geometry/IndexDataManager.cpp
gfx/angle/src/libGLESv2/geometry/IndexDataManager.h
gfx/angle/src/libGLESv2/geometry/VertexDataManager.cpp
gfx/angle/src/libGLESv2/geometry/VertexDataManager.h
gfx/angle/src/libGLESv2/geometry/backend.cpp
gfx/angle/src/libGLESv2/geometry/backend.h
gfx/angle/src/libGLESv2/geometry/dx9.cpp
gfx/angle/src/libGLESv2/geometry/dx9.h
gfx/angle/src/libGLESv2/geometry/vertexconversion.h
gfx/cairo/cairo/src/cairo-ddraw.h
gfx/cairo/wince-fixes.patch
intl/locale/public/nsIPosixLocale.h
intl/locale/src/unix/nsPosixLocale.h
js/src/SpiderMonkey.rsp
js/src/bench.sh
js/src/js.mdp
js/src/jsify.pl
js/src/jslong.h
js/src/perfect.js
js/src/plify_jsdhash.sed
js/src/tests/ecma_5/strict/function-name-arity.js
js/src/time.sh
js/src/xpconnect/idl/XPCIDispatch.idl
js/src/xpconnect/idl/nsIActiveXSecurityPolicy.idl
js/src/xpconnect/idl/nsIDispatchSupport.idl
js/src/xpconnect/src/XPCDispConvert.cpp
js/src/xpconnect/src/XPCDispInlines.h
js/src/xpconnect/src/XPCDispInterface.cpp
js/src/xpconnect/src/XPCDispObject.cpp
js/src/xpconnect/src/XPCDispParams.cpp
js/src/xpconnect/src/XPCDispPrivate.h
js/src/xpconnect/src/XPCDispTearOff.cpp
js/src/xpconnect/src/XPCDispTypeInfo.cpp
js/src/xpconnect/src/XPCIDispatchClassInfo.cpp
js/src/xpconnect/src/XPCIDispatchExtension.cpp
js/src/xpconnect/src/nsDispatchSupport.cpp
js/src/xpconnect/tests/idispatch/COM/StdAfx.cpp
js/src/xpconnect/tests/idispatch/COM/StdAfx.h
js/src/xpconnect/tests/idispatch/COM/XPCDispUtilities.h
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.cpp
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.def
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsp
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsw
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.idl
js/src/xpconnect/tests/idispatch/COM/XPCIDispatchTest.rc
js/src/xpconnect/tests/idispatch/COM/nsXPCDispSimple.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispSimple.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispSimple.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.rgs
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.cpp
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.h
js/src/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.rgs
js/src/xpconnect/tests/idispatch/COM/resource.h
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/Arrays/XPCIDispatchArrayTests.js
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/Attributes/XPCIDispatchAttributeTests.js
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCIDispatchInstantiations.js
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCStress.js
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/Methods/XPCIDispatchMethodTests.js
js/src/xpconnect/tests/idispatch/Tests/WrappedCOM/shell.js
js/src/xpconnect/tests/idispatch/Tests/WrappedJS/General/XPCIDispatchTestWrappedJS.js
js/src/xpconnect/tests/idispatch/Tests/WrappedJS/shell.js
js/src/xpconnect/tests/idispatch/Tests/exectests.cmd
js/src/xpconnect/tests/idispatch/Tests/jsDriver.pl
layout/base/tests/bug106855-1-ref.html
layout/base/tests/bug106855-1.html
layout/base/tests/bug106855-2.html
layout/base/tests/bug240933-1-ref.html
layout/base/tests/bug240933-1.html
layout/base/tests/bug240933-2.html
layout/base/tests/bug389321-1-ref.html
layout/base/tests/bug389321-1.html
layout/base/tests/bug389321-2-ref.html
layout/base/tests/bug389321-2.html
layout/base/tests/bug389321-3-ref.html
layout/base/tests/bug389321-3.html
layout/base/tests/bug482484-ref.html
layout/base/tests/bug482484.html
layout/base/tests/bug495648.rdf
layout/base/tests/bug512295-1-ref.html
layout/base/tests/bug512295-1.html
layout/base/tests/bug512295-2-ref.html
layout/base/tests/bug512295-2.html
layout/base/tests/bug585922-ref.html
layout/base/tests/bug585922.html
layout/base/tests/bug597519-1-ref.html
layout/base/tests/bug597519-1.html
layout/base/tests/bug602141-1-ref.html
layout/base/tests/bug602141-1.html
layout/base/tests/bug602141-2-ref.html
layout/base/tests/bug602141-2.html
layout/base/tests/bug602141-3-ref.html
layout/base/tests/bug602141-3.html
layout/base/tests/bug602141-4-ref.html
layout/base/tests/bug602141-4.html
layout/base/tests/bug612271-1.html
layout/base/tests/bug612271-2.html
layout/base/tests/bug612271-3.html
layout/base/tests/bug612271-ref.html
layout/base/tests/bug613433-1.html
layout/base/tests/bug613433-2.html
layout/base/tests/bug613433-3.html
layout/base/tests/bug613433-ref.html
layout/base/tests/bug613807-1-ref.html
layout/base/tests/bug613807-1.html
layout/base/tests/bug632215-1.html
layout/base/tests/bug632215-2.html
layout/base/tests/bug632215-ref.html
layout/base/tests/bug633044-1-ref.html
layout/base/tests/bug633044-1.html
layout/base/tests/bug634406-1-ref.html
layout/base/tests/bug634406-1.html
layout/base/tests/bug644428-1-ref.html
layout/base/tests/bug644428-1.html
layout/base/tests/bug646382-1-ref.html
layout/base/tests/bug646382-1.html
layout/base/tests/bug646382-2-ref.html
layout/base/tests/bug646382-2.html
layout/base/tests/test_bug495648.xul
layout/base/tests/test_reftests_with_caret.html
modules/libreg/standalone/Makefile.in
startupcache/nsStartupCacheUtils.cpp
testing/mochitest/pywebsocket/mod_pywebsocket/standalone.py
toolkit/crashreporter/test/browser/aboutcrashes_utils.js
toolkit/themes/pinstripe/mozapps/extensions/background-texture.png
toolkit/themes/winstripe/mozapps/extensions/background-texture.png
tools/cross-commit
xpcom/base/Telemetry.cpp
xpcom/base/nsITelemetry.idl
xpcom/base/nsSetDllDirectory.cpp
xpcom/io/nsFastLoadFile.cpp
xpcom/io/nsFastLoadFile.h
xpcom/io/nsFastLoadService.cpp
xpcom/io/nsFastLoadService.h
xpcom/io/nsIFastLoadFileControl.idl
xpcom/io/nsIFastLoadService.idl
xpcom/system/nsIAccelerometer.idl
xpcom/tests/unit/test_nsITelemetry.js
--- a/accessible/build/Makefile.in
+++ b/accessible/build/Makefile.in
@@ -66,34 +66,10 @@ SHARED_LIBRARY_LIBS = \
 ifdef MOZ_XUL
 SHARED_LIBRARY_LIBS += ../src/xul/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
 endif
 
 ifndef DISABLE_XFORMS_HOOKS
 SHARED_LIBRARY_LIBS += ../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX)
 endif
 
-EXTRA_DSO_LIBS = \
-	gkgfx \
-	thebes \
-	$(NULL)
-
-EXTRA_DSO_LDOPTS =           \
-	$(LIBS_DIR)              \
-	$(EXTRA_DSO_LIBS)        \
-	$(MOZ_UNICHARUTIL_LIBS)  \
-	$(MOZ_COMPONENT_LIBS)    \
-	$(NULL)
-
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS)
-endif
-
-ifeq ($(OS_ARCH),WINNT)
-OS_LIBS += \
-	oleaut32.lib \
-	version.lib \
-	ole32.lib \
-	$(NULL)
-endif
-
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/src/atk/AtkSocketAccessible.cpp
+++ b/accessible/src/atk/AtkSocketAccessible.cpp
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/AtkSocketAccessible.h
+++ b/accessible/src/atk/AtkSocketAccessible.h
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -83,18 +83,16 @@ EXPORTS = \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
   $(NULL)
 
 # we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
-EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS)
-
 include $(topsrcdir)/config/rules.mk
 
 CFLAGS		+= $(MOZ_GTK2_CFLAGS)
 CXXFLAGS	+= $(MOZ_GTK2_CFLAGS)
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
--- a/accessible/src/atk/nsARIAGridAccessibleWrap.h
+++ b/accessible/src/atk/nsARIAGridAccessibleWrap.h
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsAccessNodeWrap.cpp
+++ b/accessible/src/atk/nsAccessNodeWrap.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsAccessNodeWrap.h
+++ b/accessible/src/atk/nsAccessNodeWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsAccessibleRelationWrap.h
+++ b/accessible/src/atk/nsAccessibleRelationWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
@@ -1072,16 +1072,26 @@ nsAccessibleWrap::FirePlatformEvent(AccE
             atk_focus_tracker_notify(atkObj);
             // Fire state change event for focus
             nsRefPtr<AccEvent> stateChangeEvent =
               new AccStateChangeEvent(accessible, states::FOCUSED, PR_TRUE);
             return FireAtkStateChangeEvent(stateChangeEvent, atkObj);
         }
       } break;
 
+    case nsIAccessibleEvent::EVENT_NAME_CHANGE:
+      {
+        nsString newName;
+        accessible->GetName(newName);
+        NS_ConvertUTF16toUTF8 utf8Name(newName);
+        if (!utf8Name.Equals(atkObj->name))
+          atk_object_set_name(atkObj, utf8Name.get());
+
+        break;
+      }
     case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_VALUE_CHANGE\n"));
         nsCOMPtr<nsIAccessibleValue> value(do_QueryObject(accessible));
         if (value) {    // Make sure this is a numeric value
             // Don't fire for MSAA string value changes (e.g. text editing)
             // ATK values are always numeric
             g_object_notify( (GObject*)atkObj, "accessible-value" );
--- a/accessible/src/atk/nsAccessibleWrap.h
+++ b/accessible/src/atk/nsAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsApplicationAccessibleWrap.h
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsDocAccessibleWrap.cpp
+++ b/accessible/src/atk/nsDocAccessibleWrap.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsDocAccessibleWrap.h
+++ b/accessible/src/atk/nsDocAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsHTMLImageAccessibleWrap.h
+++ b/accessible/src/atk/nsHTMLImageAccessibleWrap.h
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsHTMLTableAccessibleWrap.h
+++ b/accessible/src/atk/nsHTMLTableAccessibleWrap.h
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsHyperTextAccessibleWrap.h
+++ b/accessible/src/atk/nsHyperTextAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMai.h
+++ b/accessible/src/atk/nsMai.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiHyperlink.cpp
+++ b/accessible/src/atk/nsMaiHyperlink.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
@@ -210,18 +210,16 @@ finalizeCB(GObject *aObj)
 }
 
 gchar *
 getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
     nsAccessible* hyperlink = get_accessible_hyperlink(aLink);
     NS_ENSURE_TRUE(hyperlink, nsnull);
 
-    MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aLink);
-
     nsCOMPtr<nsIURI> uri = hyperlink->GetAnchorURI(aLinkIndex);
     if (!uri)
         return nsnull;
 
     nsCAutoString cautoStr;
     nsresult rv = uri->GetSpec(cautoStr);
     NS_ENSURE_SUCCESS(rv, nsnull);
 
--- a/accessible/src/atk/nsMaiHyperlink.h
+++ b/accessible/src/atk/nsMaiHyperlink.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceAction.cpp
+++ b/accessible/src/atk/nsMaiInterfaceAction.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceAction.h
+++ b/accessible/src/atk/nsMaiInterfaceAction.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceComponent.h
+++ b/accessible/src/atk/nsMaiInterfaceComponent.h
@@ -1,11 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceDocument.cpp
+++ b/accessible/src/atk/nsMaiInterfaceDocument.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceDocument.h
+++ b/accessible/src/atk/nsMaiInterfaceDocument.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceEditableText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceEditableText.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceEditableText.h
+++ b/accessible/src/atk/nsMaiInterfaceEditableText.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceHyperlinkImpl.cpp
+++ b/accessible/src/atk/nsMaiInterfaceHyperlinkImpl.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceHyperlinkImpl.h
+++ b/accessible/src/atk/nsMaiInterfaceHyperlinkImpl.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceHypertext.cpp
+++ b/accessible/src/atk/nsMaiInterfaceHypertext.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceHypertext.h
+++ b/accessible/src/atk/nsMaiInterfaceHypertext.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceImage.cpp
+++ b/accessible/src/atk/nsMaiInterfaceImage.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceImage.h
+++ b/accessible/src/atk/nsMaiInterfaceImage.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceSelection.cpp
+++ b/accessible/src/atk/nsMaiInterfaceSelection.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceSelection.h
+++ b/accessible/src/atk/nsMaiInterfaceSelection.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/src/atk/nsMaiInterfaceTable.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceTable.h
+++ b/accessible/src/atk/nsMaiInterfaceTable.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceText.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceText.h
+++ b/accessible/src/atk/nsMaiInterfaceText.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceValue.cpp
+++ b/accessible/src/atk/nsMaiInterfaceValue.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsMaiInterfaceValue.h
+++ b/accessible/src/atk/nsMaiInterfaceValue.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsRoleMap.h
+++ b/accessible/src/atk/nsRoleMap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsRootAccessibleWrap.cpp
+++ b/accessible/src/atk/nsRootAccessibleWrap.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsRootAccessibleWrap.h
+++ b/accessible/src/atk/nsRootAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsStateMap.h
+++ b/accessible/src/atk/nsStateMap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsTextAccessibleWrap.h
+++ b/accessible/src/atk/nsTextAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsXULListboxAccessibleWrap.h
+++ b/accessible/src/atk/nsXULListboxAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsXULMenuAccessibleWrap.h
+++ b/accessible/src/atk/nsXULMenuAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/atk/nsXULTreeGridAccessibleWrap.h
+++ b/accessible/src/atk/nsXULTreeGridAccessibleWrap.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* ***** 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/
  *
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -45,17 +45,17 @@
 #include "nsRootAccessibleWrap.h"
 #include "States.h"
 
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
-#include "nsIEventListenerManager.h"
+#include "nsEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMWindow.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIWebNavigation.h"
 #include "nsServiceManagerUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccDocManager
@@ -386,26 +386,26 @@ nsAccDocManager::IsEventTargetDocument(n
   return (contentType == nsIDocShellTreeItem::typeContent);
 }
 
 void
 nsAccDocManager::AddListeners(nsIDocument *aDocument,
                               PRBool aAddDOMContentLoadedListener)
 {
   nsPIDOMWindow *window = aDocument->GetWindow();
-  nsPIDOMEventTarget *target = window->GetChromeEventHandler();
-  nsIEventListenerManager* elm = target->GetListenerManager(PR_TRUE);
+  nsIDOMEventTarget *target = window->GetChromeEventHandler();
+  nsEventListenerManager* elm = target->GetListenerManager(PR_TRUE);
   elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
-                              NS_EVENT_FLAG_CAPTURE, nsnull);
+                              NS_EVENT_FLAG_CAPTURE);
 
   NS_LOG_ACCDOCCREATE_TEXT("  added 'pagehide' listener")
 
   if (aAddDOMContentLoadedListener) {
     elm->AddEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
-                                NS_EVENT_FLAG_CAPTURE, nsnull);
+                                NS_EVENT_FLAG_CAPTURE);
     NS_LOG_ACCDOCCREATE_TEXT("  added 'DOMContentLoaded' listener")
   }
 }
 
 nsDocAccessible*
 nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
 {
   // Ignore temporary, hiding, resource documents and documents without
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -38,27 +38,26 @@
 
 #include "nsCoreUtils.h"
 
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessNode.h"
 
 #include "nsIDocument.h"
-#include "nsIDOM3Node.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
-#include "nsIEventListenerManager.h"
+#include "nsEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsEventStateManager.h"
 #include "nsISelection2.h"
 #include "nsISelectionController.h"
 #include "nsPIDOMWindow.h"
 #include "nsGUIEvent.h"
@@ -74,17 +73,17 @@ static NS_DEFINE_IID(kRangeCID, NS_RANGE
 ////////////////////////////////////////////////////////////////////////////////
 // nsCoreUtils
 ////////////////////////////////////////////////////////////////////////////////
 
 PRBool
 nsCoreUtils::HasClickListener(nsIContent *aContent)
 {
   NS_ENSURE_TRUE(aContent, PR_FALSE);
-  nsIEventListenerManager* listenerManager =
+  nsEventListenerManager* listenerManager =
     aContent->GetListenerManager(PR_FALSE);
 
   return listenerManager &&
     (listenerManager->HasListenersFor(NS_LITERAL_STRING("click")) ||
      listenerManager->HasListenersFor(NS_LITERAL_STRING("mousedown")) ||
      listenerManager->HasListenersFor(NS_LITERAL_STRING("mouseup")));
 }
 
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -60,28 +60,27 @@
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIDOMDataContainerEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULPopupElement.h"
 #include "nsIDocument.h"
-#include "nsIEventListenerManager.h"
+#include "nsEventListenerManager.h"
 #include "nsIFrame.h"
 #include "nsIMenuFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsRootAccessible.h"
-#include "nsIDOMNSEventTarget.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
@@ -246,21 +245,21 @@ const char* const docEvents[] = {
   "DOMMenuInactive",
   "DOMMenuItemActive",
   "DOMMenuBarActive",
   "DOMMenuBarInactive"
 };
 
 nsresult nsRootAccessible::AddEventListeners()
 {
-  // nsIDOMNSEventTarget interface allows to register event listeners to
+  // nsIDOMEventTarget interface allows to register event listeners to
   // receive untrusted events (synthetic events generated by untrusted code).
   // For example, XBL bindings implementations for elements that are hosted in
   // non chrome document fire untrusted events.
-  nsCOMPtr<nsIDOMNSEventTarget> nstarget(do_QueryInterface(mDocument));
+  nsCOMPtr<nsIDOMEventTarget> nstarget(do_QueryInterface(mDocument));
 
   if (nstarget) {
     for (const char* const* e = docEvents,
                    * const* e_end = docEvents + NS_ARRAY_LENGTH(docEvents);
          e < e_end; ++e) {
       nsresult rv = nstarget->AddEventListener(NS_ConvertASCIItoUTF16(*e),
                                                this, PR_TRUE, PR_TRUE, 2);
       NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -514,17 +514,17 @@ PRUint32 nsTextEquivUtils::gRoleToNameRu
   eNoRule,           // ROLE_VIEWPORT
   eNoRule,           // ROLE_HEADER
   eNoRule,           // ROLE_FOOTER
   eFromSubtreeIfRec, // ROLE_PARAGRAPH
   eNoRule,           // ROLE_RULER
   eNoRule,           // ROLE_AUTOCOMPLETE
   eNoRule,           // ROLE_EDITBAR
   eFromValue,        // ROLE_ENTRY
-  eNoRule,           // ROLE_CAPTION
+  eFromSubtreeIfRec, // ROLE_CAPTION
   eNoRule,           // ROLE_DOCUMENT_FRAME
   eFromSubtreeIfRec, // ROLE_HEADING
   eNoRule,           // ROLE_PAGE
   eFromSubtreeIfRec, // ROLE_SECTION
   eNoRule,           // ROLE_REDUNDANT_OBJECT
   eNoRule,           // ROLE_FORM
   eNoRule,           // ROLE_IME
   eNoRule,           // ROLE_APP_ROOT
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -459,20 +459,32 @@ nsHTMLTableAccessible::NativeState()
 {
   return nsAccessible::NativeState() | states::READONLY;
 }
 
 nsresult
 nsHTMLTableAccessible::GetNameInternal(nsAString& aName)
 {
   nsAccessible::GetNameInternal(aName);
+  if (!aName.IsEmpty())
+    return NS_OK;
 
-  if (aName.IsEmpty())
-    mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary, aName);
+  // Use table caption as a name.
+  nsAccessible* caption = Caption();
+  if (caption) {
+    nsIContent* captionContent = caption->GetContent();
+    if (captionContent) {
+      nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
+      if (!aName.IsEmpty())
+        return NS_OK;
+    }
+  }
 
+  // If no caption then use summary as a name.
+  mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary, aName);
   return NS_OK;
 }
 
 nsresult
 nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -494,35 +506,31 @@ nsHTMLTableAccessible::GetAttributesInte
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetRelationByType(PRUint32 aRelationType,
                                          nsIAccessibleRelation **aRelation)
 {
   nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType,
                                                     aRelation);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIBED_BY) {
-    nsCOMPtr<nsIAccessible> accCaption;
-    GetCaption(getter_AddRefs(accCaption));
-    return nsRelUtils::AddTarget(aRelationType, aRelation, accCaption);
-  }
+  if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIBED_BY)
+    return nsRelUtils::AddTarget(aRelationType, aRelation, Caption());
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessibleTable implementation
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
 {
-  nsAccessible* firstChild = GetChildAt(0);
-  if (firstChild && firstChild->Role() == nsIAccessibleRole::ROLE_CAPTION)
-    NS_ADDREF(*aCaption = firstChild);
+  NS_ENSURE_ARG_POINTER(aCaption);
 
+  NS_IF_ADDREF(*aCaption = Caption());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetSummary(nsAString &aSummary)
 {
   nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
@@ -1263,27 +1271,33 @@ void
 nsHTMLTableAccessible::Description(nsString& aDescription)
 {
   // Helpful for debugging layout vs. data tables
   aDescription.Truncate();
   nsAccessible::Description(aDescription);
   if (!aDescription.IsEmpty())
     return;
 
-  nsCOMPtr<nsIAccessible> captionAccessible;
-  GetCaption(getter_AddRefs(captionAccessible));
-  nsCOMPtr<nsIAccessNode> captionAccessNode = do_QueryInterface(captionAccessible);
-  if (captionAccessNode) {
-    nsCOMPtr<nsIDOMNode> captionNode;
-    captionAccessNode->GetDOMNode(getter_AddRefs(captionNode));
-    nsCOMPtr<nsIContent> captionContent = do_QueryInterface(captionNode);
-    if (captionContent)
+  // Use summary as description if it weren't used as a name.
+  // XXX: get rid code duplication with NameInternal().
+  nsAccessible* caption = Caption();
+  if (caption) {
+    nsIContent* captionContent = caption->GetContent();
+    if (captionContent) {
+      nsAutoString captionText;
       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent,
-                                                   &aDescription);
+                                                   &captionText);
+
+      if (!captionText.IsEmpty()) { // summary isn't used as a name.
+        mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary,
+                          aDescription);
+      }
+    }
   }
+
 #ifdef SHOW_LAYOUT_HEURISTIC
   if (aDescription.IsEmpty()) {
     PRBool isProbablyForLayout;
     IsProbablyForLayout(&isProbablyForLayout);
     aDescription = mLayoutHeuristic;
   }
 #ifdef DEBUG_A11Y
   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -136,16 +136,24 @@ public:
 
   // nsAccessible
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
+  // TableAccessible
+  inline nsAccessible* Caption() const
+  {
+    nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
+    return child && child->Role() == nsIAccessibleRole::ROLE_CAPTION ?
+      child : nsnull;
+  }
+
   // nsHTMLTableAccessible
 
   /**
    * Retun cell element at the given row and column index.
    */
   nsresult GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex,
                      nsIDOMElement* &aCell);
 
--- a/accessible/src/msaa/nsRootAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsRootAccessibleWrap.cpp
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsRootAccessibleWrap.h"
 
 #include "nsWinUtils.h"
 
 #include "nsIDOMEventTarget.h"
-#include "nsIEventListenerManager.h"
+#include "nsEventListenerManager.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 nsRootAccessibleWrap::
   nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
                        nsIWeakReference* aShell) :
   nsRootAccessible(aDocument, aRootContent, aShell)
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -48,38 +48,41 @@ https://bugzilla.mozilla.org/show_bug.cg
       // ARIA
       testAttrs("live", {"live" : "polite"}, true);
       testAttrs("live2", {"live" : "polite"}, true);
       testAbsentAttrs("live3", {"live" : ""});
       testAttrs("log", {"live" : "polite"}, true);
       testAttrs("logAssertive", {"live" : "assertive"}, true);
       testAttrs("marquee", {"live" : "off"}, true);
       testAttrs("status", {"live" : "polite"}, true);
+      testAttrs("tablist", {"live" : "polite"}, true);
       testAttrs("timer", {"live" : "off"}, true);
 
       // container-live object attribute
       testAttrs("liveChild", {"container-live" : "polite"}, true);
       testAttrs("live2Child", {"container-live" : "polite"}, true);
       testAttrs("logChild", {"container-live" : "polite"}, true);
       testAttrs("logAssertiveChild", {"container-live" : "assertive"}, true);
       testAttrs("marqueeChild", {"container-live" : "off"}, true);
       testAttrs("statusChild", {"container-live" : "polite"}, true);
+      testAttrs("tablistChild", {"container-live" : "polite"}, true);
       testAttrs("timerChild", {"container-live" : "off"}, true);
 
       // container-live-role object attribute
       testAttrs("log", {"container-live-role" : "log"}, true);
       testAttrs("logAssertive", {"container-live-role" : "log"}, true);
       testAttrs("marquee", {"container-live-role" : "marquee"}, true);
       testAttrs("status", {"container-live-role" : "status"}, true);
       testAttrs("timer", {"container-live-role" : "timer"}, true);
       testAttrs("logChild", {"container-live-role" : "log"}, true);
       testAttrs("logAssertive", {"container-live-role" : "log"}, true);
       testAttrs("logAssertiveChild", {"container-live-role" : "log"}, true);
       testAttrs("marqueeChild", {"container-live-role" : "marquee"}, true);
       testAttrs("statusChild", {"container-live-role" : "status"}, true);
+      testAttrs("tablistChild", {"container-live-role" : "tablist"}, true);
       testAttrs("timerChild", {"container-live-role" : "timer"}, true);
 
       // absent aria-label and aria-labelledby object attribute
       testAbsentAttrs("label", {"label" : "foo"});
       testAbsentAttrs("labelledby", {"labelledby" : "label"});
 
       // container that has no default live attribute
       testAttrs("liveGroup", {"live" : "polite"}, true);
@@ -115,17 +118,21 @@ https://bugzilla.mozilla.org/show_bug.cg
      title="Make explicit that aria-label is not an object attribute">
     Mozilla Bug 475006
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=558036"
      title="make HTML <output> accessible">
     Mozilla Bug 558036
   </a>
-
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=663136"
+     title="Add test coverage for tablist as implicit live region">
+    Mozilla Bug 663136
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <!-- aria -->
   <div id="atomic" aria-atomic="true"></div>
   <div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
@@ -149,16 +156,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- back to aria -->
   <div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
   <div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
   <div id="live3" role="region">excuse</div>
   <div id="log" role="log">excuse <div id="logChild">me</div></div>
   <div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
   <div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
   <div id="status" role="status">excuse <div id="statusChild">me</div></div>
+  <div id="tablist" role="tablist">tablist <div id="tablistChild">tab</div></div>
   <div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
 
   <!-- aria-label[ledby] should not be an object attribute -->
   <div id="label" role="checkbox" aria-label="foo"></div>
   <div id="labelledby" role="checkbox" aria-labelledby="label"></div>
 
   <!-- unusual live case -->
   <div id="liveGroup" role="group" aria-live="polite">
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -2,17 +2,16 @@
 // Name tests described by "markuprules.xml" file.
 
 var gNameRulesFileURL = "markuprules.xml";
 
 var gRuleDoc = null;
 
 // Debuggin stuff.
 var gDumpToConsole = false;
-gA11yEventDumpToConsole = gDumpToConsole;
 
 /**
  * Start name tests. Run through markup elements and test names for test
  * element (see namerules.xml for details).
  */
 function testNames()
 {
   var request = new XMLHttpRequest();
@@ -144,17 +143,17 @@ function testNameForRule(aElm, aRuleElm)
 {
   if (aRuleElm.hasAttribute("attr")) {
     if (gDumpToConsole) {
       dump("\nProcessing rule { attr: " + aRuleElm.getAttribute("attr") +" }\n");
     }
 
     testNameForAttrRule(aElm, aRuleElm);
 
-  } else if (aRuleElm.hasAttribute("elm") && aRuleElm.hasAttribute("elmattr")) {
+  } else if (aRuleElm.hasAttribute("elm")) {
     if (gDumpToConsole) {
       dump("\nProcessing rule { elm: " + aRuleElm.getAttribute("elm") +
            ", elmattr: " + aRuleElm.getAttribute("elmattr") +" }\n");
     }
 
     testNameForElmRule(aElm, aRuleElm);
 
   } else if (aRuleElm.getAttribute("fromsubtree") == "true") {
@@ -173,17 +172,17 @@ function testNameForAttrRule(aElm, aRule
 
   var attr = aRule.getAttribute("attr");
   var attrValue = aElm.getAttribute(attr);
 
   var type = aRule.getAttribute("type");
   if (type == "string") {
     name = attrValue;
 
-  } else if (type == "ref") {
+  } else if (type == "ref" && attrValue) {
     var ids = attrValue.split(/\s+/);
     for (var idx = 0; idx < ids.length; idx++) {
       var labelElm = getNode(ids[idx]);
       if (name != "")
         name += " ";
 
       name += labelElm.getAttribute("a11yname");
     }
@@ -192,47 +191,63 @@ function testNameForAttrRule(aElm, aRule
   var msg = "Attribute '" + attr + "' test. ";
   testName(aElm, name, msg);
   aElm.removeAttribute(attr);
 
   gTestIterator.iterateNext();
 }
 
 function testNameForElmRule(aElm, aRule)
-{  
-  var elm = aRule.getAttribute("elm");
-  var elmattr = aRule.getAttribute("elmattr");
+{
+  var labelElm;
 
-  var filter = {
-    acceptNode: function filter_acceptNode(aNode)
-    {
-      if (aNode.localName == this.mLocalName &&
-          aNode.getAttribute(this.mAttrName) == this.mAttrValue)
-        return NodeFilter.FILTER_ACCEPT;
+  var tagname = aRule.getAttribute("elm");
+  var attrname = aRule.getAttribute("elmattr");
+  if (attrname) {
+    var filter = {
+      acceptNode: function filter_acceptNode(aNode)
+      {
+        if (aNode.localName == this.mLocalName &&
+            aNode.getAttribute(this.mAttrName) == this.mAttrValue)
+          return NodeFilter.FILTER_ACCEPT;
+
+        return NodeFilter.FILTER_SKIP;
+      },
 
-      return NodeFilter.FILTER_SKIP;
-    },
+      mLocalName: tagname,
+      mAttrName: attrname,
+      mAttrValue: aElm.getAttribute("id")
+    };
+
+    var treeWalker = document.createTreeWalker(document.body,
+                                               NodeFilter.SHOW_ELEMENT,
+                                               filter, false);
+    labelElm = treeWalker.nextNode();
 
-    mLocalName: elm,
-    mAttrName: elmattr,
-    mAttrValue: aElm.getAttribute("id")
-  };
+  } else {
+    // if attrname is empty then look for the element in subtree.
+    labelElm = aElm.getElementsByTagName(tagname)[0];
+    if (!labelElm)
+      labelElm = aElm.getElementsByTagName("html:" + tagname)[0];
+  }
 
-  var treeWalker = document.createTreeWalker(document.body,
-                                             NodeFilter.SHOW_ELEMENT,
-                                             filter, false);
-  var labelElm = treeWalker.nextNode();
-  var msg = "Element '" + elm + "' test.";
+  if (!labelElm) {
+    ok(false, msg + " Failed to find '" + tagname + "' element.");
+    gTestIterator.iterateNext();
+    return;
+  }
+
+  var msg = "Element '" + tagname + "' test.";
   testName(aElm, labelElm.getAttribute("a11yname"), msg);
 
   var parentNode = labelElm.parentNode;
 
   if (gDumpToConsole) {
     dump("\nProcessed elm rule. Wait for reorder event on " +
-         prettyName(parentNode) + "'\n");
+         prettyName(parentNode) + "\n");
   }
   waitForEvent(EVENT_REORDER, parentNode,
                gTestIterator.iterateNext, gTestIterator);
 
   parentNode.removeChild(labelElm);
 }
 
 function testNameForSubtreeRule(aElm, aRule)
--- a/accessible/tests/mochitest/name/markuprules.xml
+++ b/accessible/tests/mochitest/name/markuprules.xml
@@ -1,36 +1,55 @@
 <?xml version="1.0"?>
 
 <!--
- This XML file is used to create sequence of accessible name tests. It consist of
- two sections. The first section 'ruledfn' declares name computation rules.
- The second section 'rulesample' defines markup samples we need to check name
- computation rules for.
+  This XML file is used to create sequence of accessible name tests. It consist
+  of two sections. The first section 'ruledfn' declares name computation rules.
+  The second section 'rulesample' defines markup samples we need to check name
+  computation rules for.
 
-  Section 'ruledfn' consist of 'ruleset' elements. Every 'ruleset' element is
+  <ruledfn>
+    <ruleset>
+      <rule>
+
+  Section 'ruledfn' contains 'ruleset' elements. Every 'ruleset' element is
   presented by 'rule' elements so that sequence of 'rule' elements gives the
   sequence of name computations rules. Every 'rule' element can be one of four
   types.
-   * name is equal to the value of attribute presented on the element. Example,
-     'aria-label' attribute. In this case 'rule' element has 'attr' attribute
-     pointing to attribute name and 'type' attribute with 'string' value. For
-     example, <rule attr="aria-label" type="string"/>.
-   * name is calculated from elements that are pointed to by attribute value on
-     the element. Example is 'aria-labelledby'. In this case 'rule' element
-     has 'attr' attribute holding the sequence of IDs of elements used to
-     compute the name, in addition the 'rule' element has 'type' attribute with
-     'ref' value. For example, <rule attr="aria-labelledby" type="ref"/>.
-   * name is calculated from another element. Example, html:label@for element.
-     In this case 'rule' element has 'elm' and 'elmattr' attributes. These
-     attributes are used to find an element by tagname and attribute with value
-     equaled to ID of the element. For example, <rule elm="label" elmattr="for"/>.
-   * name is computed from subtree. Example, html:button. In this case 'rule'
-     element has 'fromsubtree' attribute with 'true' value. For example,
-     <rule fromsubtree="true"/>
+
+   * <rule attr='' type='string'/> used when name is equal to the value of
+     attribute presented on the element.
+
+     Example, 'aria-label' attribute. In this case 'rule' element has 'attr'
+     attribute pointing to attribute name and 'type' attribute with 'string'
+     value. For example, <rule attr="aria-label" type="string"/>.
+
+   * <rule attr='' type='ref'/> used when name is calculated from elements that
+     are pointed to by attribute value on the element.
+
+     Example is 'aria-labelledby'. In this case 'rule' element has 'attr'
+     attribute holding the sequence of IDs of elements used to compute the name,
+     in addition the 'rule' element has 'type' attribute with 'ref' value.
+     For example, <rule attr="aria-labelledby" type="ref"/>.
+
+   * <rule elm='' elmattr=''/> used when name is calculated from another
+     element. These attributes are used to find an element by tagname and
+     attribute with value equaled to ID of the element. If 'elmattr' is missed
+     then element from subtree with the given tagname is used.
+
+     Example, html:label@for element, <rule elm="label" elmattr="for"/>.
+     Example, html:caption element, <rule elm="caption"/>
+
+   * <rule fromsubtree='true'/> used when name is computed from subtree.
+
+     Example, html:button. In this case 'rule' element has 'fromsubtree'
+     attribute with 'true' value.
+
+  <rulesample>
+    <markup ruleset=''>
 
   Section 'rulesample' provides set of markup samples ('markup' elements). Every
   'markup' element contains an element that accessible name will be computed for
   (let's call it test element). In addition the 'markup' element contains some
   other elements from native markup used in name calculation process for test
   element. Test element is pointed to by 'ref' attribute on 'markup' element.
   Also 'markup' element has 'ruleset' attribute to indicate ruleset for the test
   element.
@@ -115,16 +134,22 @@
 
     <ruleset id="htmloption">
       <ruleset ref="aria"/>
       <rule attr="label" type="string"/>
       <rule fromsubtree="true"/>
       <rule attr="title" type="string"/>
     </ruleset>
 
+    <ruleset id="htmltable">
+      <ruleset ref="htmlelm_start"/>
+      <rule elm="caption"/>
+      <rule attr="summary" type="string"/>
+      <ruleset ref="htmlelm_end"/>
+    </ruleset>
   </ruledfn>
 
   <rulesample>
 
     <markup ref="html:button" ruleset="htmlctrl" id="markup1test">
       <html:span id="l1" a11yname="test2">test2</html:span>
       <html:span id="l2" a11yname="test3">test3</html:span>
       <html:label for="btn" a11yname="test4">test4</html:label>
@@ -205,11 +230,30 @@
               <html:li>Listitem1</html:li>
               <html:li>Listitem2</html:li>
             </html:ul>
           </html:td>
         </html:tr>
       </html:table>
     </markup>
 
+    <markup ref="html:table" ruleset="htmltable"
+            id="markup6test">
+      <html:span id="l1" a11yname="lby_tst6_1">lby_tst6_1</html:span>
+      <html:span id="l2" a11yname="lby_tst6_2">lby_tst6_2</html:span>
+      <html:label for="t" a11yname="label_tst6">label_tst6</html:label>
+      <!-- layout frame are recreated due to varous reasons, here's text frame
+          placed after caption frame triggres table frame recreation when
+          caption element is removed from DOM; get rid text node after caption
+          node to make the test working -->
+      <html:table id="t" aria-label="arialabel_tst6"
+                  aria-labelledby="l1 l2"
+                  summary="summary_tst6"
+                  title="title_tst6">
+        <html:caption a11yname="caption_tst6">caption_tst6</html:caption><html:tr>
+          <html:td>cell1</html:td>
+          <html:td>cell2</html:td>
+        </html:tr>
+      </html:table>
+    </markup>
   </rulesample>
 
 </rules>
--- a/accessible/tests/mochitest/name/test_markup.html
+++ b/accessible/tests/mochitest/name/test_markup.html
@@ -16,30 +16,38 @@
   <script type="application/javascript"
           src="../name.js"></script>
 
   <script type="application/javascript"
           src="markup.js"></script>
 
   <script type="application/javascript">
     // gA11yEventDumpID = "eventdump";
+    //gDumpToConsole = true;
+    //gA11yEventDumpToConsole = true;
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(testNames);
   </script>
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=459635"
      title="nsIAccessible::name calculation for elements">
     Mozilla Bug 459635
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=666212"
+     title="summary attribute content mapped to accessible name in MSAA">
+    Mozilla Bug 666212
+  </a>
+
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="eventdump"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_descr.html
+++ b/accessible/tests/mochitest/test_descr.html
@@ -33,38 +33,65 @@
 
       // Description from @title attribute, name is generated from @alt
       // attribute.
       testDescr("img3", "description");
 
       // Description from content of h2.
       testDescr("p", "heading");
 
+      // From table summary (caption is used as a name)
+      testDescr("table1", "summary");
+
+      // Empty (summary is used as a name)
+      testDescr("table2", "");
+
+      // From title (summary is used as a name)
+      testDescr("table3", "title");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=489944"
      title="@title attribute no longer exposed on accDescription">
     Mozilla Bug 489944
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=666212"
+     title="summary attribute content mapped to accessible name in MSAA">
+    Mozilla Bug 666212
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="description">aria description</p>
   <img id="img1" aria-describedby="description" />
   <img id="img2" title="title" />
   <img id="img3" alt="name" title="description" />
 
   <h2 id="heading">heading</h2>
   <p id="p" aria-describedby="heading" role="button">click me</p>
+
+  <table id="table1" summary="summary">
+    <caption>caption</caption>
+    <tr><td>cell</td></tr>
+  </table>
+
+  <table id="table2" summary="summary">
+    <tr><td>cell</td></tr>
+  </table>
+
+  <table id="table3" summary="summary" title="title">
+    <tr><td>cell</td></tr>
+  </table>
 </body>
 </html>
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -86,45 +86,32 @@ endif
 
 LIBS += $(JEMALLOC_LIBS)
 
 ifdef LIBXUL_SDK
 include $(topsrcdir)/config/rules.mk
 else
 # Build a binary bootstrapping with XRE_main
 
-ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
-else
-PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
-endif
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
+LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
 
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-LIBS += $(DIST)/bin/XUL
-TK_LIBS := $(TK_LIBS)
-else
-EXTRA_DSO_LIBS += xul
-endif
+DEFINES += -DXPCOM_GLUE
+STL_FLAGS=
 
 LIBS += \
-	$(STATIC_COMPONENTS_LINKER_PATH) \
 	$(EXTRA_DSO_LIBS) \
-	$(XPCOM_GLUE_LDOPTS) \
-	$(NSPR_LIBS) \
+	$(XPCOM_STANDALONE_GLUE_LDOPTS) \
 	$(NULL)
 
-ifdef MOZ_JPROF
-LIBS += -ljprof
-endif
-
 ifndef MOZ_WINCONSOLE
 ifdef MOZ_DEBUG
 MOZ_WINCONSOLE = 1
 else
 MOZ_WINCONSOLE = 0
 endif
 endif
 
@@ -189,28 +176,19 @@ ifeq ($(OS_TEST),x86_64)
 # set stack to 2MB on x64 build.  See bug 582910
 LDFLAGS += -STACK:2097152
 endif
 endif
 endif
 
 ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
 
-$(MOZ_APP_NAME):: $(topsrcdir)/build/unix/mozilla.in $(GLOBAL_DEPS)
-	cat $< | sed -e "s|%MOZAPPDIR%|$(installdir)|" \
-		-e "s|%MOZ_APP_DISPLAYNAME%|$(MOZ_APP_DISPLAYNAME)|" > $@
-	chmod +x $@
+libs:: 
+	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 
-libs:: $(MOZ_APP_NAME)
-	$(INSTALL) $< $(DIST)/bin
-
-install:: $(MOZ_APP_NAME)
-	$(SYSINSTALL) $< $(DESTDIR)$(bindir)
-
-GARBAGE += $(MOZ_APP_NAME)
 GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js)
 
 endif
 
 endif # LIBXUL_SDK
 
 DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\"
 
@@ -268,17 +246,17 @@ libs repackage:: $(PROGRAM) application.
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%LOWER_APP_NAME%/$(LOWER_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
 ifdef LIBXUL_SDK
-	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox-bin
+	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox
 else
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
 endif
 	-cp -L $(DIST)/bin/mangle $(DIST)/bin/shlibsign $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	cp -RL $(DIST)/branding/firefox.icns $(DIST)/$(APP_NAME).app/Contents/Resources/firefox.icns
 	cp -RL $(DIST)/branding/document.icns $(DIST)/$(APP_NAME).app/Contents/Resources/document.icns
 	printf APPLMOZB > $(DIST)/$(APP_NAME).app/Contents/PkgInfo
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -138,17 +138,17 @@
 			</array>
 			<key>CFBundleTypeName</key>
 			<string>HTML5 Video (WebM)</string>
 			<key>CFBundleTypeRole</key>
 			<string>Viewer</string>
 		</dict>
 	</array>
 	<key>CFBundleExecutable</key>
-	<string>firefox-bin</string>
+	<string>firefox</string>
 	<key>CFBundleGetInfoString</key>
 	<string>%APP_NAME% %APP_VERSION%</string>
 	<key>CFBundleIconFile</key>
 	<string>firefox</string>
 	<key>CFBundleIdentifier</key>
 	<string>org.mozilla.%LOWER_APP_NAME%</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -31,39 +31,49 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "nsXPCOMGlue.h"
 #include "nsXULAppAPI.h"
-#ifdef XP_WIN
+#if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
+#elif defined(XP_UNIX)
+#include <sys/time.h>
+#include <sys/resource.h>
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 
 #include "plstr.h"
 #include "prprf.h"
 #include "prenv.h"
 
 #include "nsCOMPtr.h"
 #include "nsILocalFile.h"
 #include "nsStringGlue.h"
 
 #ifdef XP_WIN
-// we want to use the DLL blocklist if possible
-#define XRE_WANT_DLL_BLOCKLIST
 // we want a wmain entry point
 #include "nsWindowsWMain.cpp"
+#define snprintf _snprintf
+#define strcasecmp _stricmp
 #endif
+#include "BinaryPath.h"
+
+#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
+
+#include "mozilla/Telemetry.h"
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   PRUnichar msg[2048];
@@ -80,53 +90,79 @@ static void Output(const char *fmt, ... 
  * Return true if |arg| matches the given argument name.
  */
 static PRBool IsArg(const char* arg, const char* s)
 {
   if (*arg == '-')
   {
     if (*++arg == '-')
       ++arg;
-    return !PL_strcasecmp(arg, s);
+    return !strcasecmp(arg, s);
   }
 
 #if defined(XP_WIN) || defined(XP_OS2)
   if (*arg == '/')
-    return !PL_strcasecmp(++arg, s);
+    return !strcasecmp(++arg, s);
 #endif
 
   return PR_FALSE;
 }
 
 /**
  * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  */
 class ScopedLogging
 {
 public:
   ScopedLogging() { NS_LogInit(); }
   ~ScopedLogging() { NS_LogTerm(); }
 };
 
-int main(int argc, char* argv[])
-{
-  ScopedLogging log;
+XRE_GetFileFromPathType XRE_GetFileFromPath;
+XRE_CreateAppDataType XRE_CreateAppData;
+XRE_FreeAppDataType XRE_FreeAppData;
+#ifdef XRE_HAS_DLL_BLOCKLIST
+XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
+#endif
+XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
+XRE_mainType XRE_main;
 
+static const nsDynamicFunctionLoad kXULFuncs[] = {
+    { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
+    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
+    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
+#ifdef XRE_HAS_DLL_BLOCKLIST
+    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
+#endif
+    { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
+    { "XRE_main", (NSFuncPtr*) &XRE_main },
+    { nsnull, nsnull }
+};
+
+static int do_main(const char *exePath, int argc, char* argv[])
+{
   nsCOMPtr<nsILocalFile> appini;
-  nsresult rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appini));
+#ifdef XP_WIN
+  // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
+  // encoded path, so it is safe to convert it
+  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
+                                getter_AddRefs(appini));
+#else
+  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
+                                      getter_AddRefs(appini));
+#endif
   if (NS_FAILED(rv)) {
-    Output("Couldn't calculate the application directory.");
     return 255;
   }
+
   appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
-  char *appEnv = nsnull;
-  const char *appDataFile = PR_GetEnv("XUL_APP_FILE");
+  const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("Invalid path found: '%s'", appDataFile);
       return 255;
     }
   }
   else if (argc > 1 && IsArg(argv[1], "app")) {
@@ -136,28 +172,115 @@ int main(int argc, char* argv[])
     }
 
     rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("application.ini path not recognized: '%s'", argv[2]);
       return 255;
     }
 
-    appEnv = PR_smprintf("XUL_APP_FILE=%s", argv[2]);
-    PR_SetEnv(appEnv);
+    char appEnv[MAXPATHLEN];
+    snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
+    if (putenv(appEnv)) {
+      Output("Couldn't set %s.\n", appEnv);
+      return 255;
+    }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   }
 
   nsXREAppData *appData;
   rv = XRE_CreateAppData(appini, &appData);
   if (NS_FAILED(rv)) {
     Output("Couldn't read application.ini");
     return 255;
   }
 
   int result = XRE_main(argc, argv, appData);
   XRE_FreeAppData(appData);
-  if (appEnv)
-    PR_smprintf_free(appEnv);
   return result;
 }
+
+int main(int argc, char* argv[])
+{
+  char exePath[MAXPATHLEN];
+
+  nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't calculate the application directory.\n");
+    return 255;
+  }
+
+  char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
+  if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
+    return 255;
+
+  strcpy(++lastSlash, XPCOM_DLL);
+
+  int gotCounters;
+#if defined(XP_UNIX)
+  struct rusage initialRUsage;
+  gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
+#elif defined(XP_WIN)
+  // GetProcessIoCounters().ReadOperationCount seems to have little to
+  // do with actual read operations. It reports 0 or 1 at this stage
+  // in the program. Luckily 1 coincides with when prefetch is
+  // enabled. If Windows prefetch didn't happen we can do our own
+  // faster dll preloading.
+  IO_COUNTERS ioCounters;
+  gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
+  if (gotCounters && !ioCounters.ReadOperationCount)
+#endif
+  {
+      XPCOMGlueEnablePreload();
+  }
+
+
+  rv = XPCOMGlueStartup(exePath);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XPCOM.\n");
+    return 255;
+  }
+
+  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XRE functions.\n");
+    return 255;
+  }
+
+#ifdef XRE_HAS_DLL_BLOCKLIST
+  XRE_SetupDllBlocklist();
+#endif
+
+  if (gotCounters) {
+#if defined(XP_WIN)
+    XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
+                            int(ioCounters.ReadOperationCount));
+    XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER,
+                            int(ioCounters.ReadTransferCount / 1024));
+    IO_COUNTERS newIoCounters;
+    if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) {
+      XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_OPS,
+                              int(newIoCounters.ReadOperationCount - ioCounters.ReadOperationCount));
+      XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_READ_TRANSFER,
+                              int((newIoCounters.ReadTransferCount - ioCounters.ReadTransferCount) / 1024));
+    }
+#elif defined(XP_UNIX)
+    XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_HARD_FAULTS,
+                            int(initialRUsage.ru_majflt));
+    struct rusage newRUsage;
+    if (!getrusage(RUSAGE_SELF, &newRUsage)) {
+      XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS,
+                              int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
+    }
+#endif
+  }
+
+  int result;
+  {
+    ScopedLogging log;
+    result = do_main(exePath, argc, argv);
+  }
+
+  XPCOMGlueShutdown();
+  return result;
+}
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -161,20 +161,16 @@ pref("app.update.url", "https://aus3.moz
 // app.update.url.manual is in branding section
 // app.update.url.details is in branding section
 
 // User-settable override to app.update.url for testing purposes.
 //pref("app.update.url.override", "");
 
 // app.update.interval is in branding section
 
-// Interval: Time before prompting the user again to restart to install the
-//           latest download (in seconds) default=1 day
-pref("app.update.nagTimer.restart", 86400);
-
 // Give the user x seconds to react before showing the big UI. default=12 hours
 pref("app.update.promptWaitTime", 43200);
 // Show the Update Checking/Ready UI when the user was idle for x seconds
 pref("app.update.idletime", 60);
 
 // Whether or not we show a dialog box informing the user that the update was
 // successfully applied. This is off in Firefox by default since we show a 
 // upgrade start page instead! Other apps may wish to show this UI, and supply
@@ -296,16 +292,17 @@ pref("browser.urlbar.match.url", "@");
 // more (intersection). Add the following values to set the behavior as the
 // default: 1: history, 2: bookmark, 4: tag, 8: title, 16: url, 32: typed,
 //          64: javascript, 128: tabs
 // E.g., 0 = show all results (no filtering), 1 = only visited pages in history,
 // 2 = only bookmarks, 3 = visited bookmarks, 1+16 = history matching in the url
 pref("browser.urlbar.default.behavior", 0);
 
 pref("browser.urlbar.formatting.enabled", true);
+pref("browser.urlbar.trimURLs", true);
 
 // Number of milliseconds to wait for the http headers (and thus
 // the Content-Disposition filename) before giving up and falling back to 
 // picking a filename without that info in hand so that the user sees some
 // feedback from their action.
 pref("browser.download.saveLinkAsFilenameTimeout", 1000);
 
 pref("browser.download.useDownloadDir", true);
@@ -859,19 +856,16 @@ pref("browser.zoom.siteSpecific", true);
 pref("browser.zoom.updateBackgroundTabs", true);
 
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
 
 // base URL for web-based support pages
 pref("app.support.baseURL", "http://support.mozilla.com/1/firefox/%VERSION%/%OS%/%LOCALE%/");
 
-// URL for web-based support page on how to upgrade a graphics driver
-pref("app.support.updateGraphicsDriverURL", "http://support.mozilla.com/%LOCALE%/kb/how-do-i-upgrade-my-graphics-drivers");
-
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 // Whether to start the private browsing mode at application startup
 pref("browser.privatebrowsing.autostart", false);
 
 // Whether we should skip prompting before starting the private browsing mode
 pref("browser.privatebrowsing.dont_prompt_on_enter", false);
--- a/browser/base/content/aboutDialog.css
+++ b/browser/base/content/aboutDialog.css
@@ -16,16 +16,19 @@
 
 #bottomBox {
   padding: 15px 10px 0;
 }
 
 #version {
   margin-top: 10px;
   -moz-margin-start: 0;
+  -moz-user-select: text;
+  -moz-user-focus: normal;
+  cursor: text;
 }
 
 #distribution,
 #distributionId {
   font-weight: bold;
   display: none;
   margin-top: 0;
   margin-bottom: 0;
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -65,17 +65,17 @@ function init(aEvent)
     // Pref is unset
   }
 
   // Include the build ID if this is an "a#" (nightly or aurora) build
   let version = Services.appinfo.version;
   if (/a\d+$/.test(version)) {
     let buildID = Services.appinfo.appBuildID;
     let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8);
-    document.getElementById("version").value += " (" + buildDate + ")";
+    document.getElementById("version").textContent += " (" + buildDate + ")";
   }
 
 #ifdef MOZ_OFFICIAL_BRANDING
   // Hide the Charlton trademark attribution for non-en-US/en-GB
   // DO NOT REMOVE without consulting people involved with bug 616193
   let chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
                        getService(Components.interfaces.nsIXULChromeRegistry);
   let currentLocale = chromeRegistry.getSelectedLocale("global");
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -71,17 +71,17 @@
         >
 
   <script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>
 
   <vbox id="aboutDialogContainer">
     <hbox id="clientBox">
       <vbox id="leftBox" flex="1"/>
       <vbox id="rightBox" flex="1">
-#expand <label id="version" value="__MOZ_APP_VERSION__"/>
+#expand <label id="version">__MOZ_APP_VERSION__</label>
         <label id="distribution" class="text-blurb"/>
         <label id="distributionId" class="text-blurb"/>
 
         <vbox id="detailsBox" aria-describedby="communityDesc contributeDesc">
           <vbox id="updateBox">
 #ifdef MOZ_UPDATER
             <deck id="updateDeck" orient="vertical">
               <hbox id="updateButtonBox" align="center">
new file mode 100644
index 0000000000000000000000000000000000000000..22a260da2c5838e2547dc40464fc22c599113881
GIT binary patch
literal 1866
zc$@)B2etT#P)<h;3K|Lk000e1NJLTq001Ze001%w1^@s6F0+}C000LONkl<ZcwWtx
zYiv|S6vxlq-4+U}0Kq5<)$qX&n4nQjFws~LM2$vCl=wl!5J41!L?EJ2iuFUI5+N8~
zCLpDVKvPtaNReO)6qFXAu>gfWwy)i7yW8DuxBI$xuIJ9o?%dtG>Ajmm<uw1ybUSnQ
zH)rNQ9UI){F(}|$<*hSNi%^?U+i!tBM=d~2$O=%KfU3ssanyFyQq-bbpf6FoQ0-bF
zECZ^lx&<{I1;eCV)Rs5*UVq9Ia8Aje_o@J|qkxJLgOn7x3Bs%@%dYz#JJ@UsO#zYU
zag?3YCBXzF3{hgiKv-W?0;XFr$+$%6Aw|Sg`FA^D@ss0WlmiAGC!s`6-BuHFk13$4
z#P8xu;u8g|O0Xp)lMpTk))Y*HXCJx~+xr+~=CKGO;HV&}JX1g=9&@B_FJCcH#mdu^
zKPDH}%(x#$<+617V@I&xbEJ&pGv}e^luQ8$QEV!RA2SC|*5GD7z~Mw7B>g-OAv4ZR
z15EswZ!sZ~I4&x0#TE-OxV6tu(!&`b*Up>-c@9a;6B4lEh?@fnONrI7M%9ab`78sR
z5po<Kmtz}rCjd}cT+~dWZ-kpY2}bAI!Ad+hZX}LRg%s`uy_2m03Q!bpxe#t76uvOo
zGMs><^AOUm&&SM>)nh@N2XXFLi*6kO>*ff!7Edp%-*XK9y408v>W9i2*jRBA{Qcns
zB%MFXVM{%SB&#!MbTII3EqW<GrE&$IY=xrIN+?*djl$~V=jwWR_v`(zeCw}N`brkP
zn4h}cV8z8opKw4-ig4=%TvGl}MD$sejK7P%fE>>tN9WiDB;zy#<ZNjN_>IRVK(jYO
zrH@@J=fQK+ra;mB+3@I;iJ*@Kv!8&E=RO0kJv|lH;oo&Z^MqmwygYTRxGXH2MDGd?
zT2kqRwZApN&gxD*1O4(7-@Fg&-kt@S;@c&!!lCsG4DgtT=KHC(EB(T@c+H4P8kB8V
z$}c|4{vIUQQW*iMd!<<`&6FvBdS0troc_Y19o{zr@~umk=@@=(iTqTwYt_Z+6GdMi
zWA4bKMi?xX8UC&}gaFIp4C+hHSE;*H(*q4coy;TM$y8}!e28SV#X_`WcpibVis)o|
z<sb}&#Wwj_S{RGK`qoWie4|-&F+x!w4n{#UhjGzji;0B_DkRk;Y45h7M|xgJLK0cA
z02q&^99TA=b=-j{l%44qvM>+N%LN=V7BvTy!y!VHINw}8nYZp>1WK#hQEgCqI(y+<
zDo>CCvXI0RMeYj_a~BiRAM?1_agZdMK}}|n#B+?csuhV!@p1_`O2@W08Uxwa-De6I
z8wfPZ{vL>SHshoSj<BH+GSO0I(|?JES2+u9zJ!g9<>i2KzzY#)11NH|%@nYu`e2=^
z5}y+EL!|jCgc~kF)Oii$9v1?N#Iy?5;rPNNwn!xgv5qDPH~tF)4RsK6wSp?gAr=Z$
znF9J+>LLT)_KhHdPFDJQLH4?lO#{?H3dg64f5wJTI<`0jj=NidM8mW%ZV$P=`SgJw
zO#xBy+P!P`2VFOoqgfjCpi0n(pgyrZ65sO7TP<85F*pfZxx1Y%ScDphhx>kMtlB%T
z=f*jo6~HJ;xp?4<Bd5Mw_)68L`48jD3i`WRR%?t{MNHWbl0CzA3nkd-nUic19WVR4
zfP_PU3%}yIa%%3m-76od+Vsw}Gdn(9)meAE2LM8*fIL4A7SUF7xbytJ!itc$y_lBR
zqg5fMeX*#dn9g8zaDZ?m6a)p$r=4%-*+U;(tK3l^_IvcD)cOG{fWQa3ST#k|mVLG_
z+UMN?DuKAmiH*W5DKTkKAfTm$sc<oJcZY@@_cdKurY$(FAVE|cikJfm^`V@o22>Nu
zje@^-F5e(W2abUvgW`6w<8QY!^VsZ3r%PHNrPWq;w^Bn4_*`GrAKvs2UwA9(Iu*+;
zqre)VQ8Hg;7YgbsN>&g#R;R|XGM-jeDTHKTTz0KRQ*^aaQ=kzlYW93us(B67fr_L*
zV9Wu{<wyC@Fp=vgb}v>H*{Mdup!9TLvFucmPNdg^h8h4|Og);ekOOt<t97#hfg7mb
zbNQsN?fjAVv_r3=0Z5<=BnLt|9JD3<ejq^~HAQoE`4VafHaCodTL}o<K#`W}a%cCo
zvx@=iM9`rK#EcTfs(D@16yC<#r5zXk@NgsaqF^`xRep}*SC4M1!%KY?U?3EQR6K3W
z6yDB~%fD}~<>yU<gkb^XQc&&eQZGJ=Teu+ssX0785G=1LTV2M-b)wYa0~Ct$N~-u@
zVMi?F-$x<k*oBJ+i;Ik=7=A$D+vnyNc`-iM_M<75aZ_{)Qw%qt@lx-JNBWhs-+xrd
zO%dSN68yh_LOvZ(Byp+VPJqCn0>Tux6QGbsm}2PhADS<~&U=8j8~^|S07*qoM6N<$
Ef@x4__W%F@
new file mode 100644
index 0000000000000000000000000000000000000000..e0724fb6df5bbf0a601af72a82d60d942b99d939
GIT binary patch
literal 3287
zc$@*(3@G!7P)<h;3K|Lk000e1NJLTq001Ze001%w1^@s6F0+}C000c0Nkl<ZcwX(9
z3vgBSoyR}tb#HQS9wa0o1VF-5AcR+W8mqk2N>^oZwQJXQtfFYAzPjL!wWD<{R&*;4
zx^}A;ZL`%WENx0bTA&LEAR)xW1jv&lH{6@#zTdC&+L=3!D@2eibnDFScjnHyGiT=B
z&wPIKKfm9cpU9Uy{|^YT;r`i0dw;%aziFDa2i|+Q@=FKk568FH>}b92*Bib$PYv}n
zZdfz>%`X+8w?95Q7PIok+xz*KSC0}+sP}&V&M8$_3{X$C<Y<YH*7mmjb_7GrgH>au
zjVT;izI5q4@^Tcq93cig5kx^Wt{kAQbf(hw*HcNgfA6+uZf6LwDB_NaITZ{z-9*A+
z>~;&HDBS`axh%j`w0XUuM@s-AVI$w?Is<Vpf@E&3-uys0myoqf$`_|JX}rtfrlGMB
zQxFi~Ah6@I4vF7&Xk{Xnd?6AFZUI0~JgBD=gnTZF?Iwb0JbMWz_x5EsO+WD951+v8
zb>i#~Vi+cdW<JPg@{@<|TL0)bZng~xu;cKXk9b-S;OlR>dBD|L4s6kNZ9q3=;*kg=
zOYF1wg2a-k>iO4RFOQpC!1XtbVQNJQZf~jyI0dlrr_T@j#d8nzynnReh0~o5%a8yK
z-JBYY1sGm3mbwGKs;z$QsW&@Y>x%?Q!5>L8bLvEsFUaBrGnBEFt4VvEw70m)&zG1r
zBj;U!=YI0g;y_p(IMa1@Y-ygs{7L!Ap#jSFepAdQ>T@!!qN-@-f~tE<%O*?FSR4c^
zlEqffXA*Tcj`6i^e<R^-JDup+6Y8sbBRaM6E8;-spQ*1sh|?P(98EELOu>no+D&pK
zo;uw4!7j^`0-a?uMj0cAWu=D%C@OhRBiTu*8U<yunKElRnw}=Dn%Hvk*|U3BfKQSP
z_cqAZydImq;6CGQ&DEOcL>^kmo@Itm(hd?yaQi|;qw$x4KaINTtG^NDI8nb3w?B%e
zN27o-)Kk1mlI`1NYd)G9ClYj%N@<9K6^kX8XiR<NkMI6qn2`#&m7LO<7Hffkw~?OM
zFn0Rpv88P`8+PZh>8&~{rkAkd+L>|SaR4oyy45apGHX#j#W@~E6?xbGPdmwKK@_jo
z4P&pCHVyPNM#_U{pqujPRe}~d>q*C*#ey0~b?l-wm`!u;-yoIEWYqYHjGXgzI*K3S
z+1HzxQ(0_#V%=@CpL=K9=J46QqD7YQI$UI1qaonk%jqNsfEB4!?59aJK{%NtsU=Vi
zg|L<<d%EjLcWuY%>Od=7!Scz&nK42}mNfEnBqmHNCp7k6w%0VHCla-$DzDXi$1w~W
zU8i~w73-QS)r;4KU4At?n4my3Fv1RUhfkoTsS#E65;BJ~eq=G(A}ErGtO!V=fko6A
zRz8QeU_REuiL#!km#vCGPjeTENFWAmy;6YW<MHjT*~9LC|0BnK^LrA`4qWj(Tuvu8
z#g37TF%a?*NG8d)h$xDHB7;SNWXVECOkF~<Zy##fr0IitipI|T;br&YKfm+jnEqpL
zFKei&j^-AbrDJDTGHvN~hy^+5l1WxhDfOqr6lgxuzD{D{0BJRaqJS)dMG{EGA}qb_
zF04``k{+Y8DafqV>#1D+_)E8b|5v_6x7`2YU2E@{J7mDOUwh&1ISa-+>W?<;?d)l`
zmrR<^x>vSw_xGM;{PYRr=2{R;a3xCcwlpIJx`>5+Xle>kl96RO(|dDsZQMFHO!Djj
zKHTFacfuW1E_sM>uwLB!v+Bay0|)<cpzm~D_km|_zGT2$%ZRzxEv$S?k+PULEuZ@y
z`3FXnP9fP<L;a2yd8c{@s;`Y=OD}$Zihb=Vw5ShJG%-X0Q&-W`F#^5-3#Z8Bn8*3J
z)<<i5lCsh?!G=w=YS(Zw|55(+kd=lH8}a)cZ+{_R>z>zaN2;HC@70$!*Zu639m<dY
zxtdrwLg}c<xH}Hx7>FU3RB`pxs~K57ky4uzHPFQe?ICK8b&yiQd$x<7mXB#`K8e@S
z%8Hp0I_eJbyIn4H(j>f{wDjpLT(p!MW*1Vr-~n7d6L+t-_`Sz(>aBicS;YkbMUich
zp!d%1P7fbCRPyt(m{K`|$bf^eIFZTMJcvEl#{2~fIef&)n{OQ?5pi<5tCwK!8M<mV
zF(z_~W#v#+7UFAjt%#9B{O8_Y@~k;z%M!78l&qXATAgVU$rxGoTt<v3;dq^sqaU}9
zZfxzYzkhLwJP5FP=S!AkB6`EbiV9xc@?%ylo5hh+UV@=0;b@2v6Rx4ZWhbw1SkLyF
zT{!#wgvlqKNbucj3n@(XF>mGV%wPFEa+B@ME$N`D_yoQ6?T8T(DH-ADu~wQJ9pur&
z!P<QsI~_pp*-6apC*ld?^9Se~@G4e|vT_ihAd1TcL6l<QFzI-LA3eQ>`|tcZzutC&
z-~FM1?xtfj*VWPPh@p~&E0oF%0ITMVCJ_iRY~onTCru#L`UZ7<3NL<i9qWIo(tkEU
z@u*x5?r*`-7+~+dM#8}`X2UP&JG7DU;ls2xbkNn~L^lj976n<Bo*E1&2rqteMO9S-
z9xpfEu#h`$tfIpa<hzfpXUF@;sGPHiq+#J?YdbejEvDtPi*9d-DHUZz&g`elr=gYK
z%joG<D3xpYk2;aEQW?Ky;gAl$-S6O@bvtl&b}&;tL3=|Zz5QM+Sr$Z5#57H0Nt*l2
zZCB@f3V3SwD@7no<Gcj?0c>^)>+W00->;a%?++g5ot;N%>gwa~zA_4z%gu?FZj!o+
zRT6M?cM{J3DobYCnKHJ3vZ7M#BWI8ZCvn&;=s=$)GirDdd8r89Jsy&}iPfs`NiYG^
zG=*GS)|yWN1yOpQ!O7T6r&WT%Ah+E(o9!FF&6LskxIH1x^z>8v@fj8^oW*z6ehrs1
zz^Jm}IOEwg`5+uh5sIZ5nV-NhpyTe3QC3pG)2l0)S!B}h2_Q%kk|<(wZVb~PJ1gti
z&z5+N2^trSfX5p|ktBY(;clM1dkMQ50yw<}lgfwFxc?-FkF=0fgP2`g*?ZW>$L)SJ
z-*NQbTK;WEBUP1Sczk&|Ax|IfU>rq}I6vmOUvkgyBnqP75CjoXR6f^cBALSP^>gp)
z`E1?vEsDmCX5Gv0)9DCv?06?NJKKn!+)waN598eTPsBcWo|A13ZmJl^s;N2jy4<8R
z0Z9`1yhwmym^vU_sFPe35BZ7t2aqim5QOs}!36r;e)4S=UVid#S-oN&2V43uZH4^2
z`WWx+Zs%<C5ju|jfh;}Ewc|>WlObHb7=k1s3}!<V00ELZ0P;m!oo(3g%oOc&oI#Wn
zL{S=415pr&C)4=-VZM3GEH*xR3%-a(Q(uJlYdhKB<YU!>8O$!p!t3*(A|OcuCW9l(
zkk-H-6G-Wo(2GsOB(JCxMFG#5Hqwb0vTPk(asa^NjbgXLJ5R6V8_O!GoKVUu_gq7P
zki-*8AW9OzIdCQ*2_TE$jhMJXpc^0xmpClws*2T?LvFr}aG#5y+l3^{nLj&UgOIVQ
z5sjv~=eh~pzjzF!5(JZK#@hLC0$^1jshPC9H3p(4f|!9D+PGyH2Brx)g?6-f98Xsd
z>0}ZqV{<Sh0-S7fa;DEuTs4q|!R8bZBvIgOK%=EkBd%sFB3#ZyZRiGBHY?dykw||(
zLARTXP4QFtNU}sI6ek)@qUr|WNCH_F&UtKDWRbXPa@v)m*RLUFVBzvdelv6QK@hOz
zW}&CzczgR%H62-&05elc-#`d6V-tLlM8>LVf+PqivWO?Fa>|(?mNu}+!ezZ-?Y^*0
zlWbcSwk(P8fQOJjoUsSsb_cO!%z{6XK-UbiEfT5$t<D%70|_#)7gwTQ3Sha3`2=8G
z2og~wcbE-RRS66P=|AhwJj6v&L=Z&MszxxL#vM-5)Dt8a)3C}S!o|fM1)=a#OS};n
z4|HD8re>0Dw~&*kU}`E>Mb4BRflNu;odMdNApjIv_#$g}0E>a>P!35CFcH{vv634)
zl#~@PqjDVfY)j@)0T_UkF?vzBPM{FjdO2%|$ACFN08BnF>6AvcO<~dENn~ebAiwB`
zb>Ih|2#8*ZHN;0iA@CBI=I4Q`X#+tJGZT+t7+fUHKq;`{FR_ML2UGwaFgf=FrfFc9
z0K%vDK66_K9tLIr-oNCY<P=Z>R9|44W3XZRfUAJb|C_6@yMb$g#D8;{3=W%sGQj!Q
z*wq~Za)2$I7Xi9~DZpcY?Pa0?d<U2>2tph{5cv^M4zzulww=cTJ0Jkh{GZtu{}<^&
V0dzR3C*%MC002ovPDHLkV1n%yJ|zGE
--- a/browser/base/content/aboutHome.css
+++ b/browser/base/content/aboutHome.css
@@ -249,16 +249,36 @@ body[dir=rtl] #searchSubmit:active {
 }
 
 #snippets:hover:active {
   background-color: rgb(210,210,210);
   box-shadow: 0 2px 3px rgba(0,0,0,.3) inset,
               0 1px 0 rgba(255,255,255,.5);
 }
 
+#defaultSnippet1,
+#defaultSnippet2 {
+  display: table-row;
+  text-align: start;
+}
+
+#defaultSnippet1::before,
+#defaultSnippet2::before {
+  display: table-cell;
+  vertical-align: middle;
+  -moz-padding-end: 1em;
+}
+
+#defaultSnippet1::before {
+  content: url("chrome://browser/content/aboutHome-snippet1.png");
+}
+#defaultSnippet2::before {
+  content: url("chrome://browser/content/aboutHome-snippet2.png");
+}
+
 #sessionRestoreContainer {
   padding-top: 1.5%;
   text-align: center;
 }
 
 @media all and (max-height: 370px) {
   #sessionRestoreContainer {
     position: relative;
--- a/browser/base/content/aboutHome.js
+++ b/browser/base/content/aboutHome.js
@@ -136,18 +136,18 @@ const SEARCH_ENGINES = {
 };
 
 // The process of adding a new default snippet involves:
 //   * add a new entity to aboutHome.dtd
 //   * add a <span/> for it in aboutHome.xhtml
 //   * add an entry here in the proper ordering (based on spans)
 // The <a/> part of the snippet will be linked to the corresponding url.
 const DEFAULT_SNIPPETS_URLS = [
-  "http://www.mozilla.com/firefox/4.0/features"
-, "https://addons.mozilla.org/firefox/?src=snippet"
+  "http://www.mozilla.com/firefox/features/?WT.mc_ID=default1"
+, "https://addons.mozilla.org/firefox/?src=snippet&WT.mc_ID=default2"
 ];
 
 const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
 
 let gSearchEngine;
 
 function onLoad(event)
 {
--- a/browser/base/content/aboutHome.xhtml
+++ b/browser/base/content/aboutHome.xhtml
@@ -82,18 +82,18 @@
           <input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;" />
         </div>
       </form>
     </div>
 
     <div id="contentContainer">
       <div id="snippetContainer">
         <div id="defaultSnippets" hidden="true">
-          <span>&abouthome.defaultSnippet1.v1;</span>
-          <span>&abouthome.defaultSnippet2.v1;</span>
+          <span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
+          <span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
         </div>
         <div id="snippets"/>
       </div>
 
       <div id="sessionRestoreContainer">
         <button id="restorePreviousSession">&historyRestoreLastSession.label;</button>
       </div>
     </div>
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -381,16 +381,17 @@
                           label="&showAllHistoryCmd2.label;"
 #ifndef XP_MACOSX
                           key="showAllHistoryKb"
 #endif
                           command="Browser:ShowAllHistory"/>
                 <menuseparator id="showAllHistorySeparator"/>
 #ifdef MOZ_SERVICES_SYNC
                 <menuitem id="sync-tabs-menuitem"
+                          class="syncTabsMenuItem"
                           label="&syncTabsMenu.label;"
                           oncommand="BrowserOpenSyncTabs();"
                           disabled="true"/>
 #endif
                 <menuitem id="historyRestoreLastSession"
                           class="restoreLastSession"
                           label="&historyRestoreLastSession.label;"
                           oncommand="restoreLastSession();"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -654,18 +654,21 @@ HistoryMenu.prototype = {
     m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label"));
     m.setAttribute("oncommand",
       "for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
   },
 
   toggleTabsFromOtherComputers: function PHM_toggleTabsFromOtherComputers() {
     // This is a no-op if MOZ_SERVICES_SYNC isn't defined
 #ifdef MOZ_SERVICES_SYNC
-    // enable/disable the Tabs From Other Computers menu
-    let menuitem = document.getElementById("sync-tabs-menuitem");
+    // Enable/disable the Tabs From Other Computers menu. Some of the menus handled
+    // by HistoryMenu do not have this menuitem.
+    let menuitem = this._rootElt.getElementsByClassName("syncTabsMenuItem")[0];
+    if (!menuitem)
+      return;
 
     // If Sync isn't configured yet, then don't show the menuitem.
     if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
         Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
       menuitem.setAttribute("hidden", true);
       return;
     }
 
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -350,33 +350,31 @@ let TabView = {
         event.preventDefault();
 
         self._initFrame(function() {
           let groupItems = self._window.GroupItems;
           let tabItem = groupItems.getNextGroupItemTab(event.shiftKey);
           if (!tabItem)
             return;
 
-          // Switch to the new tab, and close the old group if it's now empty.
-          let oldGroupItem = groupItems.getActiveGroupItem();
+          // Switch to the new tab
           window.gBrowser.selectedTab = tabItem.tab;
-          oldGroupItem.closeIfEmpty();
         });
       }
     }, true);
   },
 
   // ----------
   // Prepares the tab view for undo close tab.
   prepareUndoCloseTab: function(blankTabToRemove) {
     if (this._window) {
       this._window.UI.restoredClosedTab = true;
 
-      if (blankTabToRemove)
-        blankTabToRemove._tabViewTabIsRemovedAfterRestore = true;
+      if (blankTabToRemove && blankTabToRemove._tabViewTabItem)
+        blankTabToRemove._tabViewTabItem.isRemovedAfterRestore = true;
     }
   },
 
   // ----------
   // Cleans up the tab view after undo close tab.
   afterUndoCloseTab: function () {
     if (this._window)
       this._window.UI.restoredClosedTab = false;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4361,20 +4361,16 @@ var XULBrowserWindow = {
           this.throbberElement.removeAttribute("busy");
 
         this.stopCommand.setAttribute("disabled", "true");
         CombinedStopReload.switchToReload(aRequest instanceof Ci.nsIRequest);
       }
     }
   },
 
-  onLocationChange2: function (aWebProgress, aRequest, aLocationURI, aFlags) {
-    onLocationChange(aWebProgress, aRequest, aLocationURI);
-  },
-
   onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
     var location = aLocationURI ? aLocationURI.spec : "";
     this._hostChanged = true;
 
     // Hide the form invalid popup.
     if (gFormSubmitObserver.panelIsOpen()) {
       gFormSubmitObserver.panel.hidePopup();
     }
@@ -5092,16 +5088,20 @@ var TabsInTitlebar = {
       if (!(condition in this._disallowed)) {
         this._disallowed[condition] = null;
         this._update();
       }
     }
 #endif
   },
 
+  get enabled() {
+    return document.documentElement.getAttribute("tabsintitlebar") == "true";
+  },
+
 #ifdef CAN_DRAW_IN_TITLEBAR
   observe: function (subject, topic, data) {
     if (topic == "nsPref:changed")
       this._readPref();
   },
 
   _initialized: false,
   _disallowed: {},
@@ -5117,18 +5117,17 @@ var TabsInTitlebar = {
       return;
 
     let allowed = true;
     for (let something in this._disallowed) {
       allowed = false;
       break;
     }
 
-    let docElement = document.documentElement;
-    if (allowed == (docElement.getAttribute("tabsintitlebar") == "true"))
+    if (allowed == this.enabled)
       return;
 
     function $(id) document.getElementById(id);
     let titlebar = $("titlebar");
 
     if (allowed) {
       function rect(ele)   ele.getBoundingClientRect();
 
@@ -5139,30 +5138,28 @@ var TabsInTitlebar = {
       this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
       this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
 
       let tabsToolbarRect = rect(tabsToolbar);
       let titlebarTop = rect($("titlebar-content")).top;
       titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop,
                                                tabsToolbarRect.height) + "px";
 
-      docElement.setAttribute("tabsintitlebar", "true");
+      document.documentElement.setAttribute("tabsintitlebar", "true");
 
       if (!this._draghandle) {
         let tmp = {};
         Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
         this._draghandle = new tmp.WindowDraggingElement(tabsToolbar, window);
         this._draghandle.mouseDownCheck = function () {
-          return !this._dragBindingAlive &&
-                 this.ownerDocument.documentElement
-                     .getAttribute("tabsintitlebar") == "true";
+          return !this._dragBindingAlive && TabsInTitlebar.enabled;
         };
       }
     } else {
-      docElement.removeAttribute("tabsintitlebar");
+      document.documentElement.removeAttribute("tabsintitlebar");
 
       titlebar.style.marginBottom = "";
     }
   },
 
   _sizePlaceholder: function (type, width) {
     Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
                   function (node) { node.width = width; });
@@ -5917,20 +5914,16 @@ var BrowserOffline = {
     }
 
     if (!ioService.offline && !this._canGoOffline()) {
       this._updateOfflineUI(false);
       return;
     }
 
     ioService.offline = !ioService.offline;
-
-    // Save the current state for later use as the initial state
-    // (if there is no netLinkService)
-    gPrefService.setBoolPref("browser.offline", ioService.offline);
   },
 
   /////////////////////////////////////////////////////////////////////////////
   // nsIObserver
   observe: function (aSubject, aTopic, aState)
   {
     if (aTopic != "network:offline-status-changed")
       return;
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -120,17 +120,17 @@ nsContextMenu.prototype = {
       let linkText = selection.toString().trim();
       let uri;
       if (/^(?:https?|ftp):/i.test(linkText)) {
         try {
           uri = makeURI(linkText);
         } catch (ex) {}
       }
       // Check if this could be a valid url, just missing the protocol.
-      else if (/^(?:\w+\.)+\D\S*$/.test(linkText)) {
+      else if (/^(?:[a-z\d-]+\.)+[a-z]+$/i.test(linkText)) {
         // Now let's see if this is an intentional link selection. Our guess is
         // based on whether the selection begins/ends with whitespace or is
         // preceded/followed by a non-word character.
 
         // selection.toString() trims trailing whitespace, so we look for
         // that explicitly in the first and last ranges.
         let beginRange = selection.getRangeAt(0);
         let delimitedAtStart = /^\s/.test(beginRange);
--- a/browser/base/content/syncQuota.js
+++ b/browser/base/content/syncQuota.js
@@ -88,17 +88,17 @@ let gSyncQuota = {
   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);
+      Weave.Utils.nextTick(function() { Service.sync(); });
     }
     return true;
   },
 
   convertKB: function convertKB(value) {
     return DownloadUtils.convertByteUnits(value * 1024);
   }
 
--- a/browser/base/content/syncSetup.js
+++ b/browser/base/content/syncSetup.js
@@ -67,16 +67,17 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 Cu.import("resource://gre/modules/PluralForm.jsm");
 
 var gSyncSetup = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
                                          Ci.nsIWebProgressListener,
                                          Ci.nsISupportsWeakReference]),
 
+  haveCaptcha: true,
   captchaBrowser: null,
   wizard: null,
   _disabledSites: [],
 
   status: {
     password: false,
     email: false,
     server: false
@@ -138,16 +139,17 @@ var gSyncSetup = {
                                            .getAttribute("accesskey");
   },
 
   startNewAccountSetup: function () {
     if (!Weave.Utils.ensureMPUnlocked())
       return false;
     this._settingUpNew = true;
     this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE;
+    this.loadCaptcha();
   },
 
   useExistingAccount: function () {
     if (!Weave.Utils.ensureMPUnlocked())
       return false;
     this._settingUpNew = false;
     this.wizard.pageIndex = EXISTING_ACCOUNT_CONNECT_PAGE;
   },
@@ -266,18 +268,19 @@ var gSyncSetup = {
         let hasUser = document.getElementById("existingAccountName").value != "";
         let hasPass = document.getElementById("existingPassword").value != "";
         let hasKey = document.getElementById("existingPassphrase").value != "";
 
         if (hasUser && hasPass && hasKey) {
           if (this._usingMainServers)
             return true;
 
-          if (this._validateServer(document.getElementById("existingServer"), false))
+          if (this._validateServer(document.getElementById("existingServer"))) {
             return true;
+          }
         }
         return false;
     }
     // Default, e.g. wizard's special page -1 etc.
     return true;
   },
 
   onEmailInput: function () {
@@ -360,16 +363,21 @@ var gSyncSetup = {
         break;
       case NEW_ACCOUNT_PP_PAGE:
         document.getElementById("saveSyncKeyButton").focus();
         let el = document.getElementById("weavePassphrase");
         if (!el.value)
           this.onPassphraseGenerate();
         this.checkFields();
         break;
+      case NEW_ACCOUNT_CAPTCHA_PAGE:
+        if (!this.haveCaptcha) {
+          gSyncSetup.wizard.advance();
+        }
+        break;
       case NEW_ACCOUNT_START_PAGE:
         this.wizard.getButton("extra1").hidden = false;
         this.wizard.getButton("next").hidden = false;
         this.wizard.getButton("back").hidden = false;
         this.onServerCommand();
         this.wizard.canRewind = true;
         this.checkFields();
         break;
@@ -473,22 +481,16 @@ var gSyncSetup = {
           this._handleNoScript(false);
           this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
           return false;
         }
 
         image.setAttribute("status", "error");
         label.value = Weave.Utils.getErrorString(error);
         return false;
-      case NEW_ACCOUNT_PP_PAGE:
-        // 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.account = Weave.Utils.normalizeAccount(
           document.getElementById("existingAccountName").value);
         Weave.Service.password = document.getElementById("existingPassword").value;
         let pp = document.getElementById("existingPassphrase").value;
         Weave.Service.passphrase = Weave.Utils.normalizePassphrase(pp);
         if (Weave.Service.login())
           this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
@@ -547,21 +549,17 @@ var gSyncSetup = {
 
       Weave.Service.persistLogin();
       Weave.Svc.Obs.notify("weave:service:setup-complete");
       if (this._settingUpNew)
         gSyncUtils.openFirstClientFirstrun();
       else
         gSyncUtils.openAddedClientFirstrun();
     }
-
-    if (!Weave.Service.isLoggedIn)
-      Weave.Service.login();
-
-    Weave.Service.syncOnIdle(1);
+    Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
   },
 
   onWizardCancel: function () {
     if (this._resettingSync)
       return;
 
     if (this.wizard.pageIndex == SETUP_SUCCESS_PAGE) {
       this.onWizardFinish();
@@ -710,16 +708,19 @@ var gSyncSetup = {
       control.value = "";
       control.inputField.focus();
       // checkServer() will call checkAccount() and checkFields().
       this.checkServer();
       return;
     }
     control.removeAttribute("editable");
     Weave.Svc.Prefs.reset("serverURL");
+    if (this._settingUpNew) {
+      this.loadCaptcha();
+    }
     this.checkAccount();
     this.status.server = true;
     document.getElementById("serverFeedbackRow").hidden = true;
     this.checkFields();
   },
 
   onServerInput: function () {
     // Check custom server validity when the user stops typing for 1 second.
@@ -732,61 +733,63 @@ var gSyncSetup = {
 
   checkServer: function () {
     delete this._checkServerTimer;
     let el = document.getElementById("server");
     let valid = false;
     let feedback = document.getElementById("serverFeedbackRow");
     let str = "";
     if (el.value) {
-      valid = this._validateServer(el, true);
+      valid = this._validateServer(el);
       let str = valid ? "" : "serverInvalid.label";
       this._setFeedbackMessage(feedback, valid, str);
     }
     else
       this._setFeedbackMessage(feedback, true);
 
     // Recheck account against the new server.
     if (valid)
       this.checkAccount();
 
     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) {
+  _validateServer: function (element) {
     let valid = false;
     let val = element.value;
     if (!val)
       return false;
 
     let uri = Weave.Utils.makeURI(val);
 
     if (!uri)
       uri = Weave.Utils.makeURI("https://" + val);
 
-    if (uri && checkRemote) {
+    if (uri && this._settingUpNew) {
       function isValid(uri) {
         Weave.Service.serverURL = uri.spec;
         let check = Weave.Service.checkAccount("a");
         return (check == "available" || check == "notAvailable");
       }
 
       if (uri.schemeIs("http")) {
         uri.scheme = "https";
         if (isValid(uri))
           valid = true;
         else
           // setting the scheme back to http
           uri.scheme = "http";
       }
       if (!valid)
         valid = isValid(uri);
+
+      if (valid) {
+        this.loadCaptcha();
+      }
     }
     else if (uri) {
       valid = true;
       Weave.Service.serverURL = uri.spec;
     }
 
     if (valid)
       element.value = Weave.Service.serverURL;
@@ -944,28 +947,44 @@ var gSyncSetup = {
       } catch(e) {}
 
       if (!str)
         str = Weave.Utils.getErrorString(string);
     }
     this._setFeedback(element, success, str);
   },
 
+  loadCaptcha: function loadCaptcha() {
+    // First check for NoScript and whitelist the right sites.
+    this._handleNoScript(true);
+    this.captchaBrowser.loadURI(Weave.Service.miscAPI + "captcha_html");
+  },
+
   onStateChange: function(webProgress, request, stateFlags, status) {
     // We're only looking for the end of the frame load
     if ((stateFlags & Ci.nsIWebProgressListener.STATE_STOP) == 0)
       return;
     if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) == 0)
       return;
     if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) == 0)
       return;
 
     // If we didn't find the captcha, assume it's not needed and move on
-    if (request.QueryInterface(Ci.nsIHttpChannel).responseStatus == 404)
-      this.onWizardAdvance();
+    if (request.QueryInterface(Ci.nsIHttpChannel).responseStatus == 404) {
+      this.haveCaptcha = false;
+      // Hide the browser just in case we end up displaying the captcha page
+      // due to a sign up error.
+      this.captchaBrowser.hidden = true;
+      if (this.wizard.pageIndex == NEW_ACCOUNT_CAPTCHA_PAGE) {
+        this.onWizardAdvance();
+      }
+    } else {
+      this.haveCaptcha = true;
+      this.captchaBrowser.hidden = false;
+    }
   },
   onProgressChange: function() {},
   onStatusChange: function() {},
   onSecurityChange: function() {},
   onLocationChange: function () {}
 }
 
 // onWizardAdvance() and onPageShow() are run before init(), so we'll set
--- a/browser/base/content/syncSetup.xul
+++ b/browser/base/content/syncSetup.xul
@@ -224,17 +224,18 @@
                 label="&button.syncKeyBackup.save.label;"
                 accesskey="&button.syncKeyBackup.save.accesskey;"
                 oncommand="gSyncUtils.passphraseSave('weavePassphrase');"/>
       </hbox>
     </groupbox>
   </wizardpage>
 
   <wizardpage label="&setup.captchaPage2.title.label;"
-              onextra1="gSyncSetup.onSyncOptions()">
+              onextra1="gSyncSetup.onSyncOptions()"
+              onpageshow="gSyncSetup.onPageShow();">
     <vbox flex="1" align="center">
       <browser height="150"
                width="450"
                id="captcha"
                type="content"
                disablehistory="true"/>
       <spacer flex="1"/>
       <hbox id="captchaFeedback" hidden="true">
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1677,16 +1677,20 @@
             // steps.
             var panel = browser.parentNode.parentNode;
 
             // This will unload the document. An unload handler could remove
             // dependant tabs, so it's important that the tabbrowser is now in
             // a consistent state (tab removed, tab positions updated, etc.).
             panel.removeChild(browser.parentNode);
 
+            // Release the browser in case something is erroneously holding a
+            // reference to the tab after its removal.
+            aTab.linkedBrowser = null;
+
             // As the browser is removed, the removal of a dependent document can
             // cause the whole window to close. So at this point, it's possible
             // that the binding is destructed.
             if (this.mTabBox) {
               let selectedPanel = this.mTabBox.selectedPanel;
 
               this.mPanelContainer.removeChild(panel);
 
@@ -3198,29 +3202,34 @@
 
         if (tab.getAttribute("fadein") == "true")
           this._handleNewTab(tab);
         else if (tab.closing)
           this.tabbrowser._endRemoveTab(tab);
       ]]></handler>
 
       <handler event="dblclick"><![CDATA[
-#ifdef MOZ_WIDGET_GTK2
-        // Disable this on GTK2 when the menubar is draggable, since (a)
-        // the menubar and tabbbar have unified appearance and should
-        // thus not have different behavior (though this condition alone
-        // applies to more cases) and (b) it interacts badly with the
-        // drag handling that we use for dragging either one.
-        if (this.parentNode._dragBindingAlive)
+#ifndef XP_MACOSX
+        // When the tabbar has an unified appearance with the titlebar
+        // and menubar, a double-click in it should have the same behavior
+        // as double-clicking the titlebar
+        if (TabsInTitlebar.enabled ||
+            (TabsOnTop.enabled && this.parentNode._dragBindingAlive))
           return;
 #endif
+
+        if (event.button != 0 ||
+            event.originalTarget.localName != "box")
+          return;
+
         // See hack note in the tabbrowser-close-tab-button binding
-        if (!this._blockDblClick && event.button == 0 &&
-            event.originalTarget.localName == "box")
+        if (!this._blockDblClick)
           BrowserOpenTab();
+
+        event.preventDefault();
       ]]></handler>
 
       <handler event="click"><![CDATA[
         if (event.button != 1)
           return;
 
         if (event.target.localName == "tab") {
           if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
--- a/browser/base/content/tabview/drag.js
+++ b/browser/base/content/tabview/drag.js
@@ -277,21 +277,16 @@ Drag.prototype = {
   // Called in response to an <Item> draggable "stop" event.
   //
   // Parameters:
   //  immediately - bool for doing the pushAway immediately, without animation
   stop: function Drag_stop(immediately) {
     Trenches.hideGuides();
     this.item.isDragging = false;
 
-    if (this.parent && this.parent != this.item.parent &&
-       this.parent.isEmpty()) {
-      this.parent.close();
-    }
-
     if (this.parent && this.parent.expanded)
       this.parent.arrange();
 
     if (this.item.parent)
       this.item.parent.arrange();
 
     if (!this.item.parent) {
       this.item.setZ(drag.zIndex);
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -59,16 +59,17 @@
 //     to <add> along with the elements provided.
 //
 // Possible options:
 //   id - specifies the groupItem's id; otherwise automatically generated
 //   userSize - see <Item.userSize>; default is null
 //   bounds - a <Rect>; otherwise based on the locations of the provided elements
 //   container - a DOM element to use as the container for this groupItem; otherwise will create
 //   title - the title for the groupItem; otherwise blank
+//   focusTitle - focus the title's input field after creation
 //   dontPush - true if this groupItem shouldn't push away or snap on creation; default is false
 //   immediately - true if we want all placement immediately, not with animation
 function GroupItem(listOfEls, options) {
   if (!options)
     options = {};
 
   this._inited = false;
   this._uninited = false;
@@ -80,20 +81,16 @@ function GroupItem(listOfEls, options) {
   this.expanded = null;
   this.hidden = false;
   this.fadeAwayUndoButtonDelay = 15000;
   this.fadeAwayUndoButtonDuration = 300;
 
   this.keepProportional = false;
   this._frozenItemSizeData = {};
 
-  // Double click tracker
-  this._lastClick = 0;
-  this._lastClickPositions = null;
-
   // Variable: _activeTab
   // The <TabItem> for the groupItem's active tab.
   this._activeTab = null;
 
   if (Utils.isPoint(options.userSize))
     this.userSize = new Point(options.userSize);
 
   var self = this;
@@ -213,22 +210,23 @@ function GroupItem(listOfEls, options) {
       self.lastMouseDownTarget = (Utils.isLeftClick(e) ? e.target : null);
     })
     .mouseup(function(e) {
       var same = (e.target == self.lastMouseDownTarget);
       self.lastMouseDownTarget = null;
       if (!same)
         return;
 
-      if (!self.isDragging) {
-        self.$titleShield.hide();
-        (self.$title)[0].focus();
-      }
+      if (!self.isDragging)
+        self.focusTitle();
     });
 
+  if (options.focusTitle)
+    this.focusTitle();
+
   // ___ Stack Expander
   this.$expander = iQ("<div/>")
     .addClass("stackExpander")
     .appendTo($container)
     .hide();
 
   // ___ app tabs: create app tab tray and populate it
   let appTabTrayContainer = iQ("<div/>")
@@ -297,17 +295,19 @@ GroupItem.prototype = Utils.extend(new I
   // Function: setActiveTab
   // Sets the active <TabItem> for this groupItem; can be null, but only
   // if there are no children.
   setActiveTab: function GroupItem_setActiveTab(tab) {
     Utils.assertThrow((!tab && this._children.length == 0) || tab.isATabItem,
         "tab must be null (if no children) or a TabItem");
 
     this._activeTab = tab;
-    this.arrange({immediately: true});
+
+    if (this.isStacked())
+      this.arrange({immediately: true});
   },
 
   // -----------
   // Function: getActiveTab
   // Gets the active <TabItem> for this groupItem; can be null, but only
   // if there are no children.
   getActiveTab: function GroupItem_getActiveTab() {
     return this._activeTab;
@@ -400,16 +400,24 @@ GroupItem.prototype = Utils.extend(new I
     // The * 6 multiplier calculation is assuming that characters in the title
     // are approximately 6 pixels wide. Bug 586545
     var css = {width: w};
     this.$title.css(css);
     this.$titleShield.css(css);
   },
 
   // ----------
+  // Function: focusTitle
+  // Hide the title's shield and focus the underlying input field.
+  focusTitle: function GroupItem_focusTitle() {
+    this.$titleShield.hide();
+    this.$title[0].focus();
+  },
+
+  // ----------
   // Function: adjustAppTabTray
   // Used to adjust the appTabTray size, to split the appTabIcons across
   // multiple columns when needed - if the groupItem size is too small.
   //
   // Parameters:
   //   arrangeGroup - rearrange the groupItem if the number of appTab columns
   //   changes. If true, then this.arrange() is called, otherwise not.
   adjustAppTabTray: function GroupItem_adjustAppTabTray(arrangeGroup) {
@@ -632,17 +640,17 @@ GroupItem.prototype = Utils.extend(new I
   // Closes the groupItem, removing (but not closing) all of its children.
   //
   // Parameters:
   //   options - An object with optional settings for this call.
   //
   // Options:
   //   immediately - (bool) if true, no animation will be used
   close: function GroupItem_close(options) {
-    this.removeAll({dontClose: true});
+    this.removeAll();
     GroupItems.unregister(this);
 
     // remove unfreeze event handlers, if item size is frozen
     this._unfreezeItemSize({dontArrange: true});
 
     let self = this;
     let destroyGroup = function () {
       iQ(self.container).remove();
@@ -707,31 +715,16 @@ GroupItem.prototype = Utils.extend(new I
   _makeClosestTabActive: function GroupItem__makeClosestTabActive() {
     let closeCenter = this.getBounds().center();
     // Find closest tab to make active
     let closestTabItem = UI.getClosestTab(closeCenter);
     UI.setActive(closestTabItem);
   },
 
   // ----------
-  // Function: closeIfEmpty
-  // Closes the group if it's empty, has no title, is closable, and
-  // autoclose is enabled (see pauseAutoclose()). Returns true if the close
-  // occurred and false otherwise.
-  closeIfEmpty: function() {
-    if (!this._children.length && !this.getTitle() &&
-        !GroupItems.getUnclosableGroupItemId() &&
-        !GroupItems._autoclosePaused) {
-      this.close();
-      return true;
-    }
-    return false;
-  },
-
-  // ----------
   // Function: _unhide
   // Shows the hidden group.
   _unhide: function GroupItem__unhide() {
     let self = this;
 
     this._cancelFadeAwayUndoButtonTimer();
     this.hidden = false;
     this.$undoContainer.remove();
@@ -771,17 +764,17 @@ GroupItem.prototype = Utils.extend(new I
       return (groupItem != self && groupItem.getChildren().length);
     });
     if (!gBrowser._numPinnedTabs && !GroupItems.getOrphanedTabs().length &&
         !remainingGroups.length) {
       let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
         return (groupItem != self && !groupItem.getChildren().length);
       });
       let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
-      group.newTab();
+      group.newTab(null, { closedLastTab: true });
     }
 
     this.destroy();
   },
 
   // ----------
   // Function: destroy
   // Close all tabs linked to children (tabItems), removes all children and 
@@ -994,18 +987,17 @@ GroupItem.prototype = Utils.extend(new I
 
       if (!wasAlreadyInThisGroupItem) {
         item.droppable(false);
         item.groupItemData = {};
 
         item.addSubscriber(this, "close", function() {
           let count = self._children.length;
           let dontArrange = self.expanded || !self.shouldStack(count);
-          let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
-          self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
+          self.remove(item, {dontArrange: dontArrange});
 
           if (dontArrange)
             self._freezeItemSize(count);
 
           if (self._children.length > 0 && self._activeTab)
             UI.setActive(self);
         });
 
@@ -1042,17 +1034,16 @@ GroupItem.prototype = Utils.extend(new I
   // Parameters:
   //
   //   a - The item to remove. Can be an <Item>, a DOM element or an iQ object.
   //       The latter two must refer to the container of an <Item>.
   //   options - An optional object with settings for this call. See below.
   //
   // Possible options: 
   //   dontArrange - don't rearrange the remaining items
-  //   dontClose - don't close the group even if it normally would
   //   immediately - don't animate
   remove: function GroupItem_remove(a, options) {
     try {
       var $el;
       var item;
 
       if (a.isAnItem) {
         item = a;
@@ -1091,25 +1082,17 @@ GroupItem.prototype = Utils.extend(new I
         item.setBounds(item.getBounds(), true, {force: true});
 
       item.droppable(true);
       item.removeSubscriber(this, "close");
 
       if (typeof item.setResizable == 'function')
         item.setResizable(true, options.immediately);
 
-      // if a blank tab is selected while restoring a tab the blank tab gets
-      // removed. we need to keep the group alive for the restored tab.
-      if (item.tab._tabViewTabIsRemovedAfterRestore)
-        options.dontClose = true;
-
-      let closed = options.dontClose ? false : this.closeIfEmpty();
-      if (closed)
-        this._makeClosestTabActive();
-      else if (!options.dontArrange) {
+      if (!options.dontArrange) {
         this.arrange({animate: !options.immediately});
         this._unfreezeItemSize({dontArrange: true});
       }
 
       this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
     } catch(e) {
       Utils.log(e);
     }
@@ -1190,17 +1173,17 @@ GroupItem.prototype = Utils.extend(new I
 
     elements.each(function(icon) {
       let $icon = iQ(icon);
       if ($icon.data("xulTab") != xulTab)
         return true;
 
       let targetIndex = xulTab._tPos;
 
-      $icon.remove();
+      $icon.remove({ preserveEventHandlers: true });
       if (targetIndex < (length - 1))
         self.$appTabTray[0].insertBefore(
           icon,
           iQ(".appTabIcon:nth-child(" + (targetIndex + 1) + ")", self.$appTabTray)[0]);
       else
         $icon.appendTo(self.$appTabTray);
       return false;
     });
@@ -1263,26 +1246,25 @@ GroupItem.prototype = Utils.extend(new I
       data.lastItemCount = itemCount;
 
       // unfreeze item size when tabview is hidden
       data.onTabViewHidden = function () self._unfreezeItemSize();
       window.addEventListener('tabviewhidden', data.onTabViewHidden, false);
 
       // we don't need to observe mouse movement when expanded because the
       // tray is closed when we leave it and collapse causes unfreezing
-      if (self.expanded)
-        return;
-
-      // unfreeze item size when cursor is moved out of group bounds
-      data.onMouseMove = function (e) {
-        let cursor = new Point(e.pageX, e.pageY);
-        if (!self.bounds.contains(cursor))
-          self._unfreezeItemSize();
+      if (!self.expanded) {
+        // unfreeze item size when cursor is moved out of group bounds
+        data.onMouseMove = function (e) {
+          let cursor = new Point(e.pageX, e.pageY);
+          if (!self.bounds.contains(cursor))
+            self._unfreezeItemSize();
+        }
+        iQ(window).mousemove(data.onMouseMove);
       }
-      iQ(window).mousemove(data.onMouseMove);
     }
 
     this.arrange({animate: true, count: data.lastItemCount});
   },
 
   // ----------
   // Function: _unfreezeItemSize
   // Unfreezes and updates item size.
@@ -1636,38 +1618,16 @@ GroupItem.prototype = Utils.extend(new I
   },
 
   // ----------
   // Function: _addHandlers
   // Helper routine for the constructor; adds various event handlers to the container.
   _addHandlers: function GroupItem__addHandlers(container) {
     let self = this;
 
-    // Create new tab and zoom in on it after a double click
-    container.mousedown(function(e) {
-      if (!Utils.isLeftClick(e) || self.$titlebar[0] == e.target || 
-          self.$titlebar.contains(e.target)) {
-        self._lastClick = 0;
-        self._lastClickPositions = null;
-        return;
-      }
-      if (Date.now() - self._lastClick <= UI.DBLCLICK_INTERVAL &&
-          (self._lastClickPositions.x - UI.DBLCLICK_OFFSET) <= e.clientX &&
-          (self._lastClickPositions.x + UI.DBLCLICK_OFFSET) >= e.clientX &&
-          (self._lastClickPositions.y - UI.DBLCLICK_OFFSET) <= e.clientY &&
-          (self._lastClickPositions.y + UI.DBLCLICK_OFFSET) >= e.clientY) {
-        self.newTab();
-        self._lastClick = 0;
-        self._lastClickPositions = null;
-      } else {
-        self._lastClick = Date.now();
-        self._lastClickPositions = new Point(e.clientX, e.clientY);
-      }
-    });
-
     var dropIndex = false;
     var dropSpaceTimer = null;
 
     // When the _dropSpaceActive flag is turned on on a group, and a tab is
     // dragged on top, a space will open up.
     this._dropSpaceActive = false;
 
     this.dropOptions.over = function GroupItem_dropOptions_over(event) {
@@ -1737,17 +1697,17 @@ GroupItem.prototype = Utils.extend(new I
 
       if (dropSpaceTimer) {
         clearTimeout(dropSpaceTimer);
         dropSpaceTimer = null;
       }
       self.arrange();
       var groupItem = drag.info.item.parent;
       if (groupItem)
-        groupItem.remove(drag.info.$el, {dontClose: true});
+        groupItem.remove(drag.info.$el);
       iQ(this.container).removeClass("acceptsDrop");
     }
 
     this.draggable();
     this.droppable(true);
 
     this.$expander.click(function() {
       self.expand();
@@ -1776,24 +1736,26 @@ GroupItem.prototype = Utils.extend(new I
       immediately ? this.$resizer.hide() : this.$resizer.fadeOut();
       this.resizable(false);
     }
   },
 
   // ----------
   // Function: newTab
   // Creates a new tab within this groupItem.
-  newTab: function GroupItem_newTab(url) {
-    UI.setActive(this, { dontSetActiveTabInGroup: true });
-    let newTab = gBrowser.loadOneTab(url || "about:blank", {inBackground: true});
+  // Parameters:
+  //  url - the new tab should open this url as well
+  //  options - the options object
+  //    closedLastTab - boolean indicates the last tab has just been closed
+  newTab: function GroupItem_newTab(url, options) {
+    if (options && options.closedLastTab)
+      UI.closedLastTabInTabView = true;
 
-    // TabItems will have handled the new tab and added the tabItem property.
-    // We don't have to check if it's an app tab (and therefore wouldn't have a
-    // TabItem), since we've just created it.
-    newTab._tabViewTabItem.zoomIn(!url);
+    UI.setActive(this, { dontSetActiveTabInGroup: true });
+    gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
   },
 
   // ----------
   // Function: reorderTabItemsBasedOnTabOrder
   // Reorders the tabs in a groupItem based on the arrangment of the tabs
   // shown in the tab bar. It does it by sorting the children
   // of the groupItem by the positions of their respective tabs in the
   // tab bar.
@@ -1869,17 +1831,16 @@ let GroupItems = {
   _inited: false,
   _activeGroupItem: null,
   _activeOrphanTab: null,
   _cleanupFunctions: [],
   _arrangePaused: false,
   _arrangesPending: [],
   _removingHiddenGroups: false,
   _delayedModUpdates: [],
-  _autoclosePaused: false,
   minGroupHeight: 110,
   minGroupWidth: 125,
 
   // ----------
   // Function: toString
   // Prints [GroupItems] for debug use
   toString: function GroupItems_toString() {
     return "[GroupItems count=" + this.groupItems.length + "]";
@@ -2641,26 +2602,10 @@ let GroupItems = {
   // Basic measure rules. Assures that item is a minimum size.
   calcValidSize: function GroupItems_calcValidSize(size, options) {
     Utils.assert(Utils.isPoint(size), 'input is a Point');
     Utils.assert((size.x>0 || size.y>0) && (size.x!=0 && size.y!=0), 
       "dimensions are valid:"+size.x+","+size.y);
     return new Point(
       Math.max(size.x, GroupItems.minGroupWidth),
       Math.max(size.y, GroupItems.minGroupHeight));
-  },
-
-  // ----------
-  // Function: pauseAutoclose()
-  // Temporarily disable the behavior that closes groups when they become
-  // empty. This is used when entering private browsing, to avoid trashing the
-  // user's groups while private browsing is shuffling things around.
-  pauseAutoclose: function GroupItems_pauseAutoclose() {
-    this._autoclosePaused = true;
-  },
-
-  // ----------
-  // Function: unpauseAutoclose()
-  // Re-enables the auto-close behavior.
-  resumeAutoclose: function GroupItems_resumeAutoclose() {
-    this._autoclosePaused = false;
   }
 };
--- a/browser/base/content/tabview/iq.js
+++ b/browser/base/content/tabview/iq.js
@@ -331,33 +331,36 @@ iQClass.prototype = {
     } while (elem && this[0] != elem);
 
     return this[0] == elem;
   },
 
   // ----------
   // Function: remove
   // Removes the receiver from the DOM.
-  remove: function iQClass_remove() {
+  remove: function iQClass_remove(options) {
+    if (!options || !options.preserveEventHandlers)
+      this.unbindAll();
     for (let i = 0; this[i] != null; i++) {
       let elem = this[i];
       if (elem.parentNode) {
         elem.parentNode.removeChild(elem);
       }
     }
     return this;
   },
 
   // ----------
   // Function: empty
   // Removes all of the reciever's children and HTML content from the DOM.
   empty: function iQClass_empty() {
     for (let i = 0; this[i] != null; i++) {
       let elem = this[i];
       while (elem.firstChild) {
+        iQ(elem.firstChild).unbindAll();
         elem.removeChild(elem.firstChild);
       }
     }
     return this;
   },
 
   // ----------
   // Function: width
@@ -742,16 +745,38 @@ iQClass.prototype = {
           }
         }
       }
 
       elem.removeEventListener(type, handler, false);
     }
 
     return this;
+  },
+
+  // ----------
+  // Function: unbindAll
+  // Unbinds all event handlers.
+  unbindAll: function iQClass_unbindAll() {
+    for (let i = 0; this[i] != null; i++) {
+      let elem = this[i];
+
+      for (let j = 0; j < elem.childElementCount; j++)
+        iQ(elem.children[j]).unbindAll();
+
+      if (!elem.iQEventData)
+        continue;
+
+      for (let type in elem.iQEventData) {
+        while (elem.iQEventData[type].length)
+          this.unbind(type, elem.iQEventData[type][0].original);
+      }
+    }
+
+    return this;
   }
 };
 
 // ----------
 // Create various event aliases
 let events = [
   'keyup',
   'keydown',
--- a/browser/base/content/tabview/items.js
+++ b/browser/base/content/tabview/items.js
@@ -174,17 +174,17 @@ Item.prototype = {
     };
 
     // ___ drop
     this.dropOptions = {
       over: function() {},
       out: function() {
         let groupItem = drag.info.item.parent;
         if (groupItem)
-          groupItem.remove(drag.info.$el, {dontClose: true});
+          groupItem.remove(drag.info.$el);
         iQ(this.container).removeClass("acceptsDrop");
       },
       drop: function(event) {
         iQ(this.container).removeClass("acceptsDrop");
       },
       // Function: dropAcceptFunction
       // Given a DOM element, returns true if it should accept tabs being dropped on it.
       // Private to this file.
--- a/browser/base/content/tabview/modules/AllTabs.jsm
+++ b/browser/base/content/tabview/modules/AllTabs.jsm
@@ -69,36 +69,36 @@ let AllTabs = {
    *        "close", "move", "open", "select", "pinned", "unpinned".
    * @param callback
    *        Callback that gets called with the tab as the first argument and
    *        the event as the second argument.
    * @usage AllTabs.register("change", function handleChange(tab, event) {});
    */
   register: function register(eventName, callback) {
     // Either add additional callbacks or create the first entry
-    let listeners = eventListeners[eventName];
+    let listeners = eventListeners[events[eventName]];
     if (listeners)
       listeners.push(callback);
     else
-      eventListeners[eventName] = [callback];
+      eventListeners[events[eventName]] = [callback];
   },
 
   /**
    * Remove a callback for a given tab event.
    *
    * @param eventName
    *        Name of the corresponding Tab* Event; one of "attrModified",
    *        "close", "move", "open", "select", "pinned", "unpinned".
    * @param callback
    *        The callback given for the original AllTabs.register call.
    * @usage AllTabs.unregister("close", handleClose);
    */
   unregister: function unregister(eventName, callback) {
     // Nothing to remove for this event
-    let listeners = eventListeners[eventName];
+    let listeners = eventListeners[events[eventName]];
     if (!listeners)
       return;
 
     // Can only remove a callback if we have it
     let index = listeners.indexOf(callback);
     if (index == -1)
       return;
 
@@ -109,41 +109,60 @@ let AllTabs = {
 __defineGetter__("browserWindows", function browserWindows() {
   let browserWindows = [];
   let windows = Services.wm.getEnumerator("navigator:browser");
   while (windows.hasMoreElements())
     browserWindows.push(windows.getNext());
   return browserWindows;
 });
 
-let events = ["attrModified", "close", "move", "open", "select", "pinned", "unpinned"];
+let events = {
+  attrModified: "TabAttrModified",
+  close:        "TabClose",
+  move:         "TabMove",
+  open:         "TabOpen",
+  select:       "TabSelect",
+  pinned:       "TabPinned",
+  unpinned:     "TabUnpinned"
+};
 let eventListeners = {};
 
 function registerBrowserWindow(browserWindow) {
-  events.forEach(function(eventName) {
-    let tabEvent = "Tab" + eventName[0].toUpperCase() + eventName.slice(1);
-    browserWindow.addEventListener(tabEvent, function(event) {
-      // Make sure we've gotten listeners before trying to call
-      let listeners = eventListeners[eventName];
-      if (!listeners)
-        return;
+  for each (let event in events)
+    browserWindow.addEventListener(event, tabEventListener, true);
+
+  browserWindow.addEventListener("unload", unregisterBrowserWindow, false);
+}
 
-      let tab = event.target;
+function unregisterBrowserWindow(unloadEvent) {
+  let browserWindow = unloadEvent.currentTarget;
+
+  for each (let event in events)
+    browserWindow.removeEventListener(event, tabEventListener, true);
+
+  browserWindow.removeEventListener("unload", unregisterBrowserWindow, false);
+}
 
-      // Make a copy of the listeners, so it can't change as we call back
-      listeners.slice().forEach(function(callback) {
-        try {
-          callback(tab, event);
-        }
-        // Don't let failing callbacks stop us but report the failure
-        catch(ex) {
-          Cu.reportError(ex);
-        }
-      });
-    }, true);
+function tabEventListener(event) {
+  // Make sure we've gotten listeners before trying to call
+  let listeners = eventListeners[event.type];
+  if (!listeners)
+    return;
+
+  let tab = event.target;
+
+  // Make a copy of the listeners, so it can't change as we call back
+  listeners.slice().forEach(function (callback) {
+    try {
+      callback(tab, event);
+    }
+    // Don't let failing callbacks stop us but report the failure
+    catch (ex) {
+      Cu.reportError(ex);
+    }
   });
 }
 
 function observer(subject, topic, data) {
   switch (topic) {
     case "domwindowopened":
       subject.addEventListener("load", function() {
         subject.removeEventListener("load", arguments.callee, false);
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -119,17 +119,18 @@ function TabItem(tab, options) {
 
     var phantom = $target.data("phantomGroupItem");
 
     var groupItem = drag.info.item.parent;
     if (groupItem) {
       groupItem.add(drag.info.$el);
     } else {
       phantom.removeClass("phantom acceptsDrop");
-      new GroupItem([$target, drag.info.$el], {container:phantom, bounds:phantom.bounds()});
+      let opts = {container:phantom, bounds:phantom.bounds(), focusTitle: true};
+      new GroupItem([$target, drag.info.$el], opts);
     }
   };
 
   this.dropOptions.over = function(e) {
     var $target = this.$container;
     this.isDropTarget = true;
 
     $target.removeClass("acceptsDrop");
@@ -374,17 +375,17 @@ TabItem.prototype = Utils.extend(new Ite
         //   Bug 645653 - Middle-click on reload button to duplicate orphan tabs does not create a group
         //   Bug 643119 - Ctrl+Drag to duplicate does not work for orphaned tabs
         //   ... (and any other way of duplicating a non-blank orphaned tab).
         if (GroupItems.getActiveGroupItem() == null)
           GroupItems.newTab(self, {immediately: true});
       }
     } else {
       // create tab by double click is handled in UI_init().
-      if (!TabItems.creatingNewOrphanTab)
+      if (!UI.creatingNewOrphanTab)
         GroupItems.newTab(self, {immediately: true});
     }
 
     self._reconnected = true;
     self.save();
     self._sendToSubscribers("reconnected");
   },
   
@@ -558,17 +559,17 @@ TabItem.prototype = Utils.extend(new Ite
       if (this.tab._tabViewTabItem.parent) {
         group = this.tab._tabViewTabItem.parent;
       } else {
         let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
           return (!groupItem.getChildren().length);
         });
         group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
       }
-      group.newTab();
+      group.newTab(null, { closedLastTab: true });
     }
     // when "TabClose" event is fired, the browser tab is about to close and our 
     // item "close" is fired before the browser tab actually get closed. 
     // Therefore, we need "tabRemoved" event below.
     gBrowser.removeTab(this.tab);
     let tabNotClosed = 
       Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
     if (!tabNotClosed)
@@ -660,16 +661,18 @@ TabItem.prototype = Utils.extend(new Ite
       if (tab != gBrowser.selectedTab) {
         UI.onTabSelect(gBrowser.selectedTab);
       } else { 
         if (isNewBlankTab)
           gWindow.gURLBar.focus();
       }
       if (self.parent && self.parent.expanded)
         self.parent.collapse();
+
+      self._sendToSubscribers("zoomedIn");
     }
 
     let animateZoom = gPrefBranch.getBoolPref("animate_zoom");
     if (animateZoom) {
       let transform = this.getZoomTransform();
       TabItems.pausePainting();
 
       if (this.parent && this.parent.expanded)
@@ -798,17 +801,16 @@ let TabItems = {
   paintingPaused: 0,
   _tabsWaitingForUpdate: null,
   _heartbeat: null, // see explanation at startHeartbeat() below
   _heartbeatTiming: 200, // milliseconds between calls
   _maxTimeForUpdating: 200, // milliseconds that consecutive updates can take
   _lastUpdateTime: Date.now(),
   _eventListeners: [],
   _pauseUpdateForTest: false,
-  creatingNewOrphanTab: false,
   tempCanvas: null,
   _reconnectingPaused: false,
   tabItemPadding: {},
 
   // ----------
   // Function: toString
   // Prints [TabItems count=count] for debug use
   toString: function TabItems_toString() {
@@ -1075,16 +1077,19 @@ let TabItems = {
         UI.setActive(null, { onlyRemoveActiveTab: true });
 
       this.unregister(tab._tabViewTabItem);
       tab._tabViewTabItem._sendToSubscribers("close");
       tab._tabViewTabItem.$container.remove();
       tab._tabViewTabItem.removeTrenches();
       Items.unsquish(null, tab._tabViewTabItem);
 
+      tab._tabViewTabItem.tab = null;
+      tab._tabViewTabItem.tabCanvas.tab = null;
+      tab._tabViewTabItem.tabCanvas = null;
       tab._tabViewTabItem = null;
       Storage.saveTab(tab, null);
 
       this._tabsWaitingForUpdate.remove(tab);
     } catch(e) {
       Utils.log(e);
     }
   },
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -134,16 +134,24 @@ let UI = {
   // Variable: _browserKeys
   // Used to keep track of allowed browser keys.
   _browserKeys: null,
 
   // Variable: ignoreKeypressForSearch
   // Used to prevent keypress being handled after quitting search mode.
   ignoreKeypressForSearch: false,
 
+  // Variable: creatingNewOrphanTab
+  // Used to keep track of whether we are creating a new oprhan tab or not.
+  creatingNewOrphanTab: false,
+
+  // Variable: _lastOpenedTab
+  // Used to keep track of the last opened tab.
+  _lastOpenedTab: null,
+
   // ----------
   // Function: toString
   // Prints [UI] for debug use
   toString: function UI_toString() {
     return "[UI]";
   },
 
   // ----------
@@ -191,30 +199,31 @@ let UI = {
           } else {
             // Create an orphan tab on double click
             if (Date.now() - self._lastClick <= self.DBLCLICK_INTERVAL && 
                 (self._lastClickPositions.x - self.DBLCLICK_OFFSET) <= e.clientX &&
                 (self._lastClickPositions.x + self.DBLCLICK_OFFSET) >= e.clientX &&
                 (self._lastClickPositions.y - self.DBLCLICK_OFFSET) <= e.clientY &&
                 (self._lastClickPositions.y + self.DBLCLICK_OFFSET) >= e.clientY) {
               self.setActive(null);
-              TabItems.creatingNewOrphanTab = true;
-
-              let newTab =
-                gBrowser.loadOneTab("about:blank", { inBackground: true });
+              self.creatingNewOrphanTab = true;
 
               let box =
                 new Rect(e.clientX - Math.floor(TabItems.tabWidth/2),
                          e.clientY - Math.floor(TabItems.tabHeight/2),
                          TabItems.tabWidth, TabItems.tabHeight);
+              let newTab =
+                gBrowser.loadOneTab("about:blank", { inBackground: false });
+
               newTab._tabViewTabItem.setBounds(box, true);
               newTab._tabViewTabItem.pushAway(true);
               self.setActive(newTab._tabViewTabItem);
 
-              TabItems.creatingNewOrphanTab = false;
+              self.creatingNewOrphanTab = false;
+              // the bounds of tab item is set and we can zoom in now.
               newTab._tabViewTabItem.zoomIn(true);
 
               self._lastClick = 0;
               self._lastClickPositions = null;
               gTabView.firstUseExperienced = true;
             } else {
               self._lastClick = Date.now();
               self._lastClickPositions = new Point(e.clientX, e.clientY);
@@ -509,26 +518,19 @@ let UI = {
 #ifdef XP_MACOSX
     this.setTitlebarColors(true);
 #endif
     let event = document.createEvent("Events");
     event.initEvent("tabviewshown", true, false);
 
     Storage.saveVisibilityData(gWindow, "true");
 
-    // Close the active group if it was empty. This will happen when the
-    // user returns to Panorama after looking at an app tab, having
-    // closed all other tabs. (If the user is looking at an orphan tab, then
-    // there is no active group for the purposes of this check.)
     let activeGroupItem = null;
-    if (!UI.getActiveOrphanTab()) {
+    if (!UI.getActiveOrphanTab())
       activeGroupItem = GroupItems.getActiveGroupItem();
-      if (activeGroupItem && activeGroupItem.closeIfEmpty())
-        activeGroupItem = null;
-    }
 
     if (zoomOut && currentTab && currentTab._tabViewTabItem) {
       item = currentTab._tabViewTabItem;
       // If there was a previous currentTab we want to animate
       // its thumbnail (canvas) for the zoom out.
       // Note that we start the animation on the chrome thread.
 
       // Zoom out!
@@ -624,20 +626,18 @@ let UI = {
   },
 #endif
 
   // ----------
   // Function: storageBusy
   // Pauses the storage activity that conflicts with sessionstore updates and 
   // private browsing mode switches. Calls can be nested. 
   storageBusy: function UI_storageBusy() {
-    if (!this._storageBusyCount) {
+    if (!this._storageBusyCount)
       TabItems.pauseReconnecting();
-      GroupItems.pauseAutoclose();
-    }
     
     this._storageBusyCount++;
   },
   
   // ----------
   // Function: storageReady
   // Resumes the activity paused by storageBusy, and updates for any new group
   // information in sessionstore. Calls can be nested. 
@@ -645,17 +645,16 @@ let UI = {
     this._storageBusyCount--;
     if (!this._storageBusyCount) {
       let hasGroupItemsData = GroupItems.load();
       if (!hasGroupItemsData)
         this.reset();
   
       TabItems.resumeReconnecting();
       GroupItems._updateTabBar();
-      GroupItems.resumeAutoclose();
     }
   },
 
   // ----------
   // Function: _addTabActionHandlers
   // Adds handlers to handle tab actions.
   _addTabActionHandlers: function UI__addTabActionHandlers() {
     var self = this;
@@ -722,16 +721,18 @@ let UI = {
     // TabOpen
     this._eventListeners.open = function(tab) {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
       // if it's an app tab, add it to all the group items
       if (tab.pinned)
         GroupItems.addAppTab(tab);
+      else if (self.isTabViewVisible())
+        self._lastOpenedTab = tab;
     };
     
     // TabClose
     this._eventListeners.close = function(tab) {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
       // if it's an app tab, remove it from all the group items
@@ -768,18 +769,19 @@ let UI = {
           // an un-named groupItem, which means that the groupItem is gone (null) and
           // there are no visible tabs. 
           let closingUnnamedGroup = (groupItem == null &&
               gBrowser.visibleTabs.length <= 1); 
 
           // 3) When a blank tab is active while restoring a closed tab the
           // blank tab gets removed. The active group is not closed as this is
           // where the restored tab goes. So do not show the TabView.
+          let tabItem = tab && tab._tabViewTabItem;
           let closingBlankTabAfterRestore =
-            (tab && tab._tabViewTabIsRemovedAfterRestore);
+            (tabItem && tabItem.isRemovedAfterRestore);
 
           if ((closingLastOfGroup || closingUnnamedGroup) &&
               !closingBlankTabAfterRestore) {
             // for the tab focus event to pick up.
             self._closedLastVisibleTab = true;
             self.showTabView();
           }
         }
@@ -856,57 +858,62 @@ let UI = {
     else
       gBrowser.selectedTab = xulTab;
   },
 
   // ----------
   // Function: onTabSelect
   // Called when the user switches from one tab to another outside of the TabView UI.
   onTabSelect: function UI_onTabSelect(tab) {
-    let currentTab = this._currentTab;
     this._currentTab = tab;
 
-    // if the last visible tab has just been closed, don't show the chrome UI.
-    if (this.isTabViewVisible() &&
-        (this._closedLastVisibleTab || this._closedSelectedTabInTabView ||
-         this.restoredClosedTab)) {
-      if (this.restoredClosedTab) {
-        // when the tab view UI is being displayed, update the thumb for the 
-        // restored closed tab after the page load
-        tab.linkedBrowser.addEventListener("load", function (event) {
-          tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-          TabItems._update(tab);
-        }, true);
+    if (this.isTabViewVisible()) {
+      if (!this.restoredClosedTab && this._lastOpenedTab == tab && 
+        tab._tabViewTabItem) {
+        if (!this.creatingNewOrphanTab)
+          tab._tabViewTabItem.zoomIn(true);
+        this._lastOpenedTab = null;
+        return;
       }
-      this._closedLastVisibleTab = false;
-      this._closedSelectedTabInTabView = false;
-      this.restoredClosedTab = false;
-      return;
+      if (this._closedLastVisibleTab ||
+          (this._closedSelectedTabInTabView && !this.closedLastTabInTabView) ||
+          this.restoredClosedTab) {
+        if (this.restoredClosedTab) {
+          // when the tab view UI is being displayed, update the thumb for the 
+          // restored closed tab after the page load
+          tab.linkedBrowser.addEventListener("load", function (event) {
+            tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
+            TabItems._update(tab);
+          }, true);
+        }
+        this._closedLastVisibleTab = false;
+        this._closedSelectedTabInTabView = false;
+        this.closedLastTabInTabView = false;
+        this.restoredClosedTab = false;
+        return;
+      }
     }
     // reset these vars, just in case.
     this._closedLastVisibleTab = false;
     this._closedSelectedTabInTabView = false;
+    this.closedLastTabInTabView = false;
     this.restoredClosedTab = false;
+    this._lastOpenedTab = null;
 
     // if TabView is visible but we didn't just close the last tab or
     // selected tab, show chrome.
     if (this.isTabViewVisible())
       this.hideTabView();
 
     // another tab might be selected when hideTabView() is invoked so a
     // validation is needed.
     if (this._currentTab != tab)
       return;
 
-    let oldItem = null;
     let newItem = null;
-
-    if (currentTab && currentTab._tabViewTabItem)
-      oldItem = currentTab._tabViewTabItem;
-
     // update the tab bar for the new tab's group
     if (tab && tab._tabViewTabItem) {
       if (!TabItems.reconnectingPaused()) {
         newItem = tab._tabViewTabItem;
         GroupItems.updateActiveGroupItemAndTabBar(newItem);
       }
     } else {
       // No tabItem; must be an app tab. Base the tab bar on the current group.
@@ -1316,17 +1323,18 @@ let UI = {
         // to that groupItem.
         var tabs = GroupItems.getOrphanedTabs();
         var insideTabs = [];
         for each(let tab in tabs) {
           if (bounds.contains(tab.bounds))
             insideTabs.push(tab);
         }
 
-        var groupItem = new GroupItem(insideTabs,{bounds:bounds});
+        let opts = {bounds: bounds, focusTitle: true};
+        let groupItem = new GroupItem(insideTabs, opts);
         self.setActive(groupItem);
         phantom.remove();
         dragOutInfo = null;
         gTabView.firstUseExperienced = true;
       } else {
         collapse();
       }
     }
@@ -1493,24 +1501,24 @@ let UI = {
       hideSearch(null);
     }
 
     if (!zoomedIn) {
       let unhiddenGroups = GroupItems.groupItems.filter(function(groupItem) {
         return (!groupItem.hidden && groupItem.getChildren().length > 0);
       });
       // no pinned tabs, no visible groups and no orphaned tabs: open a new
-      // group. open a blank tab and return
+      // group, a blank tab and return
       if (!unhiddenGroups.length && !GroupItems.getOrphanedTabs().length) {
         let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
           return (!groupItem.hidden && !groupItem.getChildren().length);
         });
         let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
         if (!gBrowser._numPinnedTabs) {
-          group.newTab();
+          group.newTab(null, { closedLastTab: true });
           return;
         }
       }
 
       // If there's an active TabItem, zoom into it. If not (for instance when the
       // selected tab is an app tab), just go there.
       let activeTabItem = this.getActiveTab();
       if (!activeTabItem) {
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -170,16 +170,17 @@ endif
                  browser_bug598923.js \
                  browser_bug599325.js \
                  browser_bug609700.js \
                  browser_bug616836.js \
                  browser_bug623893.js \
                  browser_bug624734.js \
                  browser_bug647886.js \
                  browser_bug655584.js \
+                 browser_bug664672.js \
                  browser_findbarClose.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
                  browser_disablechrome.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
@@ -214,16 +215,17 @@ endif
                  browser_scope.js \
                  browser_selectTabAtIndex.js \
                  browser_tab_dragdrop.js \
                  browser_tab_dragdrop2.js \
                  browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_isActive.js \
                  browser_tabs_owner.js \
+                 browser_urlbarTrimURLs.js \
                  browser_urlHighlight.js \
                  browser_visibleFindSelection.js \
                  browser_visibleTabs.js \
                  browser_visibleTabs_contextMenu.js \
                  browser_visibleTabs_bookmarkAllPages.js \
                  browser_visibleTabs_bookmarkAllTabs.js \
                  browser_visibleTabs_tabPreview.js \
                  bug592338.html \
--- a/browser/base/content/test/browser_bug304198.js
+++ b/browser/base/content/test/browser_bug304198.js
@@ -41,18 +41,16 @@ function test() {
   let charsToDelete, deletedURLTab, fullURLTab, partialURLTab, testPartialURL, testURL;
 
   charsToDelete = 5;
   deletedURLTab = gBrowser.addTab();
   fullURLTab = gBrowser.addTab();
   partialURLTab = gBrowser.addTab();
   testURL = "http://example.org/browser/browser/base/content/test/dummy_page.html";
 
-  testPartialURL = testURL.substr(0, (testURL.length - charsToDelete));
-
   function cleanUp() {
     gBrowser.removeTab(fullURLTab);
     gBrowser.removeTab(partialURLTab);
     gBrowser.removeTab(deletedURLTab);
   }
 
   function cycleTabs() {
     gBrowser.selectedTab = fullURLTab;
@@ -130,16 +128,19 @@ function test() {
         if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll"))
           gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
         cb();
       }
     });
   }
 
   function runTests() {
+    testURL = gURLBar.trimValue(testURL);
+    testPartialURL = testURL.substr(0, (testURL.length - charsToDelete));
+
     // prepare the three tabs required by this test
     prepareFullURLTab(function () {
       preparePartialURLTab(function () {
         prepareDeletedURLTab(function () {
           // now cycle the tabs and make sure everything looks good
           cycleTabs();
           cleanUp();
           finish();
--- a/browser/base/content/test/browser_bug321000.js
+++ b/browser/base/content/test/browser_bug321000.js
@@ -33,19 +33,16 @@
  * 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 kTestString = "  hello hello  \n  world\nworld  ";
 
 var gTests = [
 
   { desc: "Urlbar strips newlines and surrounding whitespace",
     element: gURLBar,
     expected: kTestString.replace(/\s*\n\s*/g,'')
   },
@@ -82,18 +79,17 @@ function next_test() {
 
 function test_paste(aCurrentTest) {
   var element = aCurrentTest.element;
 
   // Register input listener.
   var inputListener = {
     test: aCurrentTest,
     handleEvent: function(event) {
-      var element = event.target;
-      element.removeEventListener("input", this, false);
+      element.removeEventListener(event.type, this, false);
 
       is(element.value, this.test.expected, this.test.desc);
 
       // Clear the field and go to next test.
       element.value = "";
       setTimeout(next_test, 0);
     }
   }
--- a/browser/base/content/test/browser_bug556061.js
+++ b/browser/base/content/test/browser_bug556061.js
@@ -32,16 +32,17 @@
  * 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 testURL = "http://example.org/browser/browser/base/content/test/dummy_page.html";
 let testActionURL = "moz-action:switchtab," + testURL;
+testURL = gURLBar.trimValue(testURL);
 let testTab;
 
 function runNextTest() {
   if (tests.length) {
     let t = tests.shift();
     waitForClipboard(t.expected, t.setup, function() {
       t.success();
       runNextTest();
--- a/browser/base/content/test/browser_bug580956.js
+++ b/browser/base/content/test/browser_bug580956.js
@@ -1,16 +1,17 @@
 function numClosedTabs()
   Cc["@mozilla.org/browser/sessionstore;1"].
     getService(Ci.nsISessionStore).
     getClosedTabCount(window);
 
 function isUndoCloseEnabled() {
   document.popupNode = gBrowser.tabs[0];
   TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
+  TabContextMenu.contextTab = null;
   return !document.getElementById("context_undoCloseTab").disabled;
 }
 
 function test() {
   waitForExplicitFinish();
 
   gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", 0);
   gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug664672.js
@@ -0,0 +1,19 @@
+function test() {
+  waitForExplicitFinish();
+
+  var tab = gBrowser.addTab();
+
+  tab.addEventListener("TabClose", function () {
+    tab.removeEventListener("TabClose", arguments.callee, false);
+
+    ok(tab.linkedBrowser, "linkedBrowser should still exist during the TabClose event");
+
+    executeSoon(function () {
+      ok(!tab.linkedBrowser, "linkedBrowser should be gone after the TabClose event");
+
+      finish();
+    });
+  }, false);
+
+  gBrowser.removeTab(tab);
+}
--- a/browser/base/content/test/browser_plainTextLinks.js
+++ b/browser/base/content/test/browser_plainTextLinks.js
@@ -1,10 +1,15 @@
 let doc, range, selection;
 function setSelection(el1, el2, index1, index2) {
+  while (el1.nodeType != Node.TEXT_NODE)
+    el1 = el1.firstChild;
+  while (el2.nodeType != Node.TEXT_NODE)
+    el2 = el2.firstChild;
+
   selection.removeAllRanges();
   range.setStart(el1, index1);
   range.setEnd(el2, index2);
   selection.addRange(range);
 }
 
 function initContextMenu(aNode) {
   document.popupNode = aNode;
@@ -77,26 +82,34 @@ function runSelectionTests() {
   testExpected(false, "Link options should show for ftp.example.com");
   testLinkExpected("ftp://ftp.example.com/", "ftp.example.com should be preceeded with ftp://");
   setSelection(p2.firstChild, p2.firstChild, 0, 14);
   testExpected(false, "Link options should show for www.example.com  ");
   selection.selectAllChildren(div2);
   testExpected(false, "Link options should show for triple-click selections");
   selection.selectAllChildren(span4);
   testLinkExpected("http://www.example.com/", "Linkified text should open the correct link", span4.firstChild);
+
+  mainDiv.innerHTML = "(open-suse.ru)";
+  setSelection(mainDiv, mainDiv, 1, 13);
+  testExpected(false, "Link options should show for open-suse.ru");
+  testLinkExpected("http://open-suse.ru/", "Linkified text should open the correct link");
+  setSelection(mainDiv, mainDiv, 1, 14);
+  testExpected(true, "Link options should not show for 'open-suse.ru)'");
+
   gBrowser.removeCurrentTab();
   finish();
 }
 
 function test() {
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     range = doc.createRange();
     selection = content.getSelection();
     waitForFocus(runSelectionTests, content);
   }, true);
 
   content.location =
-    "data:text/html,Test For Non-Hyperlinked url selection";
+    "data:text/html;charset=UTF-8,Test For Non-Hyperlinked url selection";
 }
--- a/browser/base/content/test/browser_scratchpad_files.js
+++ b/browser/base/content/test/browser_scratchpad_files.js
@@ -1,16 +1,12 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 // Reference to the Scratchpad chrome window object.
 let gScratchpadWindow;
 
 // Reference to the Scratchpad object.
 let gScratchpad;
--- a/browser/base/content/test/browser_tabMatchesInAwesomebar.js
+++ b/browser/base/content/test/browser_tabMatchesInAwesomebar.js
@@ -31,18 +31,16 @@
  * 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 ***** */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
 const TEST_URL_BASES = [
   "http://example.org/browser/browser/base/content/test/dummy_page.html#tabmatch",
   "http://example.org/browser/browser/base/content/test/moz.png#tabmatch"
 ];
 
 var gPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
                          getService(Ci.nsIPrivateBrowsingService);
 var gController = Cc["@mozilla.org/autocomplete/controller;1"].
--- a/browser/base/content/test/browser_urlHighlight.js
+++ b/browser/base/content/test/browser_urlHighlight.js
@@ -1,8 +1,12 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
 function testVal(aExpected) {
   gURLBar.value = aExpected.replace(/[<>]/g, "");
 
   let selectionController = gURLBar.editor.selectionController;
   let selection = selectionController.getSelection(selectionController.SELECTION_URLSECONDARY);
   let value = gURLBar.editor.rootElement.textContent;
   let result = "";
   for (let i = 0; i < selection.rangeCount; i++) {
@@ -22,46 +26,59 @@ function test() {
     Services.prefs.clearUserPref(prefname);
     URLBarSetURI();
   });
 
   Services.prefs.setBoolPref(prefname, true);
 
   gURLBar.focus();
 
-  testVal("http://mozilla.org/");
+  testVal("https://mozilla.org");
 
   gBrowser.selectedBrowser.focus();
 
-  testVal("<http://>mozilla.org");
-  testVal("<http://>mozilla.org</>");
-  testVal("<http://>mözilla.org</>");
-  testVal("<http://>mozilla.imaginatory</>");
-  testVal("<http://www.>mozilla.org</>");
-  testVal("<http://sub.>mozilla.org</>");
-  testVal("<http://sub1.sub2.sub3.>mozilla.org</>");
-  testVal("<http://ftp.>mozilla.org</>");
-  testVal("<ftp://ftp.>mozilla.org</>");
+  testVal("<https://>mozilla.org");
+  testVal("<https://>mözilla.org");
+  testVal("<https://>mozilla.imaginatory");
+
+  testVal("<https://www.>mozilla.org");
+  testVal("<https://sub.>mozilla.org");
+  testVal("<https://sub1.sub2.sub3.>mozilla.org");
+  testVal("<www.>mozilla.org");
+  testVal("<sub.>mozilla.org");
+  testVal("<sub1.sub2.sub3.>mozilla.org");
+
+  testVal("<http://ftp.>mozilla.org");
+  testVal("<ftp://ftp.>mozilla.org");
 
-  testVal("<https://sub.>mozilla.org</>");
-  testVal("<https://sub1.sub2.sub3.>mozilla.org</>");
-  testVal("<https://user:pass@sub1.sub2.sub3.>mozilla.org</>");
-  testVal("<https://user:pass@>mozilla.org</>");
+  testVal("<https://sub.>mozilla.org");
+  testVal("<https://sub1.sub2.sub3.>mozilla.org");
+  testVal("<https://user:pass@sub1.sub2.sub3.>mozilla.org");
+  testVal("<https://user:pass@>mozilla.org");
 
-  testVal("<http://>mozilla.org</file.ext>");
-  testVal("<http://>mozilla.org</sub/file.ext>");
-  testVal("<http://>mozilla.org</sub/file.ext?foo>");
-  testVal("<http://>mozilla.org</sub/file.ext?foo&bar>");
-  testVal("<http://>mozilla.org</sub/file.ext?foo&bar#top>");
+  testVal("<https://>mozilla.org</file.ext>");
+  testVal("<https://>mozilla.org</sub/file.ext>");
+  testVal("<https://>mozilla.org</sub/file.ext?foo>");
+  testVal("<https://>mozilla.org</sub/file.ext?foo&bar>");
+  testVal("<https://>mozilla.org</sub/file.ext?foo&bar#top>");
+  testVal("<https://>mozilla.org</sub/file.ext?foo&bar#top>");
 
-  testVal("<http://sub.>mozilla.org<:666/file.ext>");
+  testVal("<https://sub.>mozilla.org<:666/file.ext>");
 
-  testVal("<http://>[fe80::222:19ff:fe11:8c76]</file.ext>");
+  testVal("<https://>[fe80::222:19ff:fe11:8c76]</file.ext>");
+  testVal("[fe80::222:19ff:fe11:8c76]</file.ext>");
+  testVal("<https://user:pass@>[fe80::222:19ff:fe11:8c76]<:666/file.ext>");
   testVal("<http://user:pass@>[fe80::222:19ff:fe11:8c76]<:666/file.ext>");
 
   testVal("mailto:admin@mozilla.org");
   testVal("gopher://mozilla.org/");
   testVal("about:config");
+  testVal("jar:http://mozilla.org/example.jar!/");
+  testVal("view-source:http://mozilla.org/");
+  testVal("foo9://mozilla.org/");
+  testVal("foo+://mozilla.org/");
+  testVal("foo.://mozilla.org/");
+  testVal("foo-://mozilla.org/");
 
   Services.prefs.setBoolPref(prefname, false);
 
-  testVal("http://mozilla.org/");
+  testVal("https://mozilla.org");
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_urlbarTrimURLs.js
@@ -0,0 +1,81 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function testVal(originalValue, targetValue) {
+  gURLBar.value = originalValue;
+  is(gURLBar.value, targetValue || originalValue, "original value: " + originalValue);
+}
+
+function test() {
+  const prefname = "browser.urlbar.trimURLs";
+
+  gBrowser.selectedTab = gBrowser.addTab();
+
+  registerCleanupFunction(function () {
+    gBrowser.removeCurrentTab();
+    Services.prefs.clearUserPref(prefname);
+    URLBarSetURI();
+  });
+
+  Services.prefs.setBoolPref(prefname, true);
+
+  testVal("http://mozilla.org/", "mozilla.org");
+  testVal("https://mozilla.org/", "https://mozilla.org");
+  testVal("http://mözilla.org/", "mözilla.org");
+  testVal("http://mozilla.imaginatory/", "mozilla.imaginatory");
+  testVal("http://www.mozilla.org/", "www.mozilla.org");
+  testVal("http://sub.mozilla.org/", "sub.mozilla.org");
+  testVal("http://sub1.sub2.sub3.mozilla.org/", "sub1.sub2.sub3.mozilla.org");
+  testVal("http://mozilla.org/file.ext", "mozilla.org/file.ext");
+  testVal("http://mozilla.org/sub/", "mozilla.org/sub/");
+
+  testVal("http://ftp.mozilla.org/", "http://ftp.mozilla.org");
+  testVal("ftp://ftp.mozilla.org/", "ftp://ftp.mozilla.org");
+
+  testVal("https://user:pass@mozilla.org/", "https://user:pass@mozilla.org");
+  testVal("http://user:pass@mozilla.org/", "http://user:pass@mozilla.org");
+  testVal("http://sub.mozilla.org:666/", "sub.mozilla.org:666");
+
+  testVal("https://[fe80::222:19ff:fe11:8c76]/file.ext");
+  testVal("http://[fe80::222:19ff:fe11:8c76]/", "[fe80::222:19ff:fe11:8c76]");
+  testVal("https://user:pass@[fe80::222:19ff:fe11:8c76]:666/file.ext");
+  testVal("http://user:pass@[fe80::222:19ff:fe11:8c76]:666/file.ext");
+
+  testVal("mailto:admin@mozilla.org");
+  testVal("gopher://mozilla.org/");
+  testVal("about:config");
+  testVal("jar:http://mozilla.org/example.jar!/");
+  testVal("view-source:http://mozilla.org/");
+
+  Services.prefs.setBoolPref(prefname, false);
+
+  testVal("http://mozilla.org/");
+
+  Services.prefs.setBoolPref(prefname, true);
+
+  waitForExplicitFinish();
+
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    is(gBrowser.currentURI.spec, "http://example.com/", "expected page should have loaded");
+
+    testCopy("example.com", "http://example.com/", function () {
+      SetPageProxyState("invalid");
+      testCopy("example.com", "example.com", finish);
+    });
+  }, true);
+
+  gBrowser.loadURI("http://example.com/");
+}
+
+function testCopy(originalValue, targetValue, cb) {
+  waitForClipboard(targetValue, function () {
+    is(gURLBar.value, originalValue);
+
+    gURLBar.focus();
+    gURLBar.select();
+    goDoCommand("cmd_copy");
+  }, cb, cb);
+}
--- a/browser/base/content/test/browser_visibleTabs.js
+++ b/browser/base/content/test/browser_visibleTabs.js
@@ -125,9 +125,12 @@ function test() {
   is(gBrowser.tabs.length, 2, "still have 2 open tabs");
 
   // Close the last visible tab and make sure we still get a visible tab
   gBrowser.removeTab(testTab);
   is(gBrowser.visibleTabs.length, 1, "only orig is left and visible");
   is(gBrowser.tabs.length, 1, "sanity check that it matches");
   is(gBrowser.selectedTab, origTab, "got the orig tab");
   is(origTab.hidden, false, "and it's not hidden -- visible!");
+
+  if (tabViewWindow)
+    tabViewWindow.GroupItems.groupItems[0].close();
 }
--- a/browser/base/content/test/browser_visibleTabs_bookmarkAllTabs.js
+++ b/browser/base/content/test/browser_visibleTabs_bookmarkAllTabs.js
@@ -86,17 +86,18 @@ function test() {
     is(origTab.hidden, false, "and it's not hidden -- visible!");
     finish();
   }, true);
 }
 
 function Disabled() {
   document.popupNode = gBrowser.selectedTab;
   TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
-  let command = document.getElementById("Browser:BookmarkAllTabs");
-  return command.hasAttribute("disabled") && command.getAttribute("disabled") === "true";
+  TabContextMenu.contextTab = null;
+  return document.getElementById("Browser:BookmarkAllTabs").getAttribute("disabled") == "true";
 }
 
 function Hidden() {
   document.popupNode = gBrowser.selectedTab;
   TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
+  TabContextMenu.contextTab = null;
   return document.getElementById("context_bookmarkAllTabs").hidden;
 }
--- a/browser/base/content/test/browser_visibleTabs_contextMenu.js
+++ b/browser/base/content/test/browser_visibleTabs_contextMenu.js
@@ -39,51 +39,49 @@ function test() {
   // There should be one tab when we start the test
   let [origTab] = gBrowser.visibleTabs;
   is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
   let testTab = gBrowser.addTab();
   is(gBrowser.visibleTabs.length, 2, "there are now two visible tabs");
 
   // Check the context menu with two tabs
   popup(origTab);
-  is(TabContextMenu.contextTab, origTab, "TabContextMenu context is the original tab");
   is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled");
   is(document.getElementById("context_reloadAllTabs").disabled, false, "Reload All Tabs is enabled");
 
   // Hide the original tab.
   gBrowser.selectedTab = testTab;
   gBrowser.showOnlyTheseTabs([testTab]);
   is(gBrowser.visibleTabs.length, 1, "now there is only one visible tab");
   
   // Check the context menu with one tab.
   popup(testTab);
-  is(TabContextMenu.contextTab, testTab, "TabContextMenu context is the test tab");
   is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled when more than one tab exists");
   is(document.getElementById("context_reloadAllTabs").disabled, true, "Reload All Tabs is disabled");
   
   // Add a tab that will get pinned
   // So now there's one pinned tab, one visible unpinned tab, and one hidden tab
   let pinned = gBrowser.addTab();
   gBrowser.pinTab(pinned);
   is(gBrowser.visibleTabs.length, 2, "now there are two visible tabs");
 
   // Check the context menu on the unpinned visible tab
   popup(testTab);
-  is(TabContextMenu.contextTab, testTab, "TabContextMenu context is again the test tab");
   is(document.getElementById("context_closeOtherTabs").disabled, true, "Close Other Tabs is disabled");
 
   // Show all tabs
   let allTabs = [tab for each (tab in gBrowser.tabs)];
   gBrowser.showOnlyTheseTabs(allTabs);
 
   // Check the context menu now
   popup(testTab);
-  is(TabContextMenu.contextTab, testTab, "TabContextMenu context is yet again the test tab");
   is(document.getElementById("context_closeOtherTabs").disabled, false, "Close Other Tabs is enabled");
   
   gBrowser.removeTab(testTab);
   gBrowser.removeTab(pinned);
 }
 
 function popup(tab) {
   document.popupNode = tab;
   TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
-}
\ No newline at end of file
+  is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
+  TabContextMenu.contextTab = null;
+}
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -80,16 +80,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug599626.js \
                  browser_tabview_bug600645.js \
                  browser_tabview_bug600812.js \
                  browser_tabview_bug602432.js \
                  browser_tabview_bug604098.js \
                  browser_tabview_bug604699.js \
                  browser_tabview_bug606657.js \
                  browser_tabview_bug606905.js \
+                 browser_tabview_bug607108.js \
                  browser_tabview_bug608037.js \
                  browser_tabview_bug608184.js \
                  browser_tabview_bug608158.js \
                  browser_tabview_bug608405.js \
                  browser_tabview_bug610208.js \
                  browser_tabview_bug610242.js \
                  browser_tabview_bug612470.js \
                  browser_tabview_bug613541.js \
@@ -143,16 +144,18 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug649307.js \
                  browser_tabview_bug649319.js \
                  browser_tabview_bug650573.js \
                  browser_tabview_bug651311.js \
                  browser_tabview_bug654941.js \
                  browser_tabview_bug655269.js \
                  browser_tabview_bug656778.js \
                  browser_tabview_bug656913.js \
+                 browser_tabview_bug662266.js \
+                 browser_tabview_bug665502.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_expander.js \
                  browser_tabview_firstrun_pref.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
                  browser_tabview_orphaned_tabs.js \
--- a/browser/base/content/test/tabview/browser_tabview_bug587276.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug587276.js
@@ -31,57 +31,60 @@ function test2() {
   });
   EventUtils.synthesizeKey("f", { accelKey: true }, contentWindow);
 }
 
 function test3() {
   ok(!contentWindow.isSearchEnabled(), "The search is disabled")
 
   is(gBrowser.tabs.length, 1, "There is one tab before cmd/ctrl + t is pressed");
-  EventUtils.synthesizeKey("t", { accelKey: true }, contentWindow);
-  is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + t is pressed");
+
+  whenTabViewIsHidden(function() { 
+    is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + t is pressed");
 
-  gBrowser.tabs[0].linkedBrowser.loadURI("about:robots");
-  gBrowser.tabs[1].linkedBrowser.loadURI("http://example.com/");
+    gBrowser.tabs[0].linkedBrowser.loadURI("about:robots");
+    gBrowser.tabs[1].linkedBrowser.loadURI("http://example.com/");
 
-  afterAllTabsLoaded(function () {
-    showTabView(test4);
+    afterAllTabsLoaded(function () {
+      showTabView(test4);
+    });
   });
+  EventUtils.synthesizeKey("t", { accelKey: true }, contentWindow);
 }
 
 function test4() {
   is(gBrowser.tabs.length, 2, "There are two tabs");
-  
+
   let onTabClose = function() {
     gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, true);
     executeSoon(function() {
       is(gBrowser.tabs.length, 1, "There is one tab after removing one");
 
       EventUtils.synthesizeKey("T", { accelKey: true, shiftKey: true }, contentWindow);
       is(gBrowser.tabs.length, 2, "There are two tabs after restoring one");
 
       gBrowser.tabs[0].linkedBrowser.loadURI("about:blank");
-      gBrowser.removeTab(gBrowser.tabs[1]);
+      gBrowser.selectedTab = gBrowser.tabs[0];
       test8();
     });
   };
   gBrowser.tabContainer.addEventListener("TabClose", onTabClose, true);
   gBrowser.removeTab(gBrowser.tabs[1]);
 }
 
 // below key combination shouldn't trigger actions in tabview UI
 function test8() {
-  let newTab = gBrowser.loadOneTab("about:blank", { inBackground: true });
+  showTabView(function() {
+    is(gBrowser.tabs.length, 2, "There are two tabs before cmd/ctrl + w is pressed");
+    EventUtils.synthesizeKey("w", { accelKey: true }, contentWindow);
+    is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + w is pressed");
 
-  is(gBrowser.tabs.length, 2, "There are two tabs before cmd/ctrl + w is pressed");
-  EventUtils.synthesizeKey("w", { accelKey: true }, contentWindow);
-  is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + w is pressed");
-
-  gBrowser.removeTab(newTab);
-  test9();
+    gBrowser.removeTab(gBrowser.tabs[1]);
+    test9();
+  });
 }
 
 function test9() {
   let zoomLevel = ZoomManager.zoom;
   EventUtils.synthesizeKey("+", { accelKey: true }, contentWindow);
   is(ZoomManager.zoom, zoomLevel, "The zoom level remains unchanged after cmd/ctrl + + is pressed");
 
   EventUtils.synthesizeKey("-", { accelKey: true }, contentWindow);
--- a/browser/base/content/test/tabview/browser_tabview_bug587990.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug587990.js
@@ -1,69 +1,31 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let newTab;
-let win;
+function test() {
+  let newTab;
 
-function test() {
-  waitForExplicitFinish();
-
-  win = window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", "about:blank");
-
-  let onLoad = function() {
-    win.removeEventListener("load", onLoad, false);
+  let onLoad = function (win) {
+    registerCleanupFunction(function () win.close());
 
     newTab = win.gBrowser.addTab();
 
-    let onTabViewFrameInitialized = function() {
-      win.removeEventListener(
-        "tabviewframeinitialized", onTabViewFrameInitialized, false);
+    let popup = win.document.getElementById("context_tabViewMenuPopup");
+    win.TabView.updateContextMenu(newTab, popup);
+  };
 
-      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();
+  let onShow = function (win) {
+    let cw = win.TabView.getContentWindow();
+    is(cw.GroupItems.groupItems.length, 1, "Has only one group");
 
-  is(tabItems[tabItems.length - 1].tab, newTab, "The new tab exists in the group");
+    let groupItem = cw.GroupItems.groupItems[0];
+    let tabItems = groupItem.getChildren();
 
-  win.gBrowser.removeTab(newTab);
-  whenWindowObservesOnce(win, "domwindowclosed", function() {
-    finish();
-  });
-  win.close();
-}
+    let tab = tabItems[tabItems.length - 1].tab;
+    is(tab, newTab, "The new tab exists in the group");
 
-function whenWindowObservesOnce(win, topic, func) {
-    let windowWatcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-      .getService(Components.interfaces.nsIWindowWatcher);
-    let origWin = win;
-    let origTopic = topic;
-    let origFunc = func;        
-    function windowObserver(aSubject, aTopic, aData) {
-      let theWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
-      if (origWin && theWin != origWin)
-        return;
-      if(aTopic == origTopic) {
-          windowWatcher.unregisterNotification(windowObserver);
-          origFunc.apply(this, []);
-      }
-    }
-    windowWatcher.registerNotification(windowObserver);
+    finish();
+  };
+
+  waitForExplicitFinish();
+  newWindowWithTabView(onShow, onLoad);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug589324.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug589324.js
@@ -1,13 +1,11 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-
 const DUMMY_PAGE_URL = "http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html";
 const DUMMY_PAGE_URL_2 = "http://mochi.test:8888/";
 
 let state = {
   windows: [{
     tabs: [{
       entries: [{ url: DUMMY_PAGE_URL }],
       hidden: true,
@@ -49,20 +47,17 @@ function test() {
   registerCleanupFunction(function () {
     Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
   });
 
   Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", false);
 
   testTabSwitchAfterRestore(function () {
     Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", true);
-
-    testTabSwitchAfterRestore(function () {
-      waitForFocus(finish);
-    });
+    testTabSwitchAfterRestore(finish);
   });
 }
 
 function testTabSwitchAfterRestore(callback) {
   newWindowWithState(state, function (win) {
     registerCleanupFunction(function () win.close());
 
     let [firstTab, secondTab] = win.gBrowser.tabs;
@@ -87,35 +82,8 @@ function testTabSwitchAfterRestore(callb
 
       callback();
     }, false);
 
     // switch to another tab
     win.switchToTabHavingURI(DUMMY_PAGE_URL);
   });
 }
-
-function newWindowWithState(state, callback) {
-  let opts = "chrome,all,dialog=no,height=800,width=800";
-  let win = window.openDialog(getBrowserURL(), "_blank", opts);
-
-  whenWindowLoaded(win, function () {
-    ss.setWindowState(win, JSON.stringify(state), true);
-  });
-
-  whenWindowStateReady(win, function () {
-    afterAllTabsLoaded(function () callback(win), win);
-  });
-}
-
-function whenWindowLoaded(win, callback) {
-  win.addEventListener("load", function onLoad() {
-    win.removeEventListener("load", onLoad, false);
-    executeSoon(callback);
-  }, false);
-}
-
-function whenWindowStateReady(win, callback) {
-  win.addEventListener("SSWindowStateReady", function onReady() {
-    win.removeEventListener("SSWindowStateReady", onReady, false);
-    executeSoon(callback);
-  }, false);
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug590606.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug590606.js
@@ -67,13 +67,11 @@ function testGroupSwitch(contentWindow, 
   // switch to groupItemOne
   tabItem = contentWindow.GroupItems.getNextGroupItemTab(false);
   if (tabItem)
     gBrowser.selectedTab = tabItem.tab;
   is(gBrowser.selectedTab, groupItemOne.getChild(1).tab,
     "The currently selected tab should be the second tab in the groupItemOne");
 
   // cleanup.
-  gBrowser.removeTab(groupItemTwo.getChild(0).tab);
   gBrowser.removeTab(newTabOne);
-
-  finish();
+  closeGroupItem(groupItemTwo, finish);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug595020.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595020.js
@@ -17,17 +17,17 @@ function test() {
   let testGroupNameChange = function (win) {
     showTabView(function () {
       let cw = win.TabView.getContentWindow();
       let groupItem = cw.GroupItems.groupItems[0];
       groupItem.setTitle("new-title");
 
       hideTabView(function () {
         assertWindowTitle(win, "new-title");
-        waitForFocus(finish);
+        finish();
       }, win);
     }, win);
   };
 
   waitForExplicitFinish();
 
   newWindowWithState(stateStartup, function (win) {
     registerCleanupFunction(function () win.close());
--- a/browser/base/content/test/tabview/browser_tabview_bug595943.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595943.js
@@ -53,23 +53,25 @@ function onTabViewWindowLoaded() {
     ok(!TabView.isVisible(), "Tab View remains hidden");
   
     // clean up
     gBrowser.selectedTab = originalTab;
     
     gBrowser.unpinTab(appXulTab);
     gBrowser.removeTab(appXulTab);
 
-    ok(groupItem.closeIfEmpty(), "the second group was empty");
+    ok(!groupItem.getChildren().length, "the second group is empty");
 
-    // Verify ending state
-    is(gBrowser.tabs.length, 1, "we finish with one tab");
-    is(contentWindow.GroupItems.groupItems.length, 1,
-       "we finish with one group");
-    ok(!TabView.isVisible(), "we finish with Tab View hidden");
-      
-    finish();
+    closeGroupItem(groupItem, function () {
+      // Verify ending state
+      is(gBrowser.tabs.length, 1, "we finish with one tab");
+      is(contentWindow.GroupItems.groupItems.length, 1,
+         "we finish with one group");
+      ok(!TabView.isVisible(), "we finish with Tab View hidden");
+  
+      finish();
+    });
   }
 
   window.addEventListener("tabviewhidden", onTabViewHidden, false);
   EventUtils.sendMouseEvent({ type: "mousedown" }, normalXulTab._tabViewTabItem.container, contentWindow);
   EventUtils.sendMouseEvent({ type: "mouseup" }, normalXulTab._tabViewTabItem.container, contentWindow);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug598600.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug598600.js
@@ -64,11 +64,11 @@ function test() {
       is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
 
       // clean up and finish
       newWin.close();
 
       finish();
     }
     newWin.addEventListener("tabviewshown", onTabViewShow, false);
-    newWin.TabView.toggle();
+    waitForFocus(function() { newWin.TabView.toggle(); });
   }, false);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug600812.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug600812.js
@@ -23,22 +23,25 @@ function test() {
 
     let sourceTab = sourceGroup.getChild(0).container;
     EventUtils.synthesizeMouseAtCenter(sourceTab, {type: 'mousedown'}, cw);
 
     let targetTab = targetGroup.getChild(0).container;
     EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mousemove'}, cw);
     EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mouseup'}, cw);
 
+    is(cw.GroupItems.groupItems.length, 2, 'there are two groupItems');
+    is(sourceGroup.getChildren().length, 0, 'source group has no tabs');
     is(targetGroup.getChildren().length, 2, 'target group has two tabs');
-    is(cw.GroupItems.groupItems.length, 1, 'sourceGroup was closed');
-    isnot(cw.GroupItems.groupItems[0], sourceGroup, 'sourceGroup was closed');
 
     targetGroup.getChild(0).close();
-    hideTabView(finish);
+
+    closeGroupItem(sourceGroup, function () {
+      hideTabView(finish);
+    });
   }
 
   waitForExplicitFinish();
 
   showTabView(function () {
     cw = TabView.getContentWindow();
     afterAllTabsLoaded(testVeryQuickDragAndDrop);
   });
--- a/browser/base/content/test/tabview/browser_tabview_bug604098.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug604098.js
@@ -4,61 +4,49 @@
 let originalTab;
 let orphanedTab;
 let contentWindow;
 let contentElement;
 
 function test() {
   waitForExplicitFinish();
 
+  registerCleanupFunction(function() {
+    if (gBrowser.tabs.length > 1)
+      gBrowser.removeTab(gBrowser.tabs[1]);
+    hideTabView(function() {});
+  });
+
   showTabView(function() {
     contentWindow = TabView.getContentWindow();
     contentElement = contentWindow.document.getElementById("content");
     originalTab = gBrowser.visibleTabs[0];
     test1();
   });
 }
 
 function test1() {
   is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
 
   whenTabViewIsHidden(function() {
     showTabView(function() {
       is(contentWindow.GroupItems.getOrphanedTabs().length, 1,
          "An orphaned tab is created");
-      orphanedTab = contentWindow.GroupItems.getOrphanedTabs()[0].tab;
-
-      test2();
+      hideTabView(function() {
+        gBrowser.selectedTab = originalTab;
+        finish();
+      });
     });
   });
 
   // first click
   mouseClick(contentElement, 0);
   // second click
   mouseClick(contentElement, 0);
 }
 
-function test2() {
-  let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
-  is(groupItem.getChildren().length, 0, "The group is empty");
-
-  hideTabView(function() {
-    is(groupItem.getChildren().length, 1, "A tab is created inside the group");
-
-    gBrowser.selectedTab = originalTab;
-    gBrowser.removeTab(orphanedTab);
-    gBrowser.removeTab(groupItem.getChildren()[0].tab);
-
-    finish();
-  });
-
-  // first click
-  mouseClick(groupItem.container, 0);
-  // second click
-  mouseClick(groupItem.container, 0);
-}
-
 function mouseClick(targetElement, buttonCode) {
   EventUtils.sendMouseEvent(
     { type: "mousedown", button: buttonCode }, targetElement, contentWindow);
   EventUtils.sendMouseEvent(
     { type: "mouseup", button: buttonCode }, targetElement, contentWindow);
 }
+
--- a/browser/base/content/test/tabview/browser_tabview_bug606905.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug606905.js
@@ -17,16 +17,18 @@ function test() {
 
     // move a tab to another group and check the closebuttons attribute
     TabView._initFrame(function() {
       TabView.moveTabTo(newTabs[newTabs.length - 1], null);
       ok(gBrowser.visibleTabs[0].getBoundingClientRect().width > gBrowser.tabContainer.mTabClipWidth, 
          "Tab width is bigger than tab clip width");
       is(gBrowser.tabContainer.getAttribute("closebuttons"), "alltabs", "Show button on all tabs.")
 
+      let cw = TabView.getContentWindow();
+      let groupItems = cw.GroupItems.groupItems;
+      is(groupItems.length, 2, "there are two groupItems");
+
       // clean up and finish
-      newTabs.forEach(function(tab) {
-        gBrowser.removeTab(tab);
-      });
-      finish();
+      newTabs.forEach(function (tab) gBrowser.removeTab(tab));
+      closeGroupItem(groupItems[1], finish);
     });
   });
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug607108.js
@@ -0,0 +1,88 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let cw;
+
+  let assertNumberOfGroupItems = function (num) {
+    let groupItems = cw.GroupItems.groupItems;
+    is(groupItems.length, num, "number of groupItems is " + num);
+  };
+
+  let dragTabOutOfGroup = function (groupItem) {
+    let tabItem = groupItem.getChild(0);
+    let target = tabItem.container;
+
+    EventUtils.synthesizeMouseAtCenter(target, {type: "mousedown"}, cw);
+    EventUtils.synthesizeMouse(target, 400, 100, {type: "mousemove"}, cw);
+    EventUtils.synthesizeMouseAtCenter(target, {type: "mouseup"}, cw);
+  };
+
+  let testCreateGroup = function (callback) {
+    let content = cw.document.getElementById("content");
+
+    // drag to create a new group
+    EventUtils.synthesizeMouse(content, 350, 50, {type: "mousedown"}, cw);
+    EventUtils.synthesizeMouse(content, 500, 250, {type: "mousemove"}, cw);
+    EventUtils.synthesizeMouse(content, 500, 250, {type: "mouseup"}, cw);
+
+    // enter a title for the new group
+    EventUtils.synthesizeKey("t", {}, cw);
+    EventUtils.synthesizeKey("VK_RETURN", {}, cw);
+
+    assertNumberOfGroupItems(2);
+
+    let groupItem = cw.GroupItems.groupItems[1];
+    is(groupItem.getTitle(), "t", "new groupItem's title is correct");
+
+    groupItem.addSubscriber(groupItem, "close", function () {
+      groupItem.removeSubscriber(groupItem, "close");
+      executeSoon(callback);
+    });
+
+    groupItem.closeAll();
+  };
+
+  let testDropOnOrphan = function (callback) {
+    assertNumberOfGroupItems(1);
+
+    let groupItem = cw.GroupItems.groupItems[0];
+    dragTabOutOfGroup(groupItem);
+    dragTabOutOfGroup(groupItem);
+    assertNumberOfGroupItems(2);
+
+    // enter a title for the new group
+    EventUtils.synthesizeKey("t", {}, cw);
+    EventUtils.synthesizeKey("VK_RETURN", {}, cw);
+
+    groupItem = cw.GroupItems.groupItems[1];
+    is(groupItem.getTitle(), "t", "new groupItem's title is correct");
+    closeGroupItem(groupItem, callback);
+  };
+
+  let onLoad = function (win) {
+    registerCleanupFunction(function () win.close());
+
+    for (let i = 0; i < 2; i++)
+      win.gBrowser.loadOneTab("about:blank", {inBackground: true});
+  };
+
+  let onShow = function (win) {
+    cw = win.TabView.getContentWindow();
+    assertNumberOfGroupItems(1);
+
+    let groupItem = cw.GroupItems.groupItems[0];
+    groupItem.setSize(200, 600, true);
+
+    waitForFocus(function () {
+      testCreateGroup(function () {
+        testDropOnOrphan(function () {
+          waitForFocus(finish);
+        });
+      });
+    }, cw);
+  };
+
+  waitForExplicitFinish();
+  newWindowWithTabView(onShow, onLoad);
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug608037.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug608037.js
@@ -9,50 +9,34 @@ function test() {
 
   tabOne = gBrowser.addTab("http://mochi.test:8888/");
   tabTwo = gBrowser.addTab("http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html");
 
   afterAllTabsLoaded(function () {
     // make sure the tab one is selected because undoCloseTab() would remove
     // the selected tab if it's a blank tab.
     gBrowser.selectedTab = tabOne;
-    showTabView(onTabViewWindowLoaded);
+    showTabView(onTabViewShown);
   });
 }
 
-function onTabViewWindowLoaded() {
+function onTabViewShown() {
   let contentWindow = TabView.getContentWindow();
   let groupItems = contentWindow.GroupItems.groupItems;
   is(groupItems.length, 1, "There is only one group");
   is(groupItems[0].getChildren().length, 3, "The group has three tab items");
 
   gBrowser.removeTab(tabTwo);
   ok(TabView.isVisible(), "Tab View is still visible after removing a tab");
   is(groupItems[0].getChildren().length, 2, "The group has two tab items");
 
-  tabTwo = undoCloseTab(0);
-  whenTabIsReconnected(tabTwo, function() {
+  restoreTab(function (tabTwo) {
     ok(TabView.isVisible(), "Tab View is still visible after restoring a tab");
     is(groupItems[0].getChildren().length, 3, "The group still has three tab items");
 
     // clean up and finish
     hideTabView(function () {
       gBrowser.removeTab(tabOne);
       gBrowser.removeTab(tabTwo);
       finish();
     });
   });
 }
-
-// ----------
-function whenTabIsReconnected(tab, callback) {
-  let tabItem = tab._tabViewTabItem;
-
-  if (tabItem._reconnected) {
-    callback();
-    return;
-  }
-
-  tabItem.addSubscriber(tabItem, "reconnected", function () {
-    tabItem.removeSubscriber(tabItem, "reconnected");
-    callback();
-  });
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug608184.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug608184.js
@@ -20,17 +20,16 @@ function test() {
     TabView.moveTabTo(newTab, null);
 
     // close the related tab
     gBrowser.removeTab(relatedTab);
 
     is(gBrowser.visibleTabs.length, 1, "The number of visible tabs is 1");
     is(gBrowser.visibleTabs[0], origTab, 
       "The original tab is the only visible tab");
-    isnot(newTab._tabViewTabItem.parent.id, newTabGroupItemId, 
+
+    let groupItem = newTab._tabViewTabItem.parent;
+    isnot(groupItem.id, newTabGroupItemId, 
       "The moved tab item has a new group id");
 
-    // clean up
-    gBrowser.removeTab(newTab);
-
-    finish();
+    closeGroupItem(groupItem, finish);
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug608405.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug608405.js
@@ -31,22 +31,24 @@ function test() {
       is(sourceGroup.getChildren().length, 1, 'setup: source group has one child');
       is(targetGroup.getChildren().length, 1, 'setup: target group has one child');
 
       let tabItem = sourceGroup.getChild(0);
       targetGroup.add(tabItem);
 
       // check state after adding tabItem to targetGroup
       is(tabItem.parent, targetGroup, 'tabItem changed groups');
-      is(cw.GroupItems.groupItems.length, 1, 'source group was closed automatically');
+      is(sourceGroup.getChildren().length, 0, 'source group has no children');
       is(targetGroup.getChildren().length, 2, 'target group has now two children');
 
       // cleanup and finish
-      tabItem.close();
-      hideTabView(finishTest);
+      closeGroupItem(sourceGroup, function () {
+        tabItem.close();
+        hideTabView(finishTest);
+      });
     });
   }
 
   waitForExplicitFinish();
 
   showTabView(function () {
     cw = TabView.getContentWindow();
     testAddChildFromAnotherGroup();
--- a/browser/base/content/test/tabview/browser_tabview_bug612470.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug612470.js
@@ -30,19 +30,16 @@ function test() {
     executeSoon(function () {
       is(win.gBrowser.visibleTabs.length, 2, "There are two tabs displayed");
       win.gBrowser.removeTab(tab);
 
       is(groupItem.getChildren().length, 0, "No tabs are in the new group");
       is(win.gBrowser.visibleTabs.length, 1, "There is one tab displayed");
       is(cw.GroupItems.groupItems.length, 2, "There are two groups still");
 
-      showTabView(function () {
-        is(cw.GroupItems.groupItems.length, 1, "There is now only one group");
-        waitForFocus(finish);
-      }, win);
+      waitForFocus(finish);
     });
   };
 
   waitForExplicitFinish();
 
   newWindowWithTabView(onShow, onLoad);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug613541.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug613541.js
@@ -15,33 +15,16 @@ function test() {
     cw.UI.setActive(groupItem);
 
     for (let i=0; i<numTabs || 0; i++)
       gBrowser.loadOneTab('about:blank', {inBackground: true});
 
     return groupItem;
   }
 
-  let hideGroupItem = function (groupItem, callback) {
-    groupItem.addSubscriber(groupItem, 'groupHidden', function () {
-      groupItem.removeSubscriber(groupItem, 'groupHidden');
-      callback();
-    });
-    groupItem.closeAll();
-  }
-
-  let closeGroupItem = function (groupItem, callback) {
-    afterAllTabsLoaded(function () {
-      hideGroupItem(groupItem, function () {
-        groupItem.closeHidden();
-        callback();
-      });
-    });
-  }
-
   let tests = [];
 
   let next = function () {
     let test = tests.shift();
 
     if (test) {
       // check that the previous test left things as expected
       if (currentTest) {
@@ -209,59 +192,68 @@ function test() {
   // setup: 1 orphan tab
   // action: exit panorama
   // expected: nothing should happen
   let testOrphanTab1 = function () {
     let groupItem = getGroupItem(0);
     let tabItem = groupItem.getChild(0);
     groupItem.remove(tabItem);
 
-    hideTabView(function () {
+    closeGroupItem(groupItem, function () {
       assertNumberOfGroupItems(0);
-      createGroupItem().add(tabItem);
-      next();
+
+      hideTabView(function () {
+        createGroupItem().add(tabItem);
+        next();
+      });
     });
   }
 
   // setup: 1 orphan tab, 1 non-empty group
   // action: close the group
   // expected: nothing should happen
   let testOrphanTab2 = function () {
     let groupItem = getGroupItem(0);
     let tabItem = groupItem.getChild(0);
     groupItem.remove(tabItem);
 
-    assertNumberOfGroupItems(0);
-    let newGroupItem = createGroupItem(1);
-    assertNumberOfGroupItems(1);
+    closeGroupItem(groupItem, function () {
+      assertNumberOfGroupItems(0);
+
+      let newGroupItem = createGroupItem(1);
+      assertNumberOfGroupItems(1);
 
-    closeGroupItem(newGroupItem, function () {
-      assertNumberOfGroupItems(0);
-      createGroupItem().add(tabItem);
-      hideTabView(next);
+      closeGroupItem(newGroupItem, function () {
+        assertNumberOfGroupItems(0);
+        createGroupItem().add(tabItem);
+        hideTabView(next);
+      });
     });
   }
 
   // setup: 1 orphan tab, 1 non-empty group
   // action: hide the group, exit panorama
   // expected: nothing should happen
   let testOrphanTab3 = function () {
     let groupItem = getGroupItem(0);
     let tabItem = groupItem.getChild(0);
     groupItem.remove(tabItem);
 
-    assertNumberOfGroupItems(0);
-    let newGroupItem = createGroupItem(1);
-    assertNumberOfGroupItems(1);
+    closeGroupItem(groupItem, function () {
+      assertNumberOfGroupItems(0);
+
+      let newGroupItem = createGroupItem(1);
+      assertNumberOfGroupItems(1);
 
-    hideGroupItem(newGroupItem, function () {
-      hideTabView(function () {
-        assertNumberOfGroupItems(0);
-        createGroupItem().add(tabItem);
-        next();
+      hideGroupItem(newGroupItem, function () {
+        hideTabView(function () {
+          assertNumberOfGroupItems(0);
+          createGroupItem().add(tabItem);
+          next();
+        });
       });
     });
   }
 
   // setup: 1 non-empty group, 1 empty group
   // action: close non-empty group
   // expected: empty group is re-used, new tab is created and zoomed into
   let testEmptyGroup1 = function () {
--- a/browser/base/content/test/tabview/browser_tabview_bug616729.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug616729.js
@@ -34,20 +34,16 @@ function test() {
     tests.push([tab2, tab1, tab3]);
     tests.push([tab2, tab3, tab1]);
     tests.push([tab3, tab1, tab2]);
     tests.push([tab3, tab2, tab1]);
     tests.push([tab1, tab2]);
     tests.push([tab2, tab1]);
     tests.push([tab1]);
 
-    // test reordering of empty groups - removes the last tab and causes
-    // the groupItem to close
-    tests.push([]);
-
     while (tests.length) {
       let test = tests.shift();
 
       // prepare
       let items = groupItem.getChildren();
       while (test.length < items.length)
         items[items.length-1].close();
 
@@ -58,17 +54,17 @@ function test() {
       groupItem.reorderTabsBasedOnTabItemOrder();
       assertCorrectItemOrder(items);
 
       // revert to original item order
       items.sort(function (a, b) orig.indexOf(a) - orig.indexOf(b));
       groupItem.reorderTabsBasedOnTabItemOrder();
     }
 
-    testMoveBetweenGroups();
+    closeGroupItem(groupItem, testMoveBetweenGroups);
   }
 
   let testMoveBetweenGroups = function () {
     let groupItem = createGroupItem();
     let groupItem2 = createGroupItem();
     
     afterAllTabsLoaded(function () {
       // move item from group1 to group2
--- a/browser/base/content/test/tabview/browser_tabview_bug622872.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug622872.js
@@ -59,21 +59,18 @@ function part1(win) {
     is(win.gBrowser.tabs.length, 1, "Only one tab again.");
     is(win.gBrowser.tabs[0], originalTab, "That one tab is the original tab.");
 
     let groupItems = contentWindow.GroupItems.groupItems;
     is(groupItems.length, 1, "Only one group");
 
     ok(!contentWindow.UI.getActiveOrphanTab(), "There is no active orphan tab.");
     ok(win.TabView.isVisible(), "Tab View is visible.");
-
-    win.gBrowser.tabContainer.addEventListener("TabSelect", function() {
-      win.gBrowser.tabContainer.removeEventListener("TabSelect", arguments.callee, false);
-      executeSoon(part4);
-    }, false);
+  
+    whenTabViewIsHidden(part4, win);
     win.document.getElementById("cmd_newNavigatorTab").doCommand();
   }
 
   // PART 4: verify it opened in the original group, and go back into Panorama
   let part4 = function part4() {
     ok(!win.TabView.isVisible(), "Tab View is hidden");
 
     is(win.gBrowser.tabs.length, 2, "There are two tabs total now.");
--- a/browser/base/content/test/tabview/browser_tabview_bug624265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624265.js
@@ -114,17 +114,18 @@ function test() {
     gBrowser.selectedTab = gBrowser.loadOneTab('http://mochi.test:8888/#3', {inBackground: true});
     gBrowser.loadOneTab('http://mochi.test:8888/#4', {inBackground: true});
 
     afterAllTabsLoaded(function () {
       assertNumberOfVisibleTabs(2);
 
       enterAndLeavePrivateBrowsing(function () {
         assertNumberOfVisibleTabs(2);
-        next();
+        gBrowser.selectedTab = gBrowser.tabs[0];
+        closeGroupItem(cw.GroupItems.groupItems[1], next);
       });
     });
   }
 
   waitForExplicitFinish();
 
   // tests for #624265
   tests.push(testUndoCloseTabs);
--- a/browser/base/content/test/tabview/browser_tabview_bug624847.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624847.js
@@ -36,30 +36,16 @@ function test() {
   let createTab = function (url) {
     return gBrowser.loadOneTab(url || 'http://mochi.test:8888/', {inBackground: true});
   }
 
   let createBlankTab = function () {
     return createTab('about:blank');
   }
 
-  let restoreTab = function (callback) {
-    let tab = undoCloseTab(0);
-
-    if (tab._tabViewTabItem._reconnected) {
-      afterAllTabsLoaded(callback);
-      return;
-    }
-
-    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
-      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
-      afterAllTabsLoaded(callback);
-    });
-  }
-
   let finishTest = function () {
     prefix = 'finish';
     assertValidPrerequisites();
     finish();
   }
 
   let testUndoCloseWithSelectedBlankTab = function () {
     prefix = 'unpinned';
--- a/browser/base/content/test/tabview/browser_tabview_bug625195.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug625195.js
@@ -28,26 +28,25 @@ function test() {
     ok(tabItems.length, 2, "There are two tabItems in this group");
 
     whenTabViewIsHidden(function() {
       popup(gBrowser.tabs[0]);
 
       ok(!document.getElementById("context_closeTab").disabled, "The 'Close tab' menu item is enabled");
       ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
 
-      let newTabTwo = gBrowser.selectedTab;
       gBrowser.selected = originalTab;
-
       gBrowser.removeTab(newTabOne);
-      gBrowser.removeTab(newTabTwo);
 
-      finish();
+      closeGroupItem(newGroup, finish);
     });
     let newGroup = contentWindow.GroupItems.newGroup();
     newGroup.newTab();
   });
 }
 
 function popup(tab) {
   document.popupNode = tab;
   TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
+  is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
+  TabContextMenu.contextTab = null;
 }
 
--- a/browser/base/content/test/tabview/browser_tabview_bug626368.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug626368.js
@@ -34,17 +34,19 @@ function test() {
     synthesizeMiddleMouseDrag(tabContainer, 200);
     is(groupItem.getChild(0), tabItem, 'tabItem was not closed');
     ok(bounds.equals(tabItem.getBounds()), 'bounds did not change');
 
     // try to drag and let the mouse stay within tab bounds
     synthesizeMiddleMouseDrag(tabContainer, 10);
     ok(!groupItem.getChild(0), 'tabItem was closed');
 
-    hideTabView(finish);
+    closeGroupItem(groupItem, function () {
+      hideTabView(finish);
+    });
   }
 
   waitForExplicitFinish();
 
   showTabView(function () {
     cw = TabView.getContentWindow();
     afterAllTabsLoaded(testDragAndDropWithMiddleMouseButton);
   });
--- a/browser/base/content/test/tabview/browser_tabview_bug626791.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug626791.js
@@ -134,46 +134,45 @@ function test() {
       next();
     });
   }
 
   let tests = [testNameGroup, testDragToCreateGroup, testCreateOrphan,
                testDragToCreateOrphan, testReAddingAfterRemoval];
 
   let next = function () {
+    if (win)
+      win.close();
+
     let test = tests.shift();
 
     if (!test) {
       finish();
       return;
     }
 
-    if (win)
-      win.close();
-
     TabView.firstUseExperienced = false;
 
     let onLoad = function (newWin) {
       win = newWin;
       removeToolbarButton();
-    }
+    };
 
     let onShow = function () {
       cw = win.TabView.getContentWindow();
 
       let groupItem = cw.GroupItems.groupItems[0];
       groupItem.setSize(200, 200, true);
       groupItem.setUserSize();
 
       SimpleTest.waitForFocus(function () {
         assertToolbarButtonNotExists();
         test();
       }, cw);
-    }
+    };
 
     newWindowWithTabView(onShow, onLoad);
   }
 
   waitForExplicitFinish();
-  registerCleanupFunction(function () win && win.close());
 
   next();
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug627288.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627288.js
@@ -10,32 +10,34 @@ function test() {
 
     afterAllTabsLoaded(function () {
       let tabItem = tab._tabViewTabItem;
       let data = tabItem.getStorageData(true);
       gBrowser.removeTab(tab);
 
       cw.TabItems.pauseReconnecting();
       tab = gBrowser.loadOneTab('http://mochi.test:8888/', {inBackground: true});
-      cw.Storage.saveTab(tab, data);
 
-      whenTabAttrModified(tab, function () {
+      afterAllTabsLoaded(function () {
         tabItem = tab._tabViewTabItem;
 
-        // Hook into loadedCachedImageData since loading cached thumbnails 
-        // is asynchronous.
-        tabItem.addSubscriber(tabItem, "loadedCachedImageData", function(item) {
-          item.removeSubscriber(item, "loadedCachedImageData");
+        tabItem.addSubscriber(tabItem, "savedCachedImageData", function () {
+          tabItem.removeSubscriber(tabItem, "savedCachedImageData");
+
+          tabItem.addSubscriber(tabItem, "loadedCachedImageData", function () {
+            tabItem.removeSubscriber(tabItem, "loadedCachedImageData");
 
-          ok(tabItem.isShowingCachedData(), 'tabItem shows cached data');
+            ok(tabItem.isShowingCachedData(), 'tabItem shows cached data');
+            testChangeUrlAfterReconnect();
+          });
 
-          testChangeUrlAfterReconnect();
+          cw.TabItems.resumeReconnecting();
         });
 
-        cw.TabItems.resumeReconnecting();
+        cw.Storage.saveTab(tab, data);
       });
     });
   }
 
   let testChangeUrlAfterReconnect = function () {
     tab.linkedBrowser.loadURI('http://mochi.test:8888/browser/');
 
     whenTabAttrModified(tab, function () {
@@ -74,20 +76,17 @@ function test() {
     cw = TabView.getContentWindow();
     testReconnectWithSameUrl();
   });
 }
 
 // ----------
 function whenTabAttrModified(tab, callback) {
   let onModified = function (event) {
-    if (tab === event.target) {
-      container.removeEventListener('TabAttrModified', onModified, false);
-      // we need executeSoon here because the tabItem also listens for the
-      // onTabAttrModified event. so this is to make sure the tabItem logic
-      // is executed before the test logic.
-      executeSoon(callback);
-    }
+    tab.removeEventListener(event.type, onModified, false);
+    // we need executeSoon here because the tabItem also listens for the
+    // TabAttrModified event. so this is to make sure the tabItem logic
+    // is executed before the test logic.
+    executeSoon(callback);
   }
 
-  let container = gBrowser.tabContainer;
-  container.addEventListener('TabAttrModified', onModified, false);
+  tab.addEventListener("TabAttrModified", onModified, false);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug627736.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627736.js
@@ -20,30 +20,35 @@ function onTabViewWindowLoaded(win) {
       immediately: true,
       bounds: {left: 20, top: 20, width: 400, height: 400}
     });
     contentWindow.UI.setActive(group);
     win.gBrowser.loadOneTab('about:blank', {inBackground: true});
   
     is(group.getChildren().length, 1, "The group has one child now.");
     let tab = group.getChild(0);
-  
+
+    function finalize() {
+      is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
+        "The original group is active.");
+      is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
+        "The original tab is active");
+
+      callback();
+    }
+
     function check() {
       if (groupOrTab == 'group') {
         group.removeSubscriber(group, "groupHidden", check);
         group.closeHidden();
-      } else
+        finalize();
+      } else {
         tab.removeSubscriber(tab, "tabRemoved", check);
-  
-      is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
-        "The original group is active.");
-      is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
-        "The original tab is active");
-  
-      callback();
+        closeGroupItem(group, finalize);
+      }
     }
   
     if (groupOrTab == 'group') {
       group.addSubscriber(group, "groupHidden", check);
       group.closeAll();
     } else {
       tab.addSubscriber(tab, "tabRemoved", check);
       tab.close();
@@ -53,9 +58,9 @@ function onTabViewWindowLoaded(win) {
   // PHASE 1: create a group with a tab and close the group.
   openAndClose("group", function postPhase1() {
     // PHASE 2: create a group with a tab and close the tab.
     openAndClose("tab", function postPhase2() {
       win.close();
       finish();
     });
   });
-}
\ No newline at end of file
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug628270.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug628270.js
@@ -20,30 +20,16 @@ function test() {
         groupItem.close();
     });
   }
 
   let getGroupItem = function (index) {
     return cw.GroupItems.groupItems[index];
   }
 
-  let restoreTab = function (callback) {
-    let tab = undoCloseTab(0);
-
-    if (tab._tabViewTabItem._reconnected) {
-      callback();
-      return;
-    }
-
-    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
-      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
-      afterAllTabsLoaded(callback);
-    });
-  }
-
   let activateFirstGroupItem = function () {
     let activeTabItem = getGroupItem(0).getChild(0);
     cw.GroupItems.updateActiveGroupItemAndTabBar(activeTabItem);
   }
 
   let assertTabViewIsHidden = function () {
     ok(!TabView.isVisible(), prefix + ': tabview is hidden');
   }
@@ -86,19 +72,17 @@ function test() {
 
     gBrowser.removeTab(tabItem.tab);
     assertNumberOfTabsInGroup(groupItem, 1);
 
     restoreTab(function () {
       assertNumberOfTabsInGroup(groupItem, 2);
 
       activateFirstGroupItem();
-      gBrowser.removeTab(gBrowser.tabs[1]);
-      gBrowser.removeTab(gBrowser.tabs[1]);
-      finishTest();
+      closeGroupItem(groupItem, finishTest);
     });
   }
 
   waitForExplicitFinish();
   assertTabViewIsHidden();
   registerCleanupFunction(function () TabView.hide());
 
   showTabView(function () {
--- a/browser/base/content/test/tabview/browser_tabview_bug630157.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug630157.js
@@ -30,17 +30,16 @@ function test() {
     for (let i=0; i<2; i++)
       EventUtils.synthesizeMouseAtCenter(target, {button: button || 0}, cw);
   }
 
   let finishTest = function () {
     let tabItem = gBrowser.tabs[0]._tabViewTabItem;
     cw.GroupItems.updateActiveGroupItemAndTabBar(tabItem);
 
-    gBrowser.removeTab(gBrowser.tabs[1]);
     assertNumberOfGroups(1);
     assertNumberOfTabs(1);
 
     finish();
   }
 
   let testDoubleClick = function () {
     let groupItem = createGroupItem();
@@ -64,19 +63,20 @@ function test() {
 
     // simulate double click with right mouse button
     simulateDoubleClick(container, 2);
     assertNumberOfTabs(1);
 
     // simulate double click with left mouse button
     let container = groupItem.container;
     simulateDoubleClick(container);
-    assertNumberOfTabs(2);
+    assertNumberOfTabs(1);
 
-    whenTabViewIsHidden(finishTest);
+    groupItem.close();
+    hideTabView(finishTest);
   }
 
   waitForExplicitFinish();
   registerCleanupFunction(function () TabView.hide());
 
   showTabView(function () {
     cw = TabView.getContentWindow();
     testDoubleClick();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug633190.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let origTab = gBrowser.visibleTabs[0];
+let contentWindow;
+
+function test() {
+  waitForExplicitFinish();
+
+  test1();
+}
+
+// Open a new tab when the active tab item belongs to a group item.
+function test1() {
+  registerCleanupFunction(function () TabView.hide());
+
+  showTabView(function() {
+    ok(origTab._tabViewTabItem.parent, "The original tab belongs to a group");
+
+    contentWindow = TabView.getContentWindow();
+    contentWindow.UI.setActive(origTab._tabViewTabItem);
+
+    testCreateTabAndThen(test2);
+  });
+}
+
+// Open a new tab when the active tab item is nothing.
+function test2() {
+  showTabView(function() {
+    contentWindow.UI.setActive(null, { onlyRemoveActiveTab: true });
+
+    testCreateTabAndThen(test3);
+  });
+}
+
+// Open a new tab when the active tab item is an orphan tab.
+function test3() {
+  showTabView(function() {
+    let groupItem = origTab._tabViewTabItem.parent;
+    let tabItems = groupItem.getChildren();
+    is(tabItems.length, 3, "There are 3 tab items in the group");
+
+    let lastTabItem = tabItems[tabItems.length - 1];
+    groupItem.remove(lastTabItem);
+
+    let orphanedTabs = contentWindow.GroupItems.getOrphanedTabs();
+    is(orphanedTabs.length, 1, "There should be 1 orphan tab");
+    is(orphanedTabs[0], lastTabItem, "The tab item is the same as the orphan tab");
+
+    contentWindow.UI.setActive(lastTabItem);
+
+    testCreateTabAndThen(function() {
+      hideTabView(finish);
+    });
+  });
+}
+
+function testCreateTabAndThen(callback) {
+  ok(TabView.isVisible(), "Tab View is visible");
+
+  // detect tab open and zoomed in event.
+  let onTabOpen = function(event) {
+    gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, false);
+
+    // ensure that the default tabview listener is called before so the 
+    // tab._tabViewTabItem exists
+    executeSoon(function() {
+      let tab = event.target;
+      tabItem = tab._tabViewTabItem;
+      ok(tabItem, "Tab item is available after tab open");
+
+      registerCleanupFunction(function () gBrowser.removeTab(tab))
+
+      tabItem.addSubscriber(tabItem, "zoomedIn", function() {
+        tabItem.removeSubscriber(tabItem, "zoomedIn");
+
+        is(gBrowser.selectedTab, tab,
+          "The selected tab is the same as the newly opened tab");
+        executeSoon(callback);
+      });
+    });
+  }
+  gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, false);
+  // use the menu item (the same as pressing cmd/ctrl + t)
+  document.getElementById("menu_newNavigatorTab").doCommand();
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug662266.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (win) {
+    registerCleanupFunction(function () win.close());
+
+    for (let i = 0; i < 4; i++)
+      win.gBrowser.loadOneTab("about:blank", {inBackground: true});
+
+    let cw = win.TabView.getContentWindow();
+    let groupItem = cw.GroupItems.groupItems[0];
+    let children = groupItem.getChildren();
+
+    groupItem.setSize(200, 200, true);
+    ok(groupItem.isStacked(), "groupItem is now stacked");
+    is(win.gBrowser.tabs.length, 5, "we have five tabs");
+
+    groupItem.addSubscriber(groupItem, "expanded", function onExpanded() {
+      groupItem.removeSubscriber(groupItem, "expanded");
+
+      ok(groupItem.expanded, "groupItem is expanded");
+      let bounds = children[1].getBounds();
+
+      // remove two tabs and see if the remaining tabs are re-arranged to fill
+      // the resulting gaps
+      for (let i = 0; i < 2; i++) {
+        children[1].close();
+        ok(bounds.equals(children[1].getBounds()), "tabItems were re-arranged");
+      }
+
+      waitForFocus(finish);
+    });
+
+    groupItem.expand();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug665502.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  let onLoad = function (win) {
+    for (let i = 0; i < 2; i++)
+      win.gBrowser.addTab();
+  };
+
+  let onShow = function (win) {
+    registerCleanupFunction(function () win.close());
+
+    let cw = win.TabView.getContentWindow();
+    let groupItem = cw.GroupItems.groupItems[0];
+
+    groupItem.setSize(400, 200, true);
+
+    let tabItem = groupItem.getChild(0);
+    let bounds = tabItem.getBounds();
+
+    is(groupItem.getActiveTab(), tabItem, "the first tab is active");
+    tabItem.close();
+
+    is(groupItem.getChildren().indexOf(tabItem), -1, "tabItem got removed");
+    ok(bounds.equals(groupItem.getChild(0).getBounds()), "tabItem bounds didn't change");
+
+    finish();
+  };
+
+  newWindowWithTabView(onShow, onLoad);
+}
--- a/browser/base/content/test/tabview/browser_tabview_dragdrop.js
+++ b/browser/base/content/test/tabview/browser_tabview_dragdrop.js
@@ -80,17 +80,17 @@ function addTest(contentWindow, groupOne
       groupTwo.closeAll();
       // close undo group
       let closeButton = groupTwo.$undoContainer.find(".close");
       EventUtils.sendMouseEvent(
         { type: "click" }, closeButton[0], contentWindow);
     };
     groupTwo.addSubscriber(groupTwo, "close", function() {
       groupTwo.removeSubscriber(groupTwo, "close");
-      finish();  
+      closeGroupItem(groupOne, finish);
     });
     window.addEventListener("tabviewhidden", onTabViewHidden, false);
     gBrowser.selectedTab = originalTab;
   }
   groupTwo.addSubscriber(groupTwo, "childAdded", endGame);
   
   simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
 }
--- a/browser/base/content/test/tabview/browser_tabview_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_group.js
@@ -90,17 +90,17 @@ function testGroupItemWithTabItem(conten
 
       // Now there should only be one tab left, so we need to hide TabView
       // and go into that tab.
       is(gBrowser.tabs.length, 1, "There is only one tab left");
             
       let endGame = function() {
         window.removeEventListener("tabviewhidden", endGame, false);
         ok(!TabView.isVisible(), "Tab View is hidden");
-        finish();
+        closeGroupItem(groupItem, finish);
       };
       window.addEventListener("tabviewhidden", endGame, false);
 
       // after the last selected tabitem is closed, there would be not active
       // tabitem on the UI so we set the active tabitem before toggling the 
       // visibility of tabview
       let tabItems = contentWindow.TabItems.getItems();
       ok(tabItems[0], "A tab item exists");
--- a/browser/base/content/test/tabview/browser_tabview_privatebrowsing.js
+++ b/browser/base/content/test/tabview/browser_tabview_privatebrowsing.js
@@ -17,71 +17,78 @@ function test() {
   showTabView(onTabViewLoadedAndShown);
 }
 
 // -----------
 function onTabViewLoadedAndShown() {
   ok(TabView.isVisible(), "Tab View is visible");
 
   // Establish initial state
-  contentWindow = document.getElementById("tab-view").contentWindow;  
+  contentWindow = document.getElementById("tab-view").contentWindow;
   verifyCleanState("start");
-  
+
   // register a clean up for private browsing just in case
   registerCleanupFunction(function() {
     pb.privateBrowsingEnabled = false;
   });
-  
+
   // create a group
   let box = new contentWindow.Rect(20, 20, 180, 180);
   let groupItem = new contentWindow.GroupItem([], {bounds: box, title: "test1"});
-  let id = groupItem.id; 
+  let id = groupItem.id;
   is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
   registerCleanupFunction(function() {
     contentWindow.GroupItems.groupItem(id).close();
   });
-  
+
   // make it the active group so new tabs will be added to it
   contentWindow.UI.setActive(groupItem);
-  
+
   // collect the group titles
   let count = contentWindow.GroupItems.groupItems.length;
   for (let a = 0; a < count; a++) {
     let gi = contentWindow.GroupItems.groupItems[a];
     groupTitles[a] = gi.getTitle();
   }
-  
+
   // Create a second tab
-  gBrowser.addTab("about:robots");
+  gBrowser.loadOneTab("about:robots", { inBackground: false });
   is(gBrowser.tabs.length, 2, "we now have 2 tabs");
   registerCleanupFunction(function() {
     gBrowser.removeTab(gBrowser.tabs[1]);
   });
 
   afterAllTabsLoaded(function() {
-    // Get normal tab urls
-    for (let a = 0; a < gBrowser.tabs.length; a++)
-      normalURLs.push(gBrowser.tabs[a].linkedBrowser.currentURI.spec);
+    showTabView(function() {
+      // Get normal tab urls
+      for (let a = 0; a < gBrowser.tabs.length; a++)
+        normalURLs.push(gBrowser.tabs[a].linkedBrowser.currentURI.spec);
 
-    // verify that we're all set up for our test
-    verifyNormal();
+      // verify that we're all set up for our test
+      verifyNormal();
+
+      // go into private browsing and make sure Tab View becomes hidden
+      togglePBAndThen(function() {
+        whenTabViewIsHidden(function() {
+          ok(!TabView.isVisible(), "Tab View is no longer visible");
 
-    // go into private browsing and make sure Tab View becomes hidden
-    togglePBAndThen(function() {
-      ok(!TabView.isVisible(), "Tab View is no longer visible");
-      verifyPB();
-      
-      // exit private browsing and make sure Tab View is shown again
-      togglePBAndThen(function() {
-        ok(TabView.isVisible(), "Tab View is visible again");
-        verifyNormal();
+          verifyPB();
 
-        hideTabView(onTabViewHidden);
+          // exit private browsing and make sure Tab View is shown again
+          togglePBAndThen(function() {
+            whenTabViewIsShown(function() {
+              ok(TabView.isVisible(), "Tab View is visible again");
+              verifyNormal();
+
+              hideTabView(onTabViewHidden);
+            });
+          });
+        });
       });
-    });
+    }); 
   });
 }
 
 // -----------
 function onTabViewHidden() {
   ok(!TabView.isVisible(), "Tab View is not visible");
   
   // go into private browsing and make sure Tab View remains hidden
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -40,24 +40,29 @@ function createGroupItemWithBlankTabs(wi
   let urls = [];
   while(numNewTabs--)
     urls.push("about:blank");
   return createGroupItemWithTabs(win, width, height, padding, urls, animate);
 }
 
 // ----------
 function closeGroupItem(groupItem, callback) {
-  groupItem.addSubscriber(groupItem, "groupHidden", function() {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
-    groupItem.addSubscriber(groupItem, "close", function() {
-      groupItem.removeSubscriber(groupItem, "close");
-      callback();
+  groupItem.addSubscriber(groupItem, "close", function () {
+    groupItem.removeSubscriber(groupItem, "close");
+    if ("function" == typeof callback)
+      executeSoon(callback);
+  });
+
+  if (groupItem.getChildren().length) {
+    groupItem.addSubscriber(groupItem, "groupHidden", function () {
+      groupItem.removeSubscriber(groupItem, "groupHidden");
+      groupItem.closeHidden();
     });
-    groupItem.closeHidden();
-  });
+  }
+
   groupItem.closeAll();
 }
 
 // ----------
 function afterAllTabItemsUpdated(callback, win) {
   win = win || window;
   let tabItems = win.document.getElementById("tab-view").contentWindow.TabItems;
 
@@ -284,38 +289,65 @@ function whenWindowLoaded(win, callback)
 function whenWindowStateReady(win, callback) {
   win.addEventListener("SSWindowStateReady", function onReady() {
     win.removeEventListener("SSWindowStateReady", onReady, false);
     executeSoon(callback);
   }, false);
 }
 
 // ----------
+function whenDelayedStartupFinished(win, callback) {
+  let topic = "browser-delayed-startup-finished";
+  Services.obs.addObserver(function onStartup(aSubject) {
+    if (win != aSubject)
+      return;
+
+    Services.obs.removeObserver(onStartup, topic, false);
+    executeSoon(callback);
+  }, topic, false);
+}
+
+// ----------
 function newWindowWithState(state, callback) {
+  const ss = Cc["@mozilla.org/browser/sessionstore;1"]
+             .getService(Ci.nsISessionStore);
+
   let opts = "chrome,all,dialog=no,height=800,width=800";
   let win = window.openDialog(getBrowserURL(), "_blank", opts);
 
   whenWindowLoaded(win, function () {
+    whenWindowStateReady(win, function () {
+      afterAllTabsLoaded(check, win);
+    });
+
     ss.setWindowState(win, JSON.stringify(state), true);
+    whenDelayedStartupFinished(win, check);
   });
 
-  whenWindowStateReady(win, function () {
-    afterAllTabsLoaded(function () callback(win), win);
-  });
+
+  let numConditions = 2;
+  let check = function () {
+    if (!--numConditions)
+      callback(win);
+  };
 }
 
 // ----------
 function restoreTab(callback, index, win) {
   win = win || window;
 
   let tab = win.undoCloseTab(index || 0);
   let tabItem = tab._tabViewTabItem;
 
+  let finalize = function () {
+    afterAllTabsLoaded(function () callback(tab), win);
+  };
+
   if (tabItem._reconnected) {
-    afterAllTabsLoaded(callback, win);
+    finalize();
     return;
   }
 
   tab._tabViewTabItem.addSubscriber(tab, "reconnected", function onReconnected() {
     tab._tabViewTabItem.removeSubscriber(tab, "reconnected");
-    afterAllTabsLoaded(callback, win);
+    finalize();
   });
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -86,16 +86,17 @@
                                 .QueryInterface(Components.interfaces.nsIPrefBranch2);
 
         this._prefs.addObserver("", this, false);
         this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
         this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
         this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
         this.timeout = this._prefs.getIntPref("delay");
         this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
+        this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
 
         this._urlTooltip = document.getElementById("urlTooltip");
 
         this.inputField.controllers.insertControllerAt(0, this._copyCutController);
         this.inputField.addEventListener("mousedown", this, false);
         this.inputField.addEventListener("mousemove", this, false);
         this.inputField.addEventListener("mouseout", this, false);
         this.inputField.addEventListener("overflow", this, false);
@@ -175,49 +176,65 @@
             this.setAttribute("actiontype", action.type);
           } else {
             this.removeAttribute("actiontype");
           }
           return returnValue;
         ]]></body>
       </method>
 
+      <field name="_mayTrimURLs">true</field>
+      <method name="trimValue">
+        <parameter name="aURL"/>
+        <body><![CDATA[
+          return this._mayTrimURLs ? trimURL(aURL) : aURL;
+        ]]></body>
+      </method>
+
       <field name="_formattingEnabled">true</field>
       <method name="formatValue">
         <body><![CDATA[
           if (!this._formattingEnabled || this.focused)
             return;
 
           let controller = this.editor.selectionController;
           let selection = controller.getSelection(controller.SELECTION_URLSECONDARY);
           selection.removeAllRanges();
 
           let textNode = this.editor.rootElement.firstChild;
           let value = textNode.textContent;
-          let matchedURL = value.match(/^((?:http|https|ftp):\/\/(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
+
+          let protocol = value.match(/^[a-z\d.+\-]+:/);
+          if (protocol &&
+              ["http:", "https:", "ftp:"].indexOf(protocol[0]) == -1)
+            return;
+          let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
           if (!matchedURL)
             return;
 
           let [, preDomain, domain] = matchedURL;
           let baseDomain = domain;
           try {
             baseDomain = Services.eTLD.getBaseDomainFromHost(domain);
           } catch (e) {}
           let segments = function (s) s.replace(/[^.]*/g, "").length + 1;
           let subSegments = segments(domain) - segments(baseDomain);
           let subDomain = domain.match(new RegExp("(?:[^.]*\.){" + subSegments + "}"))[0];
 
-          let range = document.createRange();
-          range.setStart(textNode, 0);
-          range.setEnd(textNode, preDomain.length + subDomain.length);
-          selection.addRange(range);
+          let rangeLength = preDomain.length + subDomain.length;
+          if (rangeLength) {
+            let range = document.createRange();
+            range.setStart(textNode, 0);
+            range.setEnd(textNode, rangeLength);
+            selection.addRange(range);
+          }
 
           let startRest = preDomain.length + domain.length;
           if (startRest < value.length) {
-            range = document.createRange();
+            let range = document.createRange();
             range.setStart(textNode, startRest);
             range.setEnd(textNode, value.length);
             selection.addRange(range);
           }
         ]]></body>
       </method>
 
       <method name="_clearFormatting">
@@ -462,17 +479,17 @@
           // The URL bar automatically handles inputs with newline characters,
           // so we can get away with treating text/x-moz-url flavours as text/plain.
           if (url) {
             aEvent.preventDefault();
             this.value = url;
             SetPageProxyState("invalid");
             this.focus();
             try {
-              urlSecurityCheck(this.value,
+              urlSecurityCheck(url,
                                gBrowser.contentPrincipal,
                                Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
             } catch (ex) {
               return;
             }
             this.handleCommand();
           }
         ]]></body>
@@ -483,20 +500,17 @@
           // Grab the actual input field's value, not our value, which could include moz-action:
           var inputVal = this.inputField.value;
           var val = inputVal.substring(this.selectionStart, this.selectionEnd);
 
           // If the entire value is selected and it's a valid non-javascript,
           // non-data URI, encode it.
           if (val == inputVal &&
               this.getAttribute("pageproxystate") == "valid") {
-            let uri;
-            try {
-              uri = makeURI(val);
-            } catch (e) {}
+            let uri = gBrowser.currentURI;
 
             if (uri && !uri.schemeIs("javascript") && !uri.schemeIs("data")) {
               val = uri.spec;
 
               // Parentheses are known to confuse third-party applications (bug 458565).
               val = val.replace(/[()]/g, function (c) escape(c));
             }
           }
@@ -560,16 +574,19 @@
                 this.completeDefaultIndex = this._prefs.getBoolPref(aData);
                 break;
               case "delay":
                 this.timeout = this._prefs.getIntPref(aData);
                 break;
               case "formatting.enabled":
                 this._formattingEnabled = this._prefs.getBoolPref(aData);
                 break;
+              case "trimURLs":
+                this._mayTrimURLs = this._prefs.getBoolPref(aData);
+                break;
             }
           }
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
@@ -1283,19 +1300,19 @@
   </binding>
 
  <binding id="promobox">
     <content>
       <xul:hbox class="panel-promo-box" align="start" flex="1">
         <xul:hbox align="center" flex="1">
           <xul:image class="panel-promo-icon"/>
           <xul:description anonid="promo-message" class="panel-promo-message" flex="1">
-            placeholder <xul:description anonid="promo-link"
-                                         class="plain text-link inline-link"
-                                         onclick="document.getBindingParent(this).onLinkClick();"/>
+            <xul:description anonid="promo-link"
+                             class="plain text-link inline-link"
+                             onclick="document.getBindingParent(this).onLinkClick();"/>
           </xul:description>
         </xul:hbox>
         <xul:toolbarbutton class="panel-promo-closebutton"
                            oncommand="document.getBindingParent(this).onCloseButtonCommand();"
                            tooltiptext="&closeNotification.tooltip;"/>
       </xul:hbox>
     </content>
 
@@ -1347,17 +1364,17 @@
           if (type == "editBookmarkPanel")
             return "bookmarks";
           return null;
         ]]></getter>
       </property>
       <property name="_notificationMessage">
         <getter><![CDATA[
           return gNavigatorBundle.getFormattedString(
-            "syncPromoNotification." + this._notificationType + ".label",
+            "syncPromoNotification." + this._notificationType + ".description",
             [this._brandBundle.GetStringFromName("syncBrandShortName")]
           );
         ]]></getter>
       </property>
       <method name="onCloseButtonCommand">
         <body><![CDATA[
           this._viewsLeft = 0;
           this.hidden = true;
@@ -1402,21 +1419,24 @@
 
             this._promolink.setAttribute("href", "https://services.mozilla.com/sync/");
             this._promolink.value = gNavigatorBundle.getString("syncPromoNotification.learnMoreLinkText");
 
             this.hidden = false;
 
             // HACK: The description element doesn't wrap correctly in panels,
             // thus set a width on it, based on the available space, before
-            // setting its textContent.
+            // setting its textContent.  Then set its height as well, to
+            // fix wrong height calculation on Linux (bug 659578).
+            let self = this;
             this._panel.addEventListener("popupshown", function (evt) {
-              this._panel.removeEventListener("popupshown", arguments.callee, true);
-              this._promomessage.width = this._promomessage.getBoundingClientRect().width;
-              this._promomessage.firstChild.textContent = this._notificationMessage;
-            }.bind(this), true);
+              self._panel.removeEventListener("popupshown", arguments.callee, true);
+              self._promomessage.width = self._promomessage.getBoundingClientRect().width;
+              self._promomessage.firstChild.textContent = self._notificationMessage;
+              self._promomessage.height = self._promomessage.getBoundingClientRect().height;
+            }, true);
           }
         ]]></body>
       </method>
     </implementation>
   </binding>
 
 </bindings>
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -18,16 +18,17 @@
 # Netscape Communications Corporation.
 # Portions created by the Initial Developer are Copyright (C) 1998
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Alec Flett <alecf@netscape.com>
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
 #   Gavin Sharp <gavin@gavinsharp.com>
+#   Dão Gottwald <dao@design-noir.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
@@ -612,8 +613,15 @@ function openHelpLink(aHelpTopic, aCalle
 function openPrefsHelp() {
   // non-instant apply prefwindows are usually modal, so we can't open in the topmost window, 
   // since its probably behind the window.
   var instantApply = getBoolPref("browser.preferences.instantApply");
 
   var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
   openHelpLink(helpTopic, !instantApply);
 }
+
+function trimURL(aURL) {
+  return aURL /* remove single trailing slash for http/https/ftp URLs */
+             .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1")
+              /* remove http:// unless the host starts with "ftp." or contains "@" */
+             .replace(/^http:\/\/((?!ftp\.)[^\/@]+(?:\/|$))/, "$1");
+}
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -16,16 +16,18 @@ browser.jar:
 *       content/browser/aboutDialog.js                (content/aboutDialog.js)
 *       content/browser/aboutDialog.css               (content/aboutDialog.css)
 *       content/browser/aboutRobots.xhtml             (content/aboutRobots.xhtml)
 *       content/browser/aboutHome.xhtml               (content/aboutHome.xhtml)
 *       content/browser/aboutHome.js                  (content/aboutHome.js)
 *       content/browser/aboutHome.css                 (content/aboutHome.css)
         content/browser/aboutHome-restore-icon.png    (content/aboutHome-restore-icon.png)
         content/browser/aboutHome-restore-icon-small.png    (content/aboutHome-restore-icon-small.png)
+        content/browser/aboutHome-snippet1.png        (content/aboutHome-snippet1.png)
+        content/browser/aboutHome-snippet2.png        (content/aboutHome-snippet2.png)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
 *       content/browser/browser.css                   (content/browser.css)
 *       content/browser/browser.js                    (content/browser.js)
 *       content/browser/browser.xul                   (content/browser.xul)
 *       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
 *       content/browser/fullscreen-video.xhtml        (content/fullscreen-video.xhtml)
         content/browser/highlighter.xhtml             (content/highlighter.xhtml)
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -57,17 +57,16 @@ const nsIInterfaceRequestor  = Component
 const nsINetUtil             = Components.interfaces.nsINetUtil;
 const nsIPrefBranch          = Components.interfaces.nsIPrefBranch;
 const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
 const nsISupportsString      = Components.interfaces.nsISupportsString;
 const nsIURIFixup            = Components.interfaces.nsIURIFixup;
 const nsIWebNavigation       = Components.interfaces.nsIWebNavigation;
 const nsIWindowMediator      = Components.interfaces.nsIWindowMediator;
 const nsIWindowWatcher       = Components.interfaces.nsIWindowWatcher;
-const nsICategoryManager     = Components.interfaces.nsICategoryManager;
 const nsIWebNavigationInfo   = Components.interfaces.nsIWebNavigationInfo;
 const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
 const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
 const nsIXULAppInfo          = Components.interfaces.nsIXULAppInfo;
 
 const NS_BINDING_ABORTED = Components.results.NS_BINDING_ABORTED;
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
 const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
@@ -735,18 +734,16 @@ nsBrowserContentHandler.prototype = {
       if (cmdLine.length != urlFlagIdx + 2 || /firefoxurl:/.test(urlParam))
         throw NS_ERROR_ABORT;
       cmdLine.handleFlag("osint", false)
     }
   },
 };
 var gBrowserContentHandler = new nsBrowserContentHandler();
 
-const CONTRACTID_PREFIX = "@mozilla.org/uriloader/content-handler;1?type=";
-
 function handURIToExistingBrowser(uri, location, cmdLine)
 {
   if (!shouldLoadURI(uri))
     return;
 
   var navWin = getMostRecentBrowserWindow();
   if (!navWin) {
     // if we couldn't load it in an existing window, open a new one
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -345,29 +345,16 @@ BrowserGlue.prototype = {
 
     // apply distribution customizations
     // prefs are applied in _onAppDefaults()
     this._distributionCustomizer.applyCustomizations();
 
     // handle any UI migration
     this._migrateUI();
 
-    // if ioService is managing the offline status, then ioservice.offline
-    // is already set correctly. We will continue to allow the ioService
-    // to manage its offline state until the user uses the "Work Offline" UI.
-    if (!Services.io.manageOfflineStatus) {
-      // set the initial state
-      try {
-        Services.io.offline = Services.prefs.getBoolPref("browser.offline");
-      }
-      catch (e) {
-        Services.io.offline = false;
-      }
-    }
-
     Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
   },
 
   // the first browser window has finished initializing
   _onFirstWindowLoaded: function BG__onFirstWindowLoaded() {
 #ifdef XP_WIN
     // For windows seven, initialize the jump list module.
     const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -397,19 +397,19 @@ PlacesViewBase.prototype = {
    *        The livemark container popup
    */
   _ensureLivemarkStatusMenuItem:
   function PVB_ensureLivemarkStatusMenuItem(aPopup) {
     let itemId = aPopup._placesNode.itemId;
     let as = PlacesUtils.annotations;
 
     let lmStatus = null;
-    if (as.itemHasAnnotation(itemId, "livemark/loadfailed"))
+    if (as.itemHasAnnotation(itemId, PlacesUtils.LMANNO_LOADFAILED))
       lmStatus = "bookmarksLivemarkFailed";
-    else if (as.itemHasAnnotation(itemId, "livemark/loading"))
+    else if (as.itemHasAnnotation(itemId, PlacesUtils.LMANNO_LOADING))
       lmStatus = "bookmarksLivemarkLoading";
 
     let lmStatusElt = aPopup._lmStatusMenuItem;
     if (lmStatus && !lmStatusElt) {
       // Create the status menuitem and cache it in the popup object.
       lmStatusElt = document.createElement("menuitem");
       lmStatusElt.setAttribute("lmStatus", lmStatus);
       lmStatusElt.setAttribute("label", PlacesUIUtils.getString(lmStatus));
@@ -461,27 +461,31 @@ PlacesViewBase.prototype = {
     if (!icon)
       elt.removeAttribute("image");
     else if (icon != elt.getAttribute("image"))
       elt.setAttribute("image", icon);
   },
 
   nodeAnnotationChanged:
   function PVB_nodeAnnotationChanged(aPlacesNode, aAnno) {
-    // All livemarks have a feedURI, so use it as our indicator.
+    let elt = aPlacesNode._DOMElement;
+    if (!elt)
+      throw "aPlacesNode must have _DOMElement set";
+
+    // All livemarks have a feedURI, so use it as our indicator of a livemark
+    // being modified.
     if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
-      let elt = aPlacesNode._DOMElement;
-      if (!elt)
-        throw "aPlacesNode must have _DOMElement set";
-
       let menu = elt.parentNode;
       if (!menu.hasAttribute("livemark"))
         menu.setAttribute("livemark", "true");
+    }
 
-      // Add or remove the livemark status menuitem.
+    if ([PlacesUtils.LMANNO_LOADING,
+         PlacesUtils.LMANNO_LOADFAILED].indexOf(aAnno) != -1) {
+      // Loading status changed, update the livemark status menuitem.
       this._ensureLivemarkStatusMenuItem(elt);
     }
   },
 
   nodeTitleChanged:
   function PVB_nodeTitleChanged(aPlacesNode, aNewTitle) {
     let elt = aPlacesNode._DOMElement;
     if (!elt)
@@ -1164,20 +1168,27 @@ PlacesToolbar.prototype = {
 
     if (elt.parentNode == this._rootElt) {
       // Node is on the toolbar.
 
       // All livemarks have a feedURI, so use it as our indicator.
       if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
         elt.setAttribute("livemark", true);
       }
-      return;
+
+      if ([PlacesUtils.LMANNO_LOADING,
+           PlacesUtils.LMANNO_LOADFAILED].indexOf(aAnno) != -1) {
+        // Loading status changed, update the livemark status menuitem.
+        this._ensureLivemarkStatusMenuItem(elt.firstChild);
+      }
     }
-
-    PlacesViewBase.prototype.nodeAnnotationChanged.apply(this, arguments);
+    else {
+      // Node is in a submenu.
+      PlacesViewBase.prototype.nodeAnnotationChanged.apply(this, arguments);
+    }
   },
 
   nodeTitleChanged: function PT_nodeTitleChanged(aPlacesNode, aNewTitle) {
     let elt = aPlacesNode._DOMElement;
     if (!elt)
       throw "aPlacesNode must have _DOMElement set";
 
     // There's no UI representation for the root node, thus there's
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -613,20 +613,22 @@ var gEditItemOverlay = {
   onSiteLocationFieldBlur: function EIO_onSiteLocationFieldBlur() {
     var uri = null;
     try {
       uri = PlacesUIUtils.createFixedURI(this._element("siteLocationField").value);
     }
     catch(ex) {  }
 
     var currentSiteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
-    if (!uri || !currentSiteURI.equals(uri)) {
-      var txn = PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId, uri);
-      PlacesUIUtils.ptm.doTransaction(txn);
+    if ((!uri && !currentSiteURI) ||
+        (uri && currentSiteURI && currentSiteURI.equals(uri))) {
+      return;
     }
+    var txn = PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId, uri);
+    PlacesUIUtils.ptm.doTransaction(txn);
   },
 
   onLoadInSidebarCheckboxCommand:
   function EIO_onLoadInSidebarCheckboxCommand() {
     var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
     var txn = PlacesUIUtils.ptm.setLoadInSidebar(this._itemId,
                                                  loadInSidebarChecked);
     PlacesUIUtils.ptm.doTransaction(txn);
--- a/browser/components/places/tests/Makefile.in
+++ b/browser/components/places/tests/Makefile.in
@@ -43,11 +43,11 @@ VPATH		= @srcdir@
 relativesrcdir = browser/components/places/tests
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= test_browser_places
 
 XPCSHELL_TESTS = unit
 
-DIRS = browser chrome perf
+DIRS = browser chrome
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js
+++ b/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js
@@ -39,27 +39,17 @@
 /**
  *  Test we correctly migrate Library left pane to the latest version.
  *  Note: this test MUST be the first between browser chrome tests, or results
  *        of next tests could be unexpected due to PlacesUIUtils getters.
  */
 
 const TEST_URI = "http://www.mozilla.org/";
 
-var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher);
-
-function windowObserver(aSubject, aTopic, aData) {
-  if (aTopic != "domwindowopened")
-    return;
-  ww.unregisterNotification(windowObserver);
-  var organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
-  organizer.addEventListener("load", function onLoad(event) {
-    organizer.removeEventListener("load", onLoad, false);
-    executeSoon(function () {
+function onLibraryReady(organizer) {
       // Check left pane.
       ok(PlacesUIUtils.leftPaneFolderId > 0,
          "Left pane folder correctly created");
       var leftPaneItems =
         PlacesUtils.annotations
                    .getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
       is(leftPaneItems.length, 1,
          "We correctly have only 1 left pane folder");
@@ -78,18 +68,16 @@ function windowObserver(aSubject, aTopic
       is(organizer.PlacesOrganizer._places.selectedNode.itemId,
          PlacesUIUtils.leftPaneQueries["History"],
          "Library left pane is populated and working");
 
       // Close Library window.
       organizer.close();
       // No need to cleanup anything, we have a correct left pane now.
       finish();
-    });
-  }, false);
 }
 
 function test() {
   waitForExplicitFinish();
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils is running in chrome context");
   ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
   ok(PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION > 0,
@@ -128,15 +116,10 @@ function test() {
   is(leftPaneItems[0], fakeLeftPaneRoot, "left pane root itemId is correct");
 
   // Check version.
   var version = PlacesUtils.annotations.getItemAnnotation(fakeLeftPaneRoot,
                                                           PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
   is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION - 1, "Left pane version correctly set");
 
   // Open Library, this will upgrade our left pane version.
-  ww.registerNotification(windowObserver);
-  ww.openWindow(null,
-                "chrome://browser/content/places/places.xul",
-                "",
-                "chrome,toolbar=yes,dialog=no,resizable",
-                null);
+  openLibrary(onLibraryReady);
 }
--- a/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
+++ b/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
@@ -19,22 +19,22 @@ Components.utils.import("resource://gre/
 const TEST_URL = "http://example.com/";
 const MOZURISPEC = "http://mozilla.com/";
 
 let gLibrary;
 let PlacesOrganizer;
 
 function test() {
   waitForExplicitFinish();
-  gLibrary = window.openDialog("chrome://browser/content/places/places.xul",
-                               "", "chrome,toolbar=yes,dialog=no,resizable");
-  waitForFocus(onLibraryReady, gLibrary);
+  openLibrary(onLibraryReady);
 }
 
-function onLibraryReady() {
+function onLibraryReady(library) {
+  gLibrary = library;
+
   ok(PlacesUtils, "PlacesUtils in scope");
   ok(PlacesUIUtils, "PlacesUIUtils in scope");
 
   PlacesOrganizer = gLibrary.PlacesOrganizer;
   ok(PlacesOrganizer, "Places organizer in scope");
 
   tests.makeHistVisit();
   tests.makeTag();
--- a/browser/components/places/tests/browser/browser_forgetthissite_single.js
+++ b/browser/components/places/tests/browser/browser_forgetthissite_single.js
@@ -53,38 +53,30 @@ function waitForClearHistory(aCallback) 
 
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
 }
 
 function test() {
   // initialization
-  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-           getService(Ci.nsIWindowWatcher);
   waitForExplicitFinish();
 
   // Add a history entry.
   let TEST_URIs = ["http://www.mozilla.org/test1", "http://www.mozilla.org/test2"];
   ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
   let history = PlacesUtils.history;
   TEST_URIs.forEach(function(TEST_URI) {
     let visitId = history.addVisit(PlacesUtils._uri(TEST_URI), Date.now() * 1000,
                                    null, PlacesUtils.history.TRANSITION_TYPED, false, 0);
     ok(visitId > 0, TEST_URI + " successfully marked visited");
   });
 
   function testForgetThisSiteVisibility(selectionCount, funcNext) {
-    function observer(aSubject, aTopic, aData) {
-      if (aTopic != "domwindowopened")
-        return;
-      ww.unregisterNotification(observer);
-      let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
-      SimpleTest.waitForFocus(function() {
-        executeSoon(function() {
+    openLibrary(function (organizer) {
           // Select History in the left pane.
           organizer.PlacesOrganizer.selectLeftPaneQuery('History');
           let PO = organizer.PlacesOrganizer;
           let histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
           histContainer.containerOpen = true;
           PO._places.selectNode(histContainer.getChild(0));
           // Select the first history entry.
           let doc = organizer.document;
@@ -101,43 +93,31 @@ function test() {
             let forgetThisSite = doc.getElementById("placesContext_deleteHost");
             let hideForgetThisSite = (selectionCount != 1);
             is(forgetThisSite.hidden, hideForgetThisSite,
               "The Forget this site menu item should " + (hideForgetThisSite ? "" : "not ") +
               "be hidden with " + selectionCount + " items selected");
             // Close the context menu
             contextmenu.hidePopup();
             // Wait for the Organizer window to actually be closed
-            function closeObserver(aSubject, aTopic, aData) {
-              if (aTopic != "domwindowclosed")
-                return;
-              ww.unregisterNotification(closeObserver);
+            organizer.addEventListener("unload", function () {
+              organizer.removeEventListener("unload", arguments.callee, false);
               // Proceed
               funcNext();
-            }
-            ww.registerNotification(closeObserver);
+            }, false);
             // Close Library window.
             organizer.close();
           }, true);
           // Get cell coordinates
           var x = {}, y = {}, width = {}, height = {};
           tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
                                                   x, y, width, height);
           // Initiate a context menu for the selected cell
           EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
-        });
-      }, organizer);
-    }
-
-    ww.registerNotification(observer);
-    ww.openWindow(null,
-                  "chrome://browser/content/places/places.xul",
-                  "",
-                  "chrome,toolbar=yes,dialog=no,resizable",
-                  null);
+    });
   }
 
   testForgetThisSiteVisibility(1, function() {
     testForgetThisSiteVisibility(2, function() {
       // Cleanup
       waitForClearHistory(finish);
     });
   });
--- a/browser/components/places/tests/browser/browser_library_batch_delete.js
+++ b/browser/components/places/tests/browser/browser_library_batch_delete.js
@@ -91,35 +91,20 @@ gTests.push({
 
 function test() {
   waitForExplicitFinish();
   registerCleanupFunction(function () {
     PlacesUtils.bookmarks
                .removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
   });
 
-  Services.ww.registerNotification(function (aSubject, aTopic, aData)
-  {
-    if (aTopic != "domwindowopened")
-      return;
-
-    Services.ww.unregisterNotification(arguments.callee);
-
-    gLibrary = aSubject.QueryInterface(Ci.nsIDOMWindow);
-    gLibrary.addEventListener("load", function (event) {
-      gLibrary.removeEventListener("load", arguments.callee, false);
-      executeSoon(nextTest);
-    }, false);
+  openLibrary(function (library) {
+    gLibrary = library;
+    executeSoon(nextTest);
   });
-
-  Services.ww.openWindow(null,
-                         "chrome://browser/content/places/places.xul",
-                          "",
-                          "chrome,toolbar=yes,dialog=no,resizable",
-                          null);
 }
 
 function nextTest() {
   if (gTests.length) {
     var test = gTests.shift();
     info("Start of test: " + test.desc);
     test.run();
   }
--- a/browser/components/places/tests/browser/browser_library_infoBox.js
+++ b/browser/components/places/tests/browser/browser_library_infoBox.js
@@ -210,40 +210,21 @@ function nextTest() {
   else {
     // Close Library window.
     gLibrary.close();
     // No need to cleanup anything, we have a correct left pane now.
     finish();
   }
 }
 
-var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher);
-
-function windowObserver(aSubject, aTopic, aData) {
-  if (aTopic != "domwindowopened")
-    return;
-  ww.unregisterNotification(windowObserver);
-  gLibrary = aSubject.QueryInterface(Ci.nsIDOMWindow);
-  gLibrary.addEventListener("load", function onLoad(event) {
-    gLibrary.removeEventListener("load", onLoad, false);
-    executeSoon(function() {
-      gLibrary.PlacesOrganizer._places.focus();
-      waitForFocus(nextTest, gLibrary);
-    });
-  }, false);
-}
-
 function test() {
-  dump("Starting test browser_library_infoBox.js\n");
   waitForExplicitFinish();
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils is running in chrome context");
   ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
 
   // Open Library.
-  ww.registerNotification(windowObserver);
-  ww.openWindow(null,
-                "chrome://browser/content/places/places.xul",
-                "",
-                "chrome,toolbar=yes,dialog=no,resizable",
-                null);
+  openLibrary(function (library) {
+    gLibrary = library;
+    gLibrary.PlacesOrganizer._places.focus();
+    nextTest(gLibrary);
+  });
 }
--- a/browser/components/places/tests/browser/browser_library_left_pane_commands.js
+++ b/browser/components/places/tests/browser/browser_library_left_pane_commands.js
@@ -168,36 +168,20 @@ function nextTest() {
   else {
     // Close Library window.
     gLibrary.close();
     // No need to cleanup anything, we have a correct left pane now.
     finish();
   }
 }
 
-var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher);
-
-function windowObserver(aSubject, aTopic, aData) {
-  if (aTopic != "domwindowopened")
-    return;
-  ww.unregisterNotification(windowObserver);
-  gLibrary = aSubject.QueryInterface(Ci.nsIDOMWindow);
-  gLibrary.addEventListener("load", function onLoad(event) {
-    gLibrary.removeEventListener("load", onLoad, false);
-    executeSoon(nextTest);
-  }, false);
-}
-
 function test() {
   waitForExplicitFinish();
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils is running in chrome context");
   ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
 
   // Open Library.
-  ww.registerNotification(windowObserver);
-  ww.openWindow(null,
-                "chrome://browser/content/places/places.xul",
-                "",
-                "chrome,toolbar=yes,dialog=no,resizable",
-                null);
+  openLibrary(function (library) {
+    gLibrary = library;
+    nextTest();
+  });
 }
--- a/browser/components/places/tests/browser/browser_library_left_pane_fixnames.js
+++ b/browser/components/places/tests/browser/browser_library_left_pane_fixnames.js
@@ -35,50 +35,38 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  *  Test we correctly fix broken Library left pane queries names.
  */
 
-var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher);
-
 // Array of left pane queries objects, each one has the following properties:
 // name: query's identifier got from annotations,
 // itemId: query's itemId,
 // correctTitle: original and correct query's title.
 var leftPaneQueries = [];
 
-function windowObserver(aSubject, aTopic, aData) {
-  if (aTopic != "domwindowopened")
-    return;
-  ww.unregisterNotification(windowObserver);
-  var organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
-  organizer.addEventListener("load", function onLoad(event) {
-    organizer.removeEventListener("load", onLoad, false);
-    executeSoon(function () {
+function onLibraryReady(organizer) {
       // Check titles have been fixed.
       for (var i = 0; i < leftPaneQueries.length; i++) {
         var query = leftPaneQueries[i];
         is(PlacesUtils.bookmarks.getItemTitle(query.itemId),
            query.correctTitle, "Title is correct for query " + query.name);
         if ("concreteId" in query) {
           is(PlacesUtils.bookmarks.getItemTitle(query.concreteId),
            query.concreteTitle, "Concrete title is correct for query " + query.name);
         }
       }
 
       // Close Library window.
       organizer.close();
       // No need to cleanup anything, we have a correct left pane now.
       finish();
-    });
-  }, false);
 }
 
 function test() {
   waitForExplicitFinish();
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils is running in chrome context");
   ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
   ok(PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION > 0,
@@ -129,15 +117,10 @@ function test() {
     PlacesUtils.bookmarks.setItemTitle(query.itemId, "badName");
     if ("concreteId" in query)
       PlacesUtils.bookmarks.setItemTitle(query.concreteId, "badName");
   }
 
   PlacesUIUtils.__defineGetter__("leftPaneFolderId", cachedLeftPaneFolderIdGetter);
 
   // Open Library, this will kick-off left pane code.
-  ww.registerNotification(windowObserver);
-  ww.openWindow(null,
-                "chrome://browser/content/places/places.xul",
-                "",
-                "chrome,toolbar=yes,dialog=no,resizable",
-                null);
+  openLibrary(onLibraryReady);
 }
--- a/browser/components/places/tests/browser/browser_library_middleclick.js
+++ b/browser/components/places/tests/browser/browser_library_middleclick.js
@@ -241,38 +241,22 @@ function test() {
 
   // Add tabs listeners.
   gBrowser.tabContainer.addEventListener("TabOpen", gTabsListener, false);
   gBrowser.addTabsProgressListener(gTabsListener);
 
   // Temporary disable history, so we won't record pages navigation.
   gPrefService.setBoolPref(ENABLE_HISTORY_PREF, false);
 
-  // Window watcher for Library window.
-  var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-           getService(Ci.nsIWindowWatcher);
-  function windowObserver(aSubject, aTopic, aData) {
-    if (aTopic != "domwindowopened")
-      return;
-    ww.unregisterNotification(windowObserver);
-    gLibrary = aSubject.QueryInterface(Ci.nsIDOMWindow);
-    gLibrary.addEventListener("load", function onLoad(event) {
-      gLibrary.removeEventListener("load", onLoad, false);
-      // Kick off tests.
-      setTimeout(runNextTest, 0);
-    }, false);
-  }
-
   // Open Library window.
-