Merge M-C -> IonMonkey.
authorSean Stangl <sstangl@mozilla.com>
Fri, 18 Nov 2011 15:27:12 -0800
changeset 105381 d3f02a9d4238de52da37126a94fcc6fbb054e905
parent 105380 2f01551d1e84948ef73d31f838548e2f09dbb0fe (current diff)
parent 80494 ac667309bea6bb2b1c3e93035023ac709d013c86 (diff)
child 105382 5deb641ced5b3fd7db7513ef159720ddd1089994
push id14706
push usereakhgari@mozilla.com
push dateTue, 11 Sep 2012 20:39:52 +0000
treeherdermozilla-inbound@d50bf1edaabe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.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 -> IonMonkey.
accessible/src/base/NotificationController.cpp
accessible/src/base/nsARIAMap.cpp
accessible/src/msaa/nsAccessibleWrap.cpp
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/devtools/jar.mn
browser/devtools/styleinspector/test/browser/browser_styleinspector_webconsole.htm
browser/devtools/styleinspector/test/browser/browser_styleinspector_webconsole.js
browser/devtools/webconsole/HUDService.jsm
browser/devtools/webconsole/test/browser/Makefile.in
browser/locales/en-US/chrome/browser/browser.dtd
build/win32/mozilla-dos2unix.py
config/autoconf.mk.in
configure.in
content/base/public/nsContentUtils.h
content/base/public/nsDOMFile.h
content/base/public/nsIDocument.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDOMParser.cpp
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsXMLHttpRequest.cpp
content/base/src/nsXMLHttpRequest.h
content/base/test/Makefile.in
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/test/test_canvas.html
content/html/content/test/file_fullscreen-api.html
content/html/document/src/nsHTMLDocument.cpp
content/xml/document/src/nsXMLDocument.cpp
docshell/base/nsDocShell.cpp
dom/indexedDB/IDBTransaction.cpp
dom/locales/en-US/chrome/dom/dom.properties
dom/plugins/test/reftest/reftest.list
gfx/2d/Blur.cpp
gfx/2d/Blur.h
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/d3d9/CanvasLayerD3D9.h
gfx/thebes/gfxASurface.cpp
gfx/thebes/gfxASurface.h
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxAndroidPlatform.h
gfx/thebes/gfxBlur.cpp
gfx/thebes/gfxBlur.h
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxContext.h
gfx/thebes/gfxD2DSurface.cpp
gfx/thebes/gfxD2DSurface.h
gfx/thebes/gfxFontUtils.cpp
gfx/thebes/gfxMacFont.cpp
gfx/thebes/gfxMacFont.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxPlatformMac.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
gfx/thebes/gfxWindowsSurface.cpp
gfx/thebes/gfxWindowsSurface.h
gfx/thebes/nsCoreAnimationSupport.mm
image/decoders/nsBMPDecoder.cpp
js/src/jsapi.h
js/src/jscompartment.h
js/src/jsgc.cpp
js/src/jsgcmark.h
js/src/jsobj.cpp
js/src/jsxml.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsDocumentViewer.cpp
layout/base/nsLayoutDebugger.cpp
layout/base/nsLayoutUtils.cpp
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsImageFrame.cpp
layout/generic/nsTextFrameThebes.cpp
layout/ipc/RenderFrameParent.cpp
layout/reftests/canvas/reftest.list
layout/style/ua.css
layout/xul/base/src/nsScrollbarButtonFrame.cpp
layout/xul/base/src/nsScrollbarButtonFrame.h
memory/jemalloc/jemalloc.c
mobile/LICENSE
mobile/Makefile.in
mobile/app/Makefile.in
mobile/app/android/drawable-hdpi/alertaddons.png
mobile/app/android/drawable-hdpi/alertdownloads.png
mobile/app/android/drawable/alertaddons.png
mobile/app/android/drawable/alertdownloads.png
mobile/app/application.ini
mobile/app/macbuild/Contents/Info.plist.in
mobile/app/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
mobile/app/maemo/toolbar_splash.png
mobile/app/mobile.ico
mobile/app/mobile.js
mobile/app/nsBrowserApp.cpp
mobile/app/profile/extensions/Makefile.in
mobile/app/profile/extensions/feedback@mobile.mozilla.org/chrome.manifest
mobile/app/profile/extensions/feedback@mobile.mozilla.org/content/content.js
mobile/app/profile/extensions/feedback@mobile.mozilla.org/content/overlay.js
mobile/app/profile/extensions/feedback@mobile.mozilla.org/content/overlay.xul
mobile/app/profile/extensions/feedback@mobile.mozilla.org/defaults/preferences/preferences.js
mobile/app/profile/extensions/feedback@mobile.mozilla.org/install.rdf.in
mobile/app/profile/extensions/feedback@mobile.mozilla.org/skin/beta-hdpi.png
mobile/app/profile/extensions/feedback@mobile.mozilla.org/skin/dino-32.png
mobile/app/profile/extensions/feedback@mobile.mozilla.org/skin/happy-32.png
mobile/app/profile/extensions/feedback@mobile.mozilla.org/skin/overlay.css
mobile/app/profile/extensions/feedback@mobile.mozilla.org/skin/sad-32.png
mobile/branding/aurora/Makefile.in
mobile/branding/aurora/android-resources.mn
mobile/branding/aurora/configure.sh
mobile/branding/aurora/content/Makefile.in
mobile/branding/aurora/content/about.png
mobile/branding/aurora/content/favicon32.png
mobile/branding/aurora/content/fennec_26x26.png
mobile/branding/aurora/content/fennec_40x40.png
mobile/branding/aurora/content/fennec_48x48.png
mobile/branding/aurora/content/fennec_72x72.png
mobile/branding/aurora/content/fennec_maemo_icon26.txt
mobile/branding/aurora/content/fennec_scalable.png
mobile/branding/aurora/content/jar.mn
mobile/branding/aurora/content/logo.png
mobile/branding/aurora/content/logoWordmark.png
mobile/branding/aurora/content/splash.png
mobile/branding/aurora/content/splash_v8.9.png
mobile/branding/aurora/content/splash_v9.9.png
mobile/branding/aurora/locales/Makefile.in
mobile/branding/aurora/locales/en-US/brand.dtd
mobile/branding/aurora/locales/en-US/brand.properties
mobile/branding/aurora/locales/jar.mn
mobile/branding/beta/Makefile.in
mobile/branding/beta/android-resources.mn
mobile/branding/beta/configure.sh
mobile/branding/beta/content/Makefile.in
mobile/branding/beta/content/about.png
mobile/branding/beta/content/favicon32.png
mobile/branding/beta/content/fennec_26x26.png
mobile/branding/beta/content/fennec_40x40.png
mobile/branding/beta/content/fennec_48x48.png
mobile/branding/beta/content/fennec_72x72.png
mobile/branding/beta/content/fennec_maemo_icon26.txt
mobile/branding/beta/content/fennec_scalable.png
mobile/branding/beta/content/jar.mn
mobile/branding/beta/content/logo.png
mobile/branding/beta/content/logoWordmark.png
mobile/branding/beta/content/splash.png
mobile/branding/beta/content/splash_v8.9.png
mobile/branding/beta/content/splash_v9.9.png
mobile/branding/beta/locales/Makefile.in
mobile/branding/beta/locales/en-US/brand.dtd
mobile/branding/beta/locales/en-US/brand.properties
mobile/branding/beta/locales/jar.mn
mobile/branding/nightly/Makefile.in
mobile/branding/nightly/android-resources.mn
mobile/branding/nightly/configure.sh
mobile/branding/nightly/content/Makefile.in
mobile/branding/nightly/content/about.png
mobile/branding/nightly/content/favicon32.png
mobile/branding/nightly/content/fennec_26x26.png
mobile/branding/nightly/content/fennec_40x40.png
mobile/branding/nightly/content/fennec_48x48.png
mobile/branding/nightly/content/fennec_72x72.png
mobile/branding/nightly/content/fennec_maemo_icon26.txt
mobile/branding/nightly/content/fennec_scalable.png
mobile/branding/nightly/content/jar.mn
mobile/branding/nightly/content/logo.png
mobile/branding/nightly/content/logoWordmark.png
mobile/branding/nightly/content/splash.png
mobile/branding/nightly/content/splash_v8.9.png
mobile/branding/nightly/content/splash_v9.9.png
mobile/branding/nightly/locales/Makefile.in
mobile/branding/nightly/locales/en-US/brand.dtd
mobile/branding/nightly/locales/en-US/brand.properties
mobile/branding/nightly/locales/jar.mn
mobile/branding/official/Makefile.in
mobile/branding/official/android-resources.mn
mobile/branding/official/configure.sh
mobile/branding/official/content/Makefile.in
mobile/branding/official/content/about.png
mobile/branding/official/content/favicon32.png
mobile/branding/official/content/fennec_26x26.png
mobile/branding/official/content/fennec_40x40.png
mobile/branding/official/content/fennec_48x48.png
mobile/branding/official/content/fennec_72x72.png
mobile/branding/official/content/fennec_maemo_icon26.txt
mobile/branding/official/content/fennec_scalable.png
mobile/branding/official/content/jar.mn
mobile/branding/official/content/logo.png
mobile/branding/official/content/logoWordmark.png
mobile/branding/official/content/splash.png
mobile/branding/official/content/splash_v8.9.png
mobile/branding/official/content/splash_v9.9.png
mobile/branding/official/locales/Makefile.in
mobile/branding/official/locales/en-US/brand.dtd
mobile/branding/official/locales/en-US/brand.properties
mobile/branding/official/locales/jar.mn
mobile/branding/unofficial/Makefile.in
mobile/branding/unofficial/android-resources.mn
mobile/branding/unofficial/configure.sh
mobile/branding/unofficial/content/Makefile.in
mobile/branding/unofficial/content/about.png
mobile/branding/unofficial/content/favicon32.png
mobile/branding/unofficial/content/fennec_26x26.png
mobile/branding/unofficial/content/fennec_40x40.png
mobile/branding/unofficial/content/fennec_48x48.png
mobile/branding/unofficial/content/fennec_72x72.png
mobile/branding/unofficial/content/fennec_maemo_icon26.txt
mobile/branding/unofficial/content/fennec_scalable.png
mobile/branding/unofficial/content/jar.mn
mobile/branding/unofficial/content/logo.png
mobile/branding/unofficial/content/logoWordmark.png
mobile/branding/unofficial/content/splash.png
mobile/branding/unofficial/content/splash_v8.9.png
mobile/branding/unofficial/content/splash_v9.9.png
mobile/branding/unofficial/locales/Makefile.in
mobile/branding/unofficial/locales/en-US/brand.dtd
mobile/branding/unofficial/locales/en-US/brand.properties
mobile/branding/unofficial/locales/jar.mn
mobile/build.mk
mobile/chrome/Makefile.in
mobile/chrome/content/AlertsHelper.js
mobile/chrome/content/AnimatedZoom.js
mobile/chrome/content/AppMenu.js
mobile/chrome/content/AwesomePanel.js
mobile/chrome/content/BookmarkHelper.js
mobile/chrome/content/BookmarkPopup.js
mobile/chrome/content/CaptureDialog.js
mobile/chrome/content/CaptureDialog.xul
mobile/chrome/content/CapturePickerUI.js
mobile/chrome/content/CharsetMenu.js
mobile/chrome/content/ContentPopupHelper.js
mobile/chrome/content/ContextCommands.js
mobile/chrome/content/IndexedDB.js
mobile/chrome/content/LoginManagerChild.js
mobile/chrome/content/MasterPasswordUI.js
mobile/chrome/content/MenuListHelperUI.js
mobile/chrome/content/OfflineApps.js
mobile/chrome/content/PageActions.js
mobile/chrome/content/SelectHelperUI.js
mobile/chrome/content/SelectionHelper.js
mobile/chrome/content/SharingUI.js
mobile/chrome/content/TabletSidebar.js
mobile/chrome/content/TabsPopup.js
mobile/chrome/content/Util.js
mobile/chrome/content/WebappsUI.js
mobile/chrome/content/about.xhtml
mobile/chrome/content/aboutCertError.xhtml
mobile/chrome/content/aboutHome.xhtml
mobile/chrome/content/aboutRights.xhtml
mobile/chrome/content/bindings.xml
mobile/chrome/content/bindings/arrowbox.xml
mobile/chrome/content/bindings/browser.js
mobile/chrome/content/bindings/browser.xml
mobile/chrome/content/bindings/checkbox.xml
mobile/chrome/content/bindings/console.xml
mobile/chrome/content/bindings/dialog.xml
mobile/chrome/content/bindings/downloads.xml
mobile/chrome/content/bindings/extensions.xml
mobile/chrome/content/bindings/pageaction.xml
mobile/chrome/content/blockedSite.xhtml
mobile/chrome/content/browser-scripts.js
mobile/chrome/content/browser-ui.js
mobile/chrome/content/browser.css
mobile/chrome/content/browser.js
mobile/chrome/content/browser.xul
mobile/chrome/content/commandUtil.js
mobile/chrome/content/common-ui.js
mobile/chrome/content/config.js
mobile/chrome/content/config.xul
mobile/chrome/content/console.js
mobile/chrome/content/content.js
mobile/chrome/content/cursor.css
mobile/chrome/content/downloads.js
mobile/chrome/content/exceptions.js
mobile/chrome/content/extensions.js
mobile/chrome/content/forms.js
mobile/chrome/content/fullscreen-video.js
mobile/chrome/content/fullscreen-video.xhtml
mobile/chrome/content/input.js
mobile/chrome/content/languages.properties
mobile/chrome/content/localePicker.js
mobile/chrome/content/localePicker.xul
mobile/chrome/content/masterPassword.xul
mobile/chrome/content/netError.xhtml
mobile/chrome/content/notification.xml
mobile/chrome/content/preferences.js
mobile/chrome/content/prompt/alert.xul
mobile/chrome/content/prompt/confirm.xul
mobile/chrome/content/prompt/prompt.js
mobile/chrome/content/prompt/prompt.xul
mobile/chrome/content/prompt/promptPassword.xul
mobile/chrome/content/prompt/select.xul
mobile/chrome/content/removeMasterPassword.xul
mobile/chrome/content/sanitize.js
mobile/chrome/content/share.xul
mobile/chrome/content/sync.js
mobile/chrome/content/tabs.xml
mobile/chrome/content/webapps.xul
mobile/chrome/jar.mn
mobile/chrome/tests/Makefile.in
mobile/chrome/tests/addons/browser_install1_1/bootstrap.js
mobile/chrome/tests/addons/browser_install1_1/install.rdf
mobile/chrome/tests/addons/browser_install1_2/install.rdf
mobile/chrome/tests/addons/browser_install1_3/install.rdf
mobile/chrome/tests/addons/browser_locale1/boostrap.js
mobile/chrome/tests/addons/browser_locale1/chrome.manifest
mobile/chrome/tests/addons/browser_locale1/install.rdf
mobile/chrome/tests/browser_addons.js
mobile/chrome/tests/browser_addons_locales.js
mobile/chrome/tests/browser_appmenu.js
mobile/chrome/tests/browser_autocomplete.html
mobile/chrome/tests/browser_autocomplete.js
mobile/chrome/tests/browser_autocompletesearch.js
mobile/chrome/tests/browser_awesomescreen.js
mobile/chrome/tests/browser_blank_01.html
mobile/chrome/tests/browser_blank_02.html
mobile/chrome/tests/browser_blank_03.html
mobile/chrome/tests/browser_bookmarks.js
mobile/chrome/tests/browser_bookmarks_star.js
mobile/chrome/tests/browser_bookmarks_tags.js
mobile/chrome/tests/browser_click_content.html
mobile/chrome/tests/browser_click_content.js
mobile/chrome/tests/browser_contacts.js
mobile/chrome/tests/browser_contentpopup.html
mobile/chrome/tests/browser_contentpopup.js
mobile/chrome/tests/browser_dragger.js
mobile/chrome/tests/browser_escape.js
mobile/chrome/tests/browser_find.js
mobile/chrome/tests/browser_focus.html
mobile/chrome/tests/browser_focus.js
mobile/chrome/tests/browser_forms.html
mobile/chrome/tests/browser_forms.js
mobile/chrome/tests/browser_formsZoom.html
mobile/chrome/tests/browser_formsZoom.js
mobile/chrome/tests/browser_history.js
mobile/chrome/tests/browser_install.xml
mobile/chrome/tests/browser_localepicker.js
mobile/chrome/tests/browser_localepicker_escape.js
mobile/chrome/tests/browser_localerepository.js
mobile/chrome/tests/browser_localerepository_buildid.js
mobile/chrome/tests/browser_localerepository_pref.js
mobile/chrome/tests/browser_mainui.js
mobile/chrome/tests/browser_navigation.js
mobile/chrome/tests/browser_preferences_fulltoggle.js
mobile/chrome/tests/browser_preferences_text.js
mobile/chrome/tests/browser_rect.js
mobile/chrome/tests/browser_rememberPassword.js
mobile/chrome/tests/browser_scroll.html
mobile/chrome/tests/browser_scroll.js
mobile/chrome/tests/browser_scrollbar.js
mobile/chrome/tests/browser_scrollbar.sjs
mobile/chrome/tests/browser_select.html
mobile/chrome/tests/browser_select.js
mobile/chrome/tests/browser_sessionstore.js
mobile/chrome/tests/browser_sidebars.js
mobile/chrome/tests/browser_tabs.js
mobile/chrome/tests/browser_tap_content.html
mobile/chrome/tests/browser_tap_contentedit.html
mobile/chrome/tests/browser_tapping.js
mobile/chrome/tests/browser_tapping_edit.js
mobile/chrome/tests/browser_test.js
mobile/chrome/tests/browser_thumbnails.js
mobile/chrome/tests/browser_title.sjs
mobile/chrome/tests/browser_upgrade.rdf
mobile/chrome/tests/browser_viewport.js
mobile/chrome/tests/browser_viewport.sjs
mobile/chrome/tests/browser_vkb.js
mobile/chrome/tests/head.js
mobile/chrome/tests/locales_list.sjs
mobile/chrome/tests/mock_autocomplete.json
mobile/chrome/tests/remote_autocomplete.js
mobile/chrome/tests/remote_contentpopup.js
mobile/chrome/tests/remote_focus.js
mobile/chrome/tests/remote_forms.js
mobile/chrome/tests/remote_formsZoom.js
mobile/chrome/tests/remote_head.js
mobile/chrome/tests/remote_vkb.js
mobile/components/AboutRedirector.js
mobile/components/AddonUpdateService.js
mobile/components/AlertsService.js
mobile/components/AutoCompleteCache.js
mobile/components/BlocklistPrompt.js
mobile/components/BrowserCLH.js
mobile/components/BrowserStartup.js
mobile/components/CapturePicker.js
mobile/components/ContentDispatchChooser.js
mobile/components/ContentPermissionPrompt.js
mobile/components/DirectoryProvider.js
mobile/components/DownloadManagerUI.js
mobile/components/FormAutoComplete.js
mobile/components/HelperAppDialog.js
mobile/components/LoginManager.js
mobile/components/LoginManagerPrompter.idl
mobile/components/LoginManagerPrompter.js
mobile/components/Makefile.in
mobile/components/MobileComponents.manifest
mobile/components/PromptService.js
mobile/components/SafeBrowsing.js
mobile/components/SessionStore.idl
mobile/components/SessionStore.js
mobile/components/Sidebar.js
mobile/components/UpdatePrompt.js
mobile/components/XPIDialogService.js
mobile/components/build/Makefile.in
mobile/components/build/nsBrowserComponents.h
mobile/components/build/nsBrowserModule.cpp
mobile/components/build/nsIShellService.idl
mobile/components/build/nsShellService.cpp
mobile/components/build/nsShellService.h
mobile/config/mozconfigs/android/debug
mobile/config/mozconfigs/android/nightly
mobile/config/mozconfigs/linux-desktop/l10n-mozconfig
mobile/config/mozconfigs/linux-desktop/nightly
mobile/config/mozconfigs/macosx-desktop/l10n-mozconfig
mobile/config/mozconfigs/macosx-desktop/nightly
mobile/config/mozconfigs/win32-desktop/l10n-mozconfig
mobile/config/mozconfigs/win32-desktop/nightly
mobile/confvars.sh
mobile/installer/Makefile.in
mobile/installer/debian/backup.in
mobile/installer/debian/changelog.in
mobile/installer/debian/compat.in
mobile/installer/debian/control.in
mobile/installer/debian/fennec-cud.sh.in
mobile/installer/debian/fennec-rfs.sh.in
mobile/installer/debian/fennec.aegis.in
mobile/installer/debian/fennec.conf.in
mobile/installer/debian/fennec.desktop.in
mobile/installer/debian/fennec.links.in
mobile/installer/debian/fennec.policy.in
mobile/installer/debian/fennec.postinst.in
mobile/installer/debian/fennec.preinst.in
mobile/installer/debian/fennec.prerm.in
mobile/installer/debian/fennec.service.in
mobile/installer/debian/files.in
mobile/installer/debian/menu.in
mobile/installer/debian/restore.in
mobile/installer/mobile-l10n.js
mobile/installer/package-manifest.in
mobile/installer/removed-files.in
mobile/locales/Makefile.in
mobile/locales/all-locales
mobile/locales/en-US/chrome/about.dtd
mobile/locales/en-US/chrome/aboutCertError.dtd
mobile/locales/en-US/chrome/aboutHome.dtd
mobile/locales/en-US/chrome/browser.dtd
mobile/locales/en-US/chrome/browser.properties
mobile/locales/en-US/chrome/checkbox.dtd
mobile/locales/en-US/chrome/config.dtd
mobile/locales/en-US/chrome/feedback.dtd
mobile/locales/en-US/chrome/localepicker.properties
mobile/locales/en-US/chrome/notification.dtd
mobile/locales/en-US/chrome/overrides/appstrings.properties
mobile/locales/en-US/chrome/overrides/netError.dtd
mobile/locales/en-US/chrome/overrides/passwordmgr.properties
mobile/locales/en-US/chrome/phishing.dtd
mobile/locales/en-US/chrome/preferences.dtd
mobile/locales/en-US/chrome/prompt.dtd
mobile/locales/en-US/chrome/region.properties
mobile/locales/en-US/chrome/sync.dtd
mobile/locales/en-US/chrome/sync.properties
mobile/locales/en-US/chrome/webapps.dtd
mobile/locales/en-US/crashreporter/crashreporter-override.ini
mobile/locales/en-US/defines.inc
mobile/locales/en-US/installer/setup.ini
mobile/locales/en-US/mobile-l10n.js
mobile/locales/en-US/profile/bookmarks.inc
mobile/locales/en-US/searchplugins/amazondotcom.xml
mobile/locales/en-US/searchplugins/google.xml
mobile/locales/en-US/searchplugins/list.txt
mobile/locales/en-US/searchplugins/twitter.xml
mobile/locales/en-US/searchplugins/wikipedia.xml
mobile/locales/en-US/searchplugins/yahoo.xml
mobile/locales/en-US/updater/updater.ini
mobile/locales/filter.py
mobile/locales/generic/install.rdf
mobile/locales/generic/profile/bookmarks.json.in
mobile/locales/jar.mn
mobile/locales/l10n-central.ini
mobile/locales/l10n-mozilla-1.9.2.ini
mobile/locales/l10n-mozilla-2.0.ini
mobile/locales/l10n.ini
mobile/locales/maemo-locales
mobile/makefiles.sh
mobile/modules/LocaleRepository.jsm
mobile/modules/Makefile.in
mobile/modules/contacts.jsm
mobile/modules/linuxTypes.jsm
mobile/modules/video.jsm
mobile/themes/core/Makefile.in
mobile/themes/core/about.css
mobile/themes/core/aboutHome.css
mobile/themes/core/aboutPage.css
mobile/themes/core/browser.css
mobile/themes/core/config.css
mobile/themes/core/content.css
mobile/themes/core/defines.inc
mobile/themes/core/forms.css
mobile/themes/core/gingerbread/browser.css
mobile/themes/core/gingerbread/content.css
mobile/themes/core/gingerbread/defines.inc
mobile/themes/core/gingerbread/forms.css
mobile/themes/core/gingerbread/images/aboutBackground.jpg
mobile/themes/core/gingerbread/images/addons-default-hdpi.png
mobile/themes/core/gingerbread/images/alert-addons-30.png
mobile/themes/core/gingerbread/images/alert-downloads-30.png
mobile/themes/core/gingerbread/images/allpages-48.png
mobile/themes/core/gingerbread/images/appmenu-active-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-addons-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-downloads-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-findinpage-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-more-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-preferences-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-share-hdpi.png
mobile/themes/core/gingerbread/images/appmenu-site-hdpi.png
mobile/themes/core/gingerbread/images/arrowbox-down.png
mobile/themes/core/gingerbread/images/arrowbox-horiz.png
mobile/themes/core/gingerbread/images/arrowbox-up.png
mobile/themes/core/gingerbread/images/arrowdown-16.png
mobile/themes/core/gingerbread/images/arrowdowndark-16.png
mobile/themes/core/gingerbread/images/arrowleft-16.png
mobile/themes/core/gingerbread/images/arrowleftdark-16.png
mobile/themes/core/gingerbread/images/arrowright-16.png
mobile/themes/core/gingerbread/images/arrowrightdark-16.png
mobile/themes/core/gingerbread/images/arrowup-16.png
mobile/themes/core/gingerbread/images/arrowupdark-16.png
mobile/themes/core/gingerbread/images/autocomplete-bookmarked-hdpi.png
mobile/themes/core/gingerbread/images/autocomplete-desktop-hdpi.png
mobile/themes/core/gingerbread/images/autocomplete-search-hdpi.png
mobile/themes/core/gingerbread/images/back-default-hdpi.png
mobile/themes/core/gingerbread/images/bookmark-default-hdpi.png
mobile/themes/core/gingerbread/images/bookmark-starred-hdpi.png
mobile/themes/core/gingerbread/images/bookmarks-48.png
mobile/themes/core/gingerbread/images/browseaddons-bg.jpg
mobile/themes/core/gingerbread/images/button-bg.png
mobile/themes/core/gingerbread/images/check-30.png
mobile/themes/core/gingerbread/images/check-selected-hdpi.png
mobile/themes/core/gingerbread/images/check-unselected-hdpi.png
mobile/themes/core/gingerbread/images/close-active-hdpi.png
mobile/themes/core/gingerbread/images/close-active-tablet-hdpi.png
mobile/themes/core/gingerbread/images/close-background-hdpi-rtl.png
mobile/themes/core/gingerbread/images/close-background-hdpi.png
mobile/themes/core/gingerbread/images/close-default-hdpi.png
mobile/themes/core/gingerbread/images/close-default-tablet-hdpi.png
mobile/themes/core/gingerbread/images/close-inactive-tab-hdpi.png
mobile/themes/core/gingerbread/images/close-inactive-tab-tablet-hdpi.png
mobile/themes/core/gingerbread/images/console-default-hdpi.png
mobile/themes/core/gingerbread/images/downloads-default-hdpi.png
mobile/themes/core/gingerbread/images/dropmarker-hdpi.png
mobile/themes/core/gingerbread/images/endcap-active-bg.png
mobile/themes/core/gingerbread/images/endcap-default-bg.png
mobile/themes/core/gingerbread/images/endcap-ev-active-bg.png
mobile/themes/core/gingerbread/images/endcap-ev-default-bg.png
mobile/themes/core/gingerbread/images/endcap-ssl-active-bg.png
mobile/themes/core/gingerbread/images/endcap-ssl-default-bg.png
mobile/themes/core/gingerbread/images/errorpage-larry-black.png
mobile/themes/core/gingerbread/images/errorpage-larry-white.png
mobile/themes/core/gingerbread/images/errorpage-warning.png
mobile/themes/core/gingerbread/images/favicon-default-32.png
mobile/themes/core/gingerbread/images/folder-32.png
mobile/themes/core/gingerbread/images/forward-default-hdpi.png
mobile/themes/core/gingerbread/images/handle-end.png
mobile/themes/core/gingerbread/images/handle-start.png
mobile/themes/core/gingerbread/images/history-48.png
mobile/themes/core/gingerbread/images/identity-default-hdpi.png
mobile/themes/core/gingerbread/images/identity-ev-hdpi.png
mobile/themes/core/gingerbread/images/identity-ssl-hdpi.png
mobile/themes/core/gingerbread/images/locked-hdpi.png
mobile/themes/core/gingerbread/images/mute-hdpi.png
mobile/themes/core/gingerbread/images/navigation-magnifier-30.png
mobile/themes/core/gingerbread/images/newtab-default-hdpi.png
mobile/themes/core/gingerbread/images/newtab-default-tablet-hdpi.png
mobile/themes/core/gingerbread/images/next-disabled-hdpi.png
mobile/themes/core/gingerbread/images/next-hdpi.png
mobile/themes/core/gingerbread/images/pause-hdpi.png
mobile/themes/core/gingerbread/images/play-hdpi.png
mobile/themes/core/gingerbread/images/popup-selected-item-hdpi.png
mobile/themes/core/gingerbread/images/preferences-default-hdpi.png
mobile/themes/core/gingerbread/images/previous-disabled-hdpi.png
mobile/themes/core/gingerbread/images/previous-hdpi.png
mobile/themes/core/gingerbread/images/radio-selected-hdpi.png
mobile/themes/core/gingerbread/images/radio-unselected-hdpi.png
mobile/themes/core/gingerbread/images/reload-hdpi.png
mobile/themes/core/gingerbread/images/remotetabs-32.png
mobile/themes/core/gingerbread/images/remotetabs-48.png
mobile/themes/core/gingerbread/images/row-header-bg.png
mobile/themes/core/gingerbread/images/scrubber-hdpi.png
mobile/themes/core/gingerbread/images/search-clear-30.png
mobile/themes/core/gingerbread/images/search-glass-30.png
mobile/themes/core/gingerbread/images/settings-default-hdpi.png
mobile/themes/core/gingerbread/images/stop-hdpi.png
mobile/themes/core/gingerbread/images/tab-active-hdpi.png
mobile/themes/core/gingerbread/images/tab-closed-hdpi.png
mobile/themes/core/gingerbread/images/tab-inactive-hdpi.png
mobile/themes/core/gingerbread/images/tab-reopen-hdpi.png
mobile/themes/core/gingerbread/images/tab-reopen-tablet-hdpi.png
mobile/themes/core/gingerbread/images/task-back-hdpi.png
mobile/themes/core/gingerbread/images/task-back-rtl-hdpi.png
mobile/themes/core/gingerbread/images/task-close-hdpi.png
mobile/themes/core/gingerbread/images/task-switch-hdpi.png
mobile/themes/core/gingerbread/images/textbox-bg.png
mobile/themes/core/gingerbread/images/throbber.png
mobile/themes/core/gingerbread/images/toggle-off.png
mobile/themes/core/gingerbread/images/toggle-on.png
mobile/themes/core/gingerbread/images/unlocked-hdpi.png
mobile/themes/core/gingerbread/images/unmute-hdpi.png
mobile/themes/core/gingerbread/images/urlbar-bg.png
mobile/themes/core/gingerbread/localePicker.css
mobile/themes/core/gingerbread/platform.css
mobile/themes/core/header.css
mobile/themes/core/honeycomb/browser.css
mobile/themes/core/honeycomb/defines.inc
mobile/themes/core/honeycomb/forms.css
mobile/themes/core/honeycomb/images/aboutBackground.jpg
mobile/themes/core/honeycomb/images/addons-default-hdpi.png
mobile/themes/core/honeycomb/images/alert-addons-30.png
mobile/themes/core/honeycomb/images/alert-downloads-30.png
mobile/themes/core/honeycomb/images/allpages-48.png
mobile/themes/core/honeycomb/images/appmenu-active-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-addons-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-addsearch-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-downloads-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-findinpage-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-more-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-preferences-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-saveas-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-share-hdpi.png
mobile/themes/core/honeycomb/images/appmenu-site-hdpi.png
mobile/themes/core/honeycomb/images/arrowbox-down.png
mobile/themes/core/honeycomb/images/arrowbox-horiz.png
mobile/themes/core/honeycomb/images/arrowbox-up.png
mobile/themes/core/honeycomb/images/arrowdown-16.png
mobile/themes/core/honeycomb/images/arrowdowndark-16.png
mobile/themes/core/honeycomb/images/arrowleft-16.png
mobile/themes/core/honeycomb/images/arrowleftdark-16.png
mobile/themes/core/honeycomb/images/arrowright-16.png
mobile/themes/core/honeycomb/images/arrowrightdark-16.png
mobile/themes/core/honeycomb/images/arrowup-16.png
mobile/themes/core/honeycomb/images/arrowupdark-16.png
mobile/themes/core/honeycomb/images/autocomplete-all-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-all-selected-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-bookmarked-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-bookmarked-selected-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-desktop-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-desktop-selected-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-history-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-history-selected-hdpi.png
mobile/themes/core/honeycomb/images/autocomplete-search-hdpi.png
mobile/themes/core/honeycomb/images/back-default-hdpi.png
mobile/themes/core/honeycomb/images/bookmark-default-hdpi.png
mobile/themes/core/honeycomb/images/bookmark-starred-hdpi.png
mobile/themes/core/honeycomb/images/bookmarks-48.png
mobile/themes/core/honeycomb/images/browseaddons-bg.jpg
mobile/themes/core/honeycomb/images/button-bg.png
mobile/themes/core/honeycomb/images/check-selected-hdpi.png
mobile/themes/core/honeycomb/images/check-selected-tap-hdpi.png
mobile/themes/core/honeycomb/images/check-unselected-hdpi.png
mobile/themes/core/honeycomb/images/check-unselected-tap-hdpi.png
mobile/themes/core/honeycomb/images/close-active-hdpi.png
mobile/themes/core/honeycomb/images/close-active-tablet-hdpi.png
mobile/themes/core/honeycomb/images/close-background-hdpi-rtl.png
mobile/themes/core/honeycomb/images/close-background-hdpi.png
mobile/themes/core/honeycomb/images/close-default-hdpi.png
mobile/themes/core/honeycomb/images/close-default-tablet-hdpi.png
mobile/themes/core/honeycomb/images/close-inactive-tab-hdpi.png
mobile/themes/core/honeycomb/images/close-inactive-tab-tablet-hdpi.png
mobile/themes/core/honeycomb/images/console-default-hdpi.png
mobile/themes/core/honeycomb/images/downloads-default-hdpi.png
mobile/themes/core/honeycomb/images/dropmarker-hdpi.png
mobile/themes/core/honeycomb/images/errorpage-larry-black.png
mobile/themes/core/honeycomb/images/errorpage-larry-white.png
mobile/themes/core/honeycomb/images/errorpage-warning.png
mobile/themes/core/honeycomb/images/favicon-default-32.png
mobile/themes/core/honeycomb/images/folder-32.png
mobile/themes/core/honeycomb/images/forward-default-hdpi.png
mobile/themes/core/honeycomb/images/history-48.png
mobile/themes/core/honeycomb/images/identity-default-hdpi.png
mobile/themes/core/honeycomb/images/identity-ev-hdpi.png
mobile/themes/core/honeycomb/images/identity-ssl-hdpi.png
mobile/themes/core/honeycomb/images/locked-hdpi.png
mobile/themes/core/honeycomb/images/menu-hdpi.png
mobile/themes/core/honeycomb/images/menu-top-insideglow-green.png
mobile/themes/core/honeycomb/images/menu-top-insideglow-grey.png
mobile/themes/core/honeycomb/images/menu-top-insideglow.png
mobile/themes/core/honeycomb/images/mute-hdpi.png
mobile/themes/core/honeycomb/images/navigation-magnifier-30.png
mobile/themes/core/honeycomb/images/newtab-default-hdpi.png
mobile/themes/core/honeycomb/images/newtab-default-tablet-hdpi.png
mobile/themes/core/honeycomb/images/newtab-tabmenu-tablet-hdpi.png
mobile/themes/core/honeycomb/images/next-disabled-hdpi.png
mobile/themes/core/honeycomb/images/next-hdpi.png
mobile/themes/core/honeycomb/images/panelrow-active-hdpi.png
mobile/themes/core/honeycomb/images/panelrow-default-hdpi.png
mobile/themes/core/honeycomb/images/panelrow-selected-hdpi.png
mobile/themes/core/honeycomb/images/pause-hdpi.png
mobile/themes/core/honeycomb/images/play-hdpi.png
mobile/themes/core/honeycomb/images/popup-bg-hdpi.png
mobile/themes/core/honeycomb/images/popup-selected-item-hdpi.png
mobile/themes/core/honeycomb/images/preferences-default-hdpi.png
mobile/themes/core/honeycomb/images/previous-disabled-hdpi.png
mobile/themes/core/honeycomb/images/previous-hdpi.png
mobile/themes/core/honeycomb/images/reload-hdpi.png
mobile/themes/core/honeycomb/images/remotetabs-32.png
mobile/themes/core/honeycomb/images/remotetabs-48.png
mobile/themes/core/honeycomb/images/row-header-bg.png
mobile/themes/core/honeycomb/images/scrubber-hdpi.png
mobile/themes/core/honeycomb/images/search-clear-30.png
mobile/themes/core/honeycomb/images/search-glass-30.png
mobile/themes/core/honeycomb/images/settings-default-hdpi.png
mobile/themes/core/honeycomb/images/sidebarbutton-active-hdpi.png
mobile/themes/core/honeycomb/images/stop-hdpi.png
mobile/themes/core/honeycomb/images/tab-active-hdpi.png
mobile/themes/core/honeycomb/images/tab-closed-hdpi.png
mobile/themes/core/honeycomb/images/tab-inactive-hdpi.png
mobile/themes/core/honeycomb/images/tab-reopen-hdpi.png
mobile/themes/core/honeycomb/images/tab-reopen-tablet-hdpi.png
mobile/themes/core/honeycomb/images/tabs-default-bg-rtl.png
mobile/themes/core/honeycomb/images/tabs-default-bg.png
mobile/themes/core/honeycomb/images/tabs-hdpi.png
mobile/themes/core/honeycomb/images/tabs-selected-bg-rtl.png
mobile/themes/core/honeycomb/images/tabs-selected-bg.png
mobile/themes/core/honeycomb/images/task-back-hdpi.png
mobile/themes/core/honeycomb/images/task-back-rtl-hdpi.png
mobile/themes/core/honeycomb/images/task-close-hdpi.png
mobile/themes/core/honeycomb/images/task-switch-hdpi.png
mobile/themes/core/honeycomb/images/textbox-bg.png
mobile/themes/core/honeycomb/images/throbber.png
mobile/themes/core/honeycomb/images/toggle-off.png
mobile/themes/core/honeycomb/images/toggle-on.png
mobile/themes/core/honeycomb/images/unlocked-hdpi.png
mobile/themes/core/honeycomb/images/unmute-hdpi.png
mobile/themes/core/honeycomb/images/urlbar-border-bottom-active.png
mobile/themes/core/honeycomb/images/urlbar-border-bottom.png
mobile/themes/core/honeycomb/images/urlbar-border-side-active.png
mobile/themes/core/honeycomb/images/urlbar-border-side.png
mobile/themes/core/honeycomb/platform.css
mobile/themes/core/images/aboutBackground.jpg
mobile/themes/core/images/addons-32.png
mobile/themes/core/images/addons-default-hdpi.png
mobile/themes/core/images/alert-addons-30.png
mobile/themes/core/images/alert-downloads-30.png
mobile/themes/core/images/allpages-48.png
mobile/themes/core/images/appmenu-active-hdpi.png
mobile/themes/core/images/appmenu-addons-hdpi.png
mobile/themes/core/images/appmenu-downloads-hdpi.png
mobile/themes/core/images/appmenu-findinpage-hdpi.png
mobile/themes/core/images/appmenu-more-hdpi.png
mobile/themes/core/images/appmenu-preferences-hdpi.png
mobile/themes/core/images/appmenu-share-hdpi.png
mobile/themes/core/images/appmenu-site-hdpi.png
mobile/themes/core/images/arrowbox-down.png
mobile/themes/core/images/arrowbox-horiz.png
mobile/themes/core/images/arrowbox-up.png
mobile/themes/core/images/arrowdown-16.png
mobile/themes/core/images/arrowdowndark-16.png
mobile/themes/core/images/arrowleft-16.png
mobile/themes/core/images/arrowleftdark-16.png
mobile/themes/core/images/arrowright-16.png
mobile/themes/core/images/arrowrightdark-16.png
mobile/themes/core/images/arrowup-16.png
mobile/themes/core/images/arrowupdark-16.png
mobile/themes/core/images/aurora-lightbox-bg.jpg
mobile/themes/core/images/aurora-lightbox-close.png
mobile/themes/core/images/aurora-lightbox-logo.png
mobile/themes/core/images/autocomplete-bookmarked-hdpi.png
mobile/themes/core/images/autocomplete-desktop-hdpi.png
mobile/themes/core/images/autocomplete-search-hdpi.png
mobile/themes/core/images/back-default-hdpi.png
mobile/themes/core/images/bookmark-default-hdpi.png
mobile/themes/core/images/bookmark-starred-hdpi.png
mobile/themes/core/images/bookmarks-48.png
mobile/themes/core/images/browseaddons-bg.jpg
mobile/themes/core/images/button-bg.png
mobile/themes/core/images/check-30.png
mobile/themes/core/images/check-selected-30.png
mobile/themes/core/images/check-unselected-30.png
mobile/themes/core/images/checkmark-hdpi.png
mobile/themes/core/images/close-active-hdpi.png
mobile/themes/core/images/close-active-tablet-hdpi.png
mobile/themes/core/images/close-background-hdpi-rtl.png
mobile/themes/core/images/close-background-hdpi.png
mobile/themes/core/images/close-default-hdpi.png
mobile/themes/core/images/close-default-tablet-hdpi.png
mobile/themes/core/images/close-inactive-tab-hdpi.png
mobile/themes/core/images/close-inactive-tab-tablet-hdpi.png
mobile/themes/core/images/console-default-hdpi.png
mobile/themes/core/images/downloads-default-hdpi.png
mobile/themes/core/images/dropmarker-hdpi.png
mobile/themes/core/images/endcap-active-bg.png
mobile/themes/core/images/endcap-default-bg.png
mobile/themes/core/images/endcap-ev-active-bg.png
mobile/themes/core/images/endcap-ev-default-bg.png
mobile/themes/core/images/endcap-ssl-active-bg.png
mobile/themes/core/images/endcap-ssl-default-bg.png
mobile/themes/core/images/errorpage-larry-black.png
mobile/themes/core/images/errorpage-larry-white.png
mobile/themes/core/images/errorpage-warning.png
mobile/themes/core/images/favicon-default-32.png
mobile/themes/core/images/folder-32.png
mobile/themes/core/images/forward-default-hdpi.png
mobile/themes/core/images/handle-end.png
mobile/themes/core/images/handle-start.png
mobile/themes/core/images/history-48.png
mobile/themes/core/images/homescreen-blank-hdpi.png
mobile/themes/core/images/homescreen-default-hdpi.png
mobile/themes/core/images/identity-default-hdpi.png
mobile/themes/core/images/identity-ev-hdpi.png
mobile/themes/core/images/identity-ssl-hdpi.png
mobile/themes/core/images/locked-hdpi.png
mobile/themes/core/images/menu-hdpi.png
mobile/themes/core/images/mozilla-32.png
mobile/themes/core/images/mute-hdpi.png
mobile/themes/core/images/navigation-magnifier-30.png
mobile/themes/core/images/newtab-default-hdpi.png
mobile/themes/core/images/newtab-default-tablet-hdpi.png
mobile/themes/core/images/next-disabled-hdpi.png
mobile/themes/core/images/next-hdpi.png
mobile/themes/core/images/panelrow-active-hdpi.png
mobile/themes/core/images/panelrow-default-hdpi.png
mobile/themes/core/images/panelrow-selected-hdpi.png
mobile/themes/core/images/pause-hdpi.png
mobile/themes/core/images/play-hdpi.png
mobile/themes/core/images/popup-bg-hdpi.png
mobile/themes/core/images/popup-selected-item-hdpi.png
mobile/themes/core/images/preferences-default-hdpi.png
mobile/themes/core/images/previous-disabled-hdpi.png
mobile/themes/core/images/previous-hdpi.png
mobile/themes/core/images/ratings-18.png
mobile/themes/core/images/reload-hdpi.png
mobile/themes/core/images/remotetabs-32.png
mobile/themes/core/images/remotetabs-48.png
mobile/themes/core/images/row-header-bg.png
mobile/themes/core/images/scrubber-hdpi.png
mobile/themes/core/images/search-clear-30.png
mobile/themes/core/images/search-glass-30.png
mobile/themes/core/images/section-collapsed-16.png
mobile/themes/core/images/section-expanded-16.png
mobile/themes/core/images/settings-default-hdpi.png
mobile/themes/core/images/sidebarbutton-active-hdpi.png
mobile/themes/core/images/stop-hdpi.png
mobile/themes/core/images/tab-active-hdpi.png
mobile/themes/core/images/tab-closed-hdpi.png
mobile/themes/core/images/tab-inactive-hdpi.png
mobile/themes/core/images/tab-reopen-hdpi.png
mobile/themes/core/images/tab-reopen-tablet-hdpi.png
mobile/themes/core/images/tabs-hdpi.png
mobile/themes/core/images/task-back-hdpi.png
mobile/themes/core/images/task-back-rtl-hdpi.png
mobile/themes/core/images/task-close-hdpi.png
mobile/themes/core/images/task-switch-hdpi.png
mobile/themes/core/images/textbox-bg.png
mobile/themes/core/images/throbber.png
mobile/themes/core/images/toggle-off.png
mobile/themes/core/images/toggle-on.png
mobile/themes/core/images/unlocked-hdpi.png
mobile/themes/core/images/unmute-hdpi.png
mobile/themes/core/jar.mn
mobile/themes/core/localePicker.css
mobile/themes/core/netError.css
mobile/themes/core/notification.css
mobile/themes/core/platform.css
mobile/themes/core/tablet.css
mobile/themes/core/touchcontrols.css
mobile/xul/app/mobile.js
mobile/xul/app/nsBrowserApp.cpp
mobile/xul/chrome/content/BookmarkHelper.js
mobile/xul/chrome/content/BookmarkPopup.js
mobile/xul/chrome/content/ContextCommands.js
mobile/xul/chrome/content/TabsPopup.js
mobile/xul/chrome/content/Util.js
mobile/xul/chrome/content/WebappsUI.js
mobile/xul/chrome/content/aboutHome.xhtml
mobile/xul/chrome/content/bindings/arrowbox.xml
mobile/xul/chrome/content/browser-scripts.js
mobile/xul/chrome/content/browser-ui.js
mobile/xul/chrome/content/browser.js
mobile/xul/chrome/content/browser.xul
mobile/xul/chrome/content/common-ui.js
mobile/xul/chrome/content/content.js
mobile/xul/chrome/content/downloads.js
mobile/xul/chrome/content/extensions.js
mobile/xul/chrome/content/forms.js
mobile/xul/chrome/content/localePicker.js
mobile/xul/chrome/content/localePicker.xul
mobile/xul/chrome/content/preferences.js
mobile/xul/chrome/content/sync.js
mobile/xul/chrome/content/tabs.xml
mobile/xul/chrome/content/webapps.xul
mobile/xul/chrome/jar.mn
mobile/xul/chrome/tests/Makefile.in
mobile/xul/chrome/tests/browser_awesomescreen.js
mobile/xul/components/Makefile.in
mobile/xul/components/MobileComponents.manifest
mobile/xul/components/SessionStore.js
mobile/xul/confvars.sh
mobile/xul/installer/package-manifest.in
mobile/xul/locales/en-US/chrome/aboutHome.dtd
mobile/xul/locales/en-US/chrome/sync.dtd
mobile/xul/locales/en-US/chrome/webapps.dtd
mobile/xul/modules/LocaleRepository.jsm
mobile/xul/modules/contacts.jsm
mobile/xul/themes/core/aboutHome.css
mobile/xul/themes/core/browser.css
mobile/xul/themes/core/defines.inc
mobile/xul/themes/core/gingerbread/browser.css
mobile/xul/themes/core/gingerbread/defines.inc
mobile/xul/themes/core/gingerbread/images/throbber.png
mobile/xul/themes/core/honeycomb/browser.css
mobile/xul/themes/core/honeycomb/defines.inc
mobile/xul/themes/core/honeycomb/images/addons-default-hdpi.png
mobile/xul/themes/core/honeycomb/images/check-selected-hdpi.png
mobile/xul/themes/core/honeycomb/images/check-unselected-hdpi.png
mobile/xul/themes/core/honeycomb/images/downloads-default-hdpi.png
mobile/xul/themes/core/honeycomb/images/dropmarker-hdpi.png
mobile/xul/themes/core/honeycomb/images/forward-default-hdpi.png
mobile/xul/themes/core/honeycomb/images/menu-hdpi.png
mobile/xul/themes/core/honeycomb/images/navigation-magnifier-30.png
mobile/xul/themes/core/honeycomb/images/preferences-default-hdpi.png
mobile/xul/themes/core/honeycomb/images/reload-hdpi.png
mobile/xul/themes/core/honeycomb/images/stop-hdpi.png
mobile/xul/themes/core/honeycomb/images/throbber.png
mobile/xul/themes/core/honeycomb/images/urlbar-border-side.png
mobile/xul/themes/core/honeycomb/platform.css
mobile/xul/themes/core/images/throbber.png
mobile/xul/themes/core/jar.mn
mobile/xul/themes/core/tablet.css
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
parser/html/nsHtml5Parser.cpp
parser/html/nsHtml5StreamParser.cpp
parser/html/nsHtml5StreamParser.h
parser/html/nsHtml5TreeOpExecutor.cpp
parser/html/nsHtml5TreeOpExecutor.h
parser/htmlparser/public/nsIParser.h
testing/testsuite-targets.mk
toolkit/components/autocomplete/nsAutoCompleteController.cpp
toolkit/components/places/nsNavBookmarks.cpp
toolkit/components/places/nsNavBookmarks.h
toolkit/library/libxul-config.mk
toolkit/library/libxul-rules.mk
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/installer/packager.mk
toolkit/xre/nsNativeAppSupportQt.cpp
widget/public/LookAndFeel.h
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
widget/src/android/nsLookAndFeel.cpp
widget/src/android/nsWindow.cpp
widget/src/gtk2/nsLookAndFeel.cpp
widget/src/xpwidgets/nsXPLookAndFeel.cpp
xpcom/base/nsConsoleService.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/glue/nsISupportsImpl.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -161,17 +161,21 @@ EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BU
 endif
 
 SYMBOL_INDEX_NAME = \
   $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
 
 buildsymbols:
 ifdef MOZ_CRASHREPORTER
 ifdef USE_ELF_HACK
-	$(MAKE) -C $(MOZ_BUILD_APP)/installer elfhack
+    ifeq (mobile,$(MOZ_BUILD_APP))
+		$(MAKE) -C mobile/xul/installer elfhack
+    else
+		$(MAKE) -C $(MOZ_BUILD_APP)/installer elfhack
+    endif
 endif
 	echo building symbol store
 	$(RM) -r $(DIST)/crashreporter-symbols
 	$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
 	OBJCOPY="$(OBJCOPY)" \
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
 	  $(MAKE_SYM_STORE_ARGS)                                          \
--- a/accessible/src/base/AccGroupInfo.cpp
+++ b/accessible/src/base/AccGroupInfo.cpp
@@ -45,16 +45,22 @@ AccGroupInfo::AccGroupInfo(nsAccessible*
   mPosInSet(0), mSetSize(0), mParent(nsnull)
 {
   MOZ_COUNT_CTOR(AccGroupInfo);
   nsAccessible* parent = aItem->Parent();
   if (!parent)
     return;
 
   PRInt32 indexInParent = aItem->IndexInParent();
+  PRInt32 siblingCount = parent->GetChildCount();
+  if (siblingCount < indexInParent) {
+    NS_ERROR("Wrong index in parent! Tree invalidation problem.");
+    return;
+  }
+
   PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(aItem);
 
   // Compute position in set.
   mPosInSet = 1;
   for (PRInt32 idx = indexInParent - 1; idx >=0 ; idx--) {
     nsAccessible* sibling = parent->GetChildAt(idx);
     PRUint32 siblingRole = sibling->Role();
 
@@ -90,17 +96,16 @@ AccGroupInfo::AccGroupInfo(nsAccessible*
     }
 
     mPosInSet++;
   }
 
   // Compute set size.
   mSetSize = mPosInSet;
 
-  PRInt32 siblingCount = parent->GetChildCount();
   for (PRInt32 idx = indexInParent + 1; idx < siblingCount; idx++) {
     nsAccessible* sibling = parent->GetChildAt(idx);
 
     PRUint32 siblingRole = sibling->Role();
 
     // If the sibling is separator then the group is ended.
     if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR)
       break;
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -587,29 +587,29 @@ NotificationController::CoalesceSelChang
   }
 
   // Unpack the packed selection change event because we've got one
   // more selection add/remove.
   if (aThisEvent->mEventType == nsIAccessibleEvent::EVENT_SELECTION) {
     if (aThisEvent->mPackedEvent) {
       aThisEvent->mPackedEvent->mEventType =
         aThisEvent->mPackedEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd ?
-          static_cast<PRUint32>(nsIAccessibleEvent::EVENT_SELECTION_ADD) :
-          static_cast<PRUint32>(nsIAccessibleEvent::EVENT_SELECTION_REMOVE);
+          nsIAccessibleEvent::EVENT_SELECTION_ADD :
+          nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
 
       aThisEvent->mPackedEvent->mEventRule =
         AccEvent::eCoalesceSelectionChange;
 
       aThisEvent->mPackedEvent = nsnull;
     }
 
     aThisEvent->mEventType =
       aThisEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd ?
-        static_cast<PRUint32>(nsIAccessibleEvent::EVENT_SELECTION_ADD) :
-        static_cast<PRUint32>(nsIAccessibleEvent::EVENT_SELECTION_REMOVE);
+        nsIAccessibleEvent::EVENT_SELECTION_ADD :
+        nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
 
     return;
   }
 
   // Convert into selection add since control has single selection but other
   // selection events for this control are queued.
   if (aTailEvent->mEventType == nsIAccessibleEvent::EVENT_SELECTION)
     aTailEvent->mEventType = nsIAccessibleEvent::EVENT_SELECTION_ADD;
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -435,26 +435,28 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
   },
   {
     "separator",
     nsIAccessibleRole::ROLE_SEPARATOR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
-    kNoReqStates
+    kNoReqStates,
+    eARIAOrientation
   },
   {
     "slider",
     nsIAccessibleRole::ROLE_SLIDER,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
+    eARIAOrientation,
     eARIAReadonly
   },
   {
     "spinbutton",
     nsIAccessibleRole::ROLE_SPINBUTTON,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
@@ -644,18 +646,18 @@ nsStateMapEntry nsARIAMap::gWAIStateMap[
                   0, states::MULTI_LINE, states::SINGLE_LINE, true),
 
   // eARIAMultiSelectable
   nsStateMapEntry(&nsGkAtoms::aria_multiselectable, kBoolType,
                   0, states::MULTISELECTABLE | states::EXTSELECTABLE),
 
   // eARIAOrientation
   nsStateMapEntry(&nsGkAtoms::aria_orientation, eUseFirstState,
-                  "vertical", states::VERTICAL,
-                  "horizontal", states::HORIZONTAL),
+                  "horizontal", states::HORIZONTAL,
+                  "vertical", states::VERTICAL),
 
   // eARIAPressed
   nsStateMapEntry(&nsGkAtoms::aria_pressed, kMixedType,
                   states::CHECKABLE, states::PRESSED),
 
   // eARIAReadonly
   nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
                   0, states::READONLY),
--- a/accessible/src/msaa/ia2AccessibleRelation.cpp
+++ b/accessible/src/msaa/ia2AccessibleRelation.cpp
@@ -186,17 +186,17 @@ ia2AccessibleRelation::get_nTargets(long
 
 STDMETHODIMP
 ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
 {
 __try {
   if (aTargetIndex < 0 || aTargetIndex >= mTargets.Length() || !aTarget)
     return E_INVALIDARG;
 
-  mTargets[aTargetIndex]->QueryInterface((const nsID&) IID_IUnknown, (void**) aTarget);
+  mTargets[aTargetIndex]->QueryNativeInterface(IID_IUnknown, (void**) aTarget);
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -284,25 +284,22 @@ STDMETHODIMP nsAccessibleWrap::get_accNa
   *pszName = NULL;
   nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_FAIL;
   nsAutoString name;
   nsresult rv = xpAccessible->GetName(name);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
-    
-  if (name.IsVoid()) {
-    // Valid return value for the name:
-    // The name was not provided, e.g. no alt attribute for an image.
-    // A screen reader may choose to invent its own accessible name, e.g. from
-    // an image src attribute.
-    // See nsHTMLImageAccessible::GetName()
-    return S_OK;
-  }
+
+  // The name was not provided, e.g. no alt attribute for an image. A screen
+  // reader may choose to invent its own accessible name, e.g. from an image src
+  // attribute. Refer to NS_OK_EMPTY_NAME return value.
+  if (name.IsVoid())
+    return S_FALSE;
 
   *pszName = ::SysAllocStringLen(name.get(), name.Length());
   if (!*pszName)
     return E_OUTOFMEMORY;
 
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
 
   return S_OK;
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -119,20 +119,26 @@
       testStates("aria_link_anchor", STATE_SELECTABLE);
 
       // some weak landmarks
       testStates("aria_main_link", STATE_LINKED);
       testStates("aria_navigation_link", STATE_LINKED);
       testStates("aria_main_anchor", STATE_SELECTABLE);
       testStates("aria_navigation_anchor", STATE_SELECTABLE);
 
-      // scrollbar
-      testStates("aria_scrollbar", 0, EXT_STATE_VERTICAL);
+      // aria-orientation (applied to scrollbar, separator, slider)
+      testStates("aria_scrollbar", 0, EXT_STATE_HORIZONTAL);
       testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL);
       testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL);
+      testStates("aria_separator", 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_hseparator", 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_vseparator", 0, EXT_STATE_VERTICAL);
+      testStates("aria_slider", 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_hslider", 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_vslider", 0, EXT_STATE_VERTICAL);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
@@ -155,16 +161,21 @@
      title="Unify ARIA state attributes mapping rules">
     Mozilla Bug 499653
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
      title="aria-autocomplete not supported on standard form text input controls">
     Mozilla Bug 681674
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
+     title="aria-orientation should be applied to separator and slider roles">
+    Mozilla Bug 681674
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
   <div id="textbox_autocomplete_both" role="textbox" aria-autocomplete="both"></div>
@@ -222,14 +233,20 @@
   <a id="aria_main_link" role="main" href="foo">main</a>
   <a id="aria_navigation_link" role="navigation" href="foo">nav</a>
   
   <!-- landmarks: anchors -->
   <a id="aria_application_anchor" role="application" name="app_anchor">app</a>
   <a id="aria_main_anchor" role="main" name="main_anchor">main</a>
   <a id="aria_navigation_anchor" role="navigation" name="nav_anchor">nav</a>
 
-  <!-- scrollbar -->
-  <div id="aria_scrollbar" role="scrollbar">scrollbar</a>
-  <div id="aria_hscrollbar" role="scrollbar" aria-orientation="horizontal">horizontal scrollbar</a>
-  <div id="aria_vscrollbar" role="scrollbar" aria-orientation="vertical">vertical scrollbar</a>
+  <!-- aria-orientation -->
+  <div id="aria_scrollbar" role="scrollbar">scrollbar</div>
+  <div id="aria_hscrollbar" role="scrollbar" aria-orientation="horizontal">horizontal scrollbar</div>
+  <div id="aria_vscrollbar" role="scrollbar" aria-orientation="vertical">vertical scrollbar</div>
+  <div id="aria_separator" role="separator">separator</div>
+  <div id="aria_hseparator" role="separator" aria-orientation="horizontal">horizontal separator</div>
+  <div id="aria_vseparator" role="separator" aria-orientation="vertical">vertical separator</div>
+  <div id="aria_slider" role="slider">slider</div>
+  <div id="aria_hslider" role="slider" aria-orientation="horizontal">horizontal slider</div>
+  <div id="aria_vslider" role="slider" aria-orientation="vertical">vertical slider</div>
 </body>
 </html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -49,19 +49,18 @@
 #endif
 
 pref("browser.chromeURL","chrome://browser/content/");
 pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
 
 // Enables some extra Extension System Logging (can reduce performance)
 pref("extensions.logging.enabled", false);
 
-// Enables strict compatibility. To be toggled in bug 698653, to make addons
-// compatibile by default.
-pref("extensions.strictCompatibility", true);
+// Disables strict compatibility, making addons compatible-by-default.
+pref("extensions.strictCompatibility", false);
 
 // Specifies a minimum maxVersion an addon needs to say it's compatible with
 // for it to be compatible by default.
 pref("extensions.minCompatibleAppVersion", "4.0");
 
 // Preferences for AMO integration
 pref("extensions.getAddons.cache.enabled", true);
 pref("extensions.getAddons.maxResults", 15);
@@ -1014,16 +1013,19 @@ pref("devtools.inspector.htmlHeight", 11
 pref("devtools.styleinspector.enabled", true);
 
 // Enable the rules view
 pref("devtools.ruleview.enabled", true);
 
 // Enable the Scratchpad tool.
 pref("devtools.scratchpad.enabled", true);
 
+// Enable the Style Editor.
+pref("devtools.styleeditor.enabled", true);
+
 // Enable tools for Chrome development.
 pref("devtools.chrome.enabled", false);
 
 // Disable the GCLI enhanced command line.
 pref("devtools.gcli.enable", false);
 
 // The last Web Console height. This is initially 0 which means that the Web
 // Console will use the default height next time it shows.
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -187,16 +187,21 @@
                     type="checkbox"
                     command="Tools:Inspect"
                     key="key_inspect"/>
           <menuitem id="appmenu_scratchpad"
                     hidden="true"
                     label="&scratchpad.label;"
                     key="key_scratchpad"
                     command="Tools:Scratchpad"/>
+          <menuitem id="appmenu_styleeditor"
+                    hidden="true"
+                    label="&styleeditor.label;"
+                    key="key_styleeditor"
+                    command="Tools:StyleEditor"/>
           <menuitem id="appmenu_pageSource"
                     label="&viewPageSourceCmd.label;"
                     command="View:PageSource"
                     key="key_viewSource"/>
           <menuitem id="appmenu_errorConsole"
                     hidden="true"
                     label="&errorConsoleCmd.label;"
                     key="key_errorConsole"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -545,16 +545,22 @@
                             key="key_inspect"
                             command="Tools:Inspect"/>
                   <menuitem id="menu_scratchpad"
                             hidden="true"
                             label="&scratchpad.label;"
                             accesskey="&scratchpad.accesskey;"
                             key="key_scratchpad"
                             command="Tools:Scratchpad"/>
+                  <menuitem id="menu_styleeditor"
+                            hidden="true"
+                            label="&styleeditor.label;"
+                            accesskey="&styleeditor.accesskey;"
+                            key="key_styleeditor"
+                            command="Tools:StyleEditor"/>
                   <menuitem id="menu_pageSource"
                             accesskey="&pageSourceCmd.accesskey;"
                             label="&pageSourceCmd.label;"
                             key="key_viewSource"
                             command="View:PageSource"/>
                   <menuitem id="javascriptConsole"
                             hidden="true"
                             label="&errorConsoleCmd.label;"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -121,16 +121,17 @@
     <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
     <command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
     <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true"/>
+    <command id="Tools:StyleEditor" oncommand="StyleEditor.openChrome();" disabled="true"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing" oncommand="gPrivateBrowsingUI.toggleMode();"/>
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
     <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
   </commandset>
@@ -239,16 +240,18 @@
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #endif
     <key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
     <key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
     <key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
     <key id="key_inspect" key="&inspectMenu.commandkey;" command="Tools:Inspect" modifiers="accel,shift"/>
     <key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift"
          keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/>
+    <key id="key_styleeditor" keycode="&styleeditor.keycode;" modifiers="shift"
+         keytext="&styleeditor.keytext;" command="Tools:StyleEditor"/>
     <key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile"  modifiers="accel"/>
     <key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>
     <key id="printKb" key="&printCmd.commandkey;" command="cmd_print"  modifiers="accel"/>
     <key id="key_close" key="&closeCmd.key;" command="cmd_close" modifiers="accel"/>
     <key id="key_closeWindow" key="&closeCmd.key;" command="cmd_closeWindow" modifiers="accel,shift"/>
     <key id="key_undo"
          key="&undoCmd.key;"
          modifiers="accel"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1716,16 +1716,26 @@ function delayedStartup(isLoadingBlank, 
   if (scratchpadEnabled) {
     document.getElementById("menu_scratchpad").hidden = false;
     document.getElementById("Tools:Scratchpad").removeAttribute("disabled");
 #ifdef MENUBAR_CAN_AUTOHIDE
     document.getElementById("appmenu_scratchpad").hidden = false;
 #endif
   }
 
+  // Enable Style Editor?
+  let styleEditorEnabled = gPrefService.getBoolPref(StyleEditor.prefEnabledName);
+  if (styleEditorEnabled) {
+    document.getElementById("menu_styleeditor").hidden = false;
+    document.getElementById("Tools:StyleEditor").removeAttribute("disabled");
+#ifdef MENUBAR_CAN_AUTOHIDE
+    document.getElementById("appmenu_styleeditor").hidden = false;
+#endif
+  }
+
 #ifdef MENUBAR_CAN_AUTOHIDE
   // If the user (or the locale) hasn't enabled the top-level "Character
   // Encoding" menu via the "browser.menu.showCharacterEncoding" preference,
   // hide it.
   if ("true" != gPrefService.getComplexValue("browser.menu.showCharacterEncoding",
                                              Ci.nsIPrefLocalizedString).data)
     document.getElementById("appmenu_charsetMenu").hidden = true;
 #endif
@@ -8964,16 +8974,44 @@ var Scratchpad = {
 };
 
 XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() {
   let tmp = {};
   Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", tmp);
   return tmp.ScratchpadManager;
 });
 
+var StyleEditor = {
+  prefEnabledName: "devtools.styleeditor.enabled",
+  openChrome: function SE_openChrome()
+  {
+    const CHROME_URL = "chrome://browser/content/styleeditor.xul";
+    const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
+    const CHROME_WINDOW_FLAGS = "chrome,centerscreen,resizable,dialog=no";
+
+    // focus currently open Style Editor window for this document, if any
+    let contentWindow = gBrowser.selectedBrowser.contentWindow;
+    let contentWindowID = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
+    let enumerator = Services.wm.getEnumerator(CHROME_WINDOW_TYPE);
+    while (enumerator.hasMoreElements()) {
+      var win = enumerator.getNext();
+      if (win.styleEditorChrome.contentWindowID == contentWindowID) {
+        win.focus();
+        return win;
+      }
+    }
+
+    let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
+                                              CHROME_WINDOW_FLAGS,
+                                              contentWindow);
+    chromeWindow.focus();
+    return chromeWindow;
+  }
+};
 
 XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
 #ifdef XP_WIN
   // Only show resizers on Windows 2000 and XP
   let sysInfo = Components.classes["@mozilla.org/system-info;1"]
                           .getService(Components.interfaces.nsIPropertyBag2);
   return parseFloat(sysInfo.getProperty("version")) < 6;
 #else
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -31,19 +31,19 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
+let Cc = Components.classes;
+let Ci = Components.interfaces;
+let Cu = Components.utils;
 
 // Bug 671101 - directly using webNavigation in this context
 // causes docshells to leak
 __defineGetter__("webNavigation", function () {
   return docShell.QueryInterface(Ci.nsIWebNavigation);
 });
 
 addMessageListener("WebNavigation:LoadURI", function (message) {
--- a/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
+++ b/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
@@ -255,20 +255,20 @@ var gTests = [
         });
     }
   },
 ];
 
 function nextTest() {
   if (gTests.length) {
     var test = gTests.shift();
-    info("Start of test: " + test.desc);
-    test.run();
-
-    waitForFocus(nextTest);
+    waitForFocus(function() {
+      info("Start of test: " + test.desc);
+      test.run();
+    });
   }
   else {
     // Collapse the personal toolbar if needed.
     if (wasCollapsed)
       setToolbarVisibility(toolbar, false);
     finish();
   }
 }
@@ -278,11 +278,11 @@ let wasCollapsed = toolbar.collapsed;
 
 function test() {
   waitForExplicitFinish();
 
   // Uncollapse the personal toolbar if needed.
   if (wasCollapsed)
     setToolbarVisibility(toolbar, true);
 
-  waitForFocus(nextTest);
+  nextTest();
 }
 
--- a/browser/components/tabview/content.js
+++ b/browser/components/tabview/content.js
@@ -31,17 +31,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 ***** */
 
 "use strict";
 
-const Cu = Components.utils;
+let Cu = Components.utils;
 
 Cu.import("resource:///modules/tabview/utils.jsm");
 
 // Bug 671101 - directly using webProgress in this context
 // causes docShells to leak
 __defineGetter__("webProgress", function () {
   let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
   return ifaceReq.getInterface(Ci.nsIWebProgress);
--- a/browser/devtools/Makefile.in
+++ b/browser/devtools/Makefile.in
@@ -45,14 +45,15 @@ VPATH   = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/config.mk
 
 DIRS = \
   highlighter \
   webconsole \
   sourceeditor \
+  styleeditor \
   styleinspector \
   scratchpad \
   shared \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -1,11 +1,15 @@
 browser.jar:
 *   content/browser/inspector.html                (highlighter/inspector.html)
     content/browser/NetworkPanel.xhtml            (webconsole/NetworkPanel.xhtml)
 *   content/browser/scratchpad.xul                (scratchpad/scratchpad.xul)
 *   content/browser/scratchpad.js                 (scratchpad/scratchpad.js)
+*   content/browser/styleeditor.xul               (styleeditor/styleeditor.xul)
+    content/browser/splitview.css                 (styleeditor/splitview.css)
+    content/browser/styleeditor.css               (styleeditor/styleeditor.css)
     content/browser/devtools/csshtmltree.xul      (styleinspector/csshtmltree.xul)
     content/browser/devtools/cssruleview.xul      (styleinspector/cssruleview.xul)
     content/browser/devtools/styleinspector.css   (styleinspector/styleinspector.css)
     content/browser/orion.js                      (sourceeditor/orion/orion.js)
     content/browser/orion.css                     (sourceeditor/orion/orion.css)
     content/browser/orion-mozilla.css             (sourceeditor/orion/mozilla.css)
+
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -486,20 +486,22 @@ var Scratchpad = {
 
     return propPanel;
   },
 
   // Menu Operations
 
   /**
    * Open a new Scratchpad window.
+   *
+   * @return nsIWindow
    */
   openScratchpad: function SP_openScratchpad()
   {
-    ScratchpadManager.openScratchpad();
+    return ScratchpadManager.openScratchpad();
   },
 
   /**
    * Export the textbox content to a file.
    *
    * @param nsILocalFile aFile
    *        The file where you want to save the textbox content.
    * @param boolean aNoConfirmation
@@ -763,16 +765,18 @@ var Scratchpad = {
     this.editor.setCaretOffset(this.editor.getCharCount());
     
     if (this.filename && !this.saved) {
       this.onTextChanged();
     }
     else if (this.filename && this.saved) {
       this.onTextSaved();
     }
+
+    this._triggerObservers("Ready");
   },
 
   /**
    * Insert text at the current caret location.
    *
    * @param string aText
    *        The text you want to insert.
    */
@@ -872,16 +876,78 @@ var Scratchpad = {
     }
 
     this.resetContext();
     this.editor.removeEventListener(SourceEditor.EVENTS.CONTEXT_MENU,
                                     this.onContextMenu);
     this.editor.destroy();
     this.editor = null;
   },
+
+  _observers: [],
+
+  /**
+   * Add an observer for Scratchpad events.
+   *
+   * The observer implements IScratchpadObserver := {
+   *   onReady:      Called when the Scratchpad and its SourceEditor are ready.
+   *                 Arguments: (Scratchpad aScratchpad)
+   * }
+   *
+   * All observer handlers are optional.
+   *
+   * @param IScratchpadObserver aObserver
+   * @see removeObserver
+   */
+  addObserver: function SP_addObserver(aObserver)
+  {
+    this._observers.push(aObserver);
+  },
+
+  /**
+   * Remove an observer for Scratchpad events.
+   *
+   * @param IScratchpadObserver aObserver
+   * @see addObserver
+   */
+  removeObserver: function SP_removeObserver(aObserver)
+  {
+    let index = this._observers.indexOf(aObserver);
+    if (index != -1) {
+      this._observers.splice(index, 1);
+    }
+  },
+
+  /**
+   * Trigger named handlers in Scratchpad observers.
+   *
+   * @param string aName
+   *        Name of the handler to trigger.
+   * @param Array aArgs
+   *        Optional array of arguments to pass to the observer(s).
+   * @see addObserver
+   */
+  _triggerObservers: function SP_triggerObservers(aName, aArgs)
+  {
+    // insert this Scratchpad instance as the first argument
+    if (!aArgs) {
+      aArgs = [this];
+    } else {
+      aArgs.unshift(this);
+    }
+
+    // trigger all observers that implement this named handler
+    for (let i = 0; i < this._observers.length; ++i) {
+      let observer = this._observers[i];
+      let handler = observer["on" + aName];
+      if (handler) {
+        handler.apply(observer, aArgs);
+      }
+    }
+  }
 };
 
 XPCOMUtils.defineLazyGetter(Scratchpad, "strings", function () {
   return Services.strings.createBundle(SCRATCHPAD_L10N);
 });
 
 addEventListener("DOMContentLoaded", Scratchpad.onLoad.bind(Scratchpad), false);
 addEventListener("unload", Scratchpad.onUnload.bind(Scratchpad), false);
--- a/browser/devtools/scratchpad/test/Makefile.in
+++ b/browser/devtools/scratchpad/test/Makefile.in
@@ -53,11 +53,12 @@ include $(topsrcdir)/config/rules.mk
 		browser_scratchpad_ui.js \
 		browser_scratchpad_bug_646070_chrome_context_pref.js \
 		browser_scratchpad_bug_660560_tab.js \
 		browser_scratchpad_open.js \
 		browser_scratchpad_restore.js \
 		browser_scratchpad_bug_679467_falsy.js \
 		browser_scratchpad_bug_699130_edit_ui_updates.js \
 		browser_scratchpad_bug_669612_unsaved.js \
+		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_646070_chrome_context_pref.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_646070_chrome_context_pref.js
@@ -1,15 +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/ */
 
-// Reference to the Scratchpad chrome window object.
-let gScratchpadWindow;
-
 let gOldPref;
 let DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
 
 function test()
 {
   waitForExplicitFinish();
 
   gOldPref = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
@@ -50,13 +47,10 @@ function runTests()
   let chromeContextCommand = gScratchpadWindow.document.
                             getElementById("sp-cmd-browserContext");
   ok(chromeContextCommand, "Chrome context command element exists");
   ok(!chromeContextCommand.hasAttribute("disabled"),
      "Chrome context command is disabled");
 
   Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, gOldPref);
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_660560_tab.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_660560_tab.js
@@ -1,41 +1,47 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Reference to the Scratchpad chrome window object.
-let gScratchpadWindow;
+var ScratchpadManager = Scratchpad.ScratchpadManager;
 
 function test()
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+  gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
 
     ok(window.Scratchpad, "Scratchpad variable exists");
 
     Services.prefs.setIntPref("devtools.editor.tabsize", 5);
 
     gScratchpadWindow = Scratchpad.openScratchpad();
-    gScratchpadWindow.addEventListener("load", runTests, false);
+    gScratchpadWindow.addEventListener("load", function onScratchpadLoad() {
+      gScratchpadWindow.removeEventListener("load", onScratchpadLoad, false);
+
+      gScratchpadWindow.Scratchpad.addObserver({
+        onReady: runTests
+      });
+    }, false);
   }, true);
 
   content.location = "data:text/html,Scratchpad test for the Tab key, bug 660560";
 }
 
 function runTests()
 {
-  gScratchpadWindow.removeEventListener("load", arguments.callee, false);
-
   let sp = gScratchpadWindow.Scratchpad;
   ok(sp, "Scratchpad object exists in new window");
 
+  is(this.onReady, runTests, "the handler runs in the context of the observer");
+  sp.removeObserver(this);
+
   ok(sp.editor.hasFocus(), "the editor has focus");
 
   sp.setText("window.foo;");
   sp.editor.setCaretOffset(0);
 
   EventUtils.synthesizeKey("VK_TAB", {}, gScratchpadWindow);
 
   is(sp.getText(), "     window.foo;", "Tab key added 5 spaces");
@@ -58,36 +64,37 @@ function runTests()
   is(sp.getText(), "     w    omgindow.foo;", "insertTextAtCaret() works");
 
   is(sp.editor.getCaretOffset(), 13, "caret location is correct after update");
 
   gScratchpadWindow.close();
 
   Services.prefs.setIntPref("devtools.editor.tabsize", 6);
   Services.prefs.setBoolPref("devtools.editor.expandtab", false);
+
   gScratchpadWindow = Scratchpad.openScratchpad();
-  gScratchpadWindow.addEventListener("load", runTests2, false);
+  gScratchpadWindow.addEventListener("load", function onScratchpadLoad() {
+    gScratchpadWindow.removeEventListener("load", onScratchpadLoad, false);
+    gScratchpadWindow.Scratchpad.addObserver({
+      onReady: runTests2
+    });
+  }, false);
 }
 
 function runTests2()
 {
-  gScratchpadWindow.removeEventListener("load", arguments.callee, false);
-
   let sp = gScratchpadWindow.Scratchpad;
+  sp.removeObserver(this);
 
   sp.setText("window.foo;");
   sp.editor.setCaretOffset(0);
 
   EventUtils.synthesizeKey("VK_TAB", {}, gScratchpadWindow);
 
   is(sp.getText(), "\twindow.foo;", "Tab key added the tab character");
 
   is(sp.editor.getCaretOffset(), 1, "caret location is correct");
 
   Services.prefs.clearUserPref("devtools.editor.tabsize");
   Services.prefs.clearUserPref("devtools.editor.expandtab");
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
@@ -27,114 +27,144 @@ function test()
 
   content.location = "data:text/html,<p>test star* UI for unsaved file changes";
 }
 
 function testListeners()
 {
   let win = ScratchpadManager.openScratchpad();
 
-  win.addEventListener("load", function() {
-    let scratchpad = win.Scratchpad;
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
 
-    scratchpad.setText("new text");
-    ok(!isStar(win), "no star if scratchpad isn't from a file");
+    win.Scratchpad.addObserver({
+      onReady: function (aScratchpad) {
+        aScratchpad.removeObserver(this);
 
-    scratchpad.onTextSaved(); 
-    ok(!isStar(win), "no star before changing text");
+        aScratchpad.setText("new text");
+        ok(!isStar(win), "no star if scratchpad isn't from a file");
+
+        aScratchpad.onTextSaved();
+        ok(!isStar(win), "no star before changing text");
 
-    scratchpad.setText("new text2");
-    ok(isStar(win), "shows star if scratchpad text changes");
+        aScratchpad.setText("new text2");
+        ok(isStar(win), "shows star if scratchpad text changes");
+
+        aScratchpad.onTextSaved();
+        ok(!isStar(win), "no star if scratchpad was just saved");
 
-    scratchpad.onTextSaved();
-    ok(!isStar(win), "no star if scratchpad was just saved");
-    
-    scratchpad.undo();
-    ok(isStar(win), "star if scratchpad undo");
+        aScratchpad.undo();
+        ok(isStar(win), "star if scratchpad undo");
 
-    win.close();
-    done();
-  });
+        win.close();
+        done();
+      }
+    });
+  }, false);
 }
 
 function testErrorStatus()
 {
   let win = ScratchpadManager.openScratchpad();
 
-  win.addEventListener("load", function() {
-    let scratchpad = win.Scratchpad;
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
+
+    win.Scratchpad.addObserver({
+      onReady: function (aScratchpad) {
+        aScratchpad.removeObserver(this);
 
-    scratchpad.onTextSaved(Components.results.NS_ERROR_FAILURE);
-    scratchpad.setText("new text");
-    ok(!isStar(win), "no star if file save failed");
+        aScratchpad.onTextSaved(Components.results.NS_ERROR_FAILURE);
+        aScratchpad.setText("new text");
+        ok(!isStar(win), "no star if file save failed");
 
-    win.close();
-    done();
-  });
+        win.close();
+        done();
+      }
+    });
+  }, false);
 }
 
 
 function testRestoreNotFromFile()
 {
   let session = [{
     text: "test1",
     executionContext: 1
   }];
 
   let [win] = ScratchpadManager.restoreSession(session);
-  win.addEventListener("load", function() {
-    let scratchpad = win.Scratchpad;
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
+
+    win.Scratchpad.addObserver({
+      onReady: function (aScratchpad) {
+        aScratchpad.removeObserver(this);
 
-    scratchpad.setText("new text");
-    ok(!isStar(win), "no star if restored scratchpad isn't from a file");
-    
-    win.close();
-    done();
-  });
+        aScratchpad.setText("new text");
+        ok(!isStar(win), "no star if restored scratchpad isn't from a file");
+
+        win.close();
+        done();
+      }
+    });
+  }, false);
 }
 
 function testRestoreFromFileSaved()
 {
   let session = [{
     filename: "test.js",
     text: "test1",
     executionContext: 1,
     saved: true
   }];
 
   let [win] = ScratchpadManager.restoreSession(session);
-  win.addEventListener("load", function() {
-    let scratchpad = win.Scratchpad;
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
 
-    ok(!isStar(win), "no star before changing text in scratchpad restored from file");
+    win.Scratchpad.addObserver({
+      onReady: function (aScratchpad) {
+        aScratchpad.removeObserver(this);
+
+        ok(!isStar(win), "no star before changing text in scratchpad restored from file");
 
-    scratchpad.setText("new text");
-    ok(isStar(win), "star when text changed from scratchpad restored from file");
+        aScratchpad.setText("new text");
+        ok(isStar(win), "star when text changed from scratchpad restored from file");
 
-    win.close();
-    done();
-  });
+        win.close();
+        done();
+      }
+    });
+  }, false);
 }
 
 function testRestoreFromFileUnsaved()
 {
   let session = [{
     filename: "test.js",
     text: "test1",
     executionContext: 1,
     saved: false
   }];
 
   let [win] = ScratchpadManager.restoreSession(session);
-  win.addEventListener("load", function() {
-    let scratchpad = win.Scratchpad;
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
+
+    win.Scratchpad.addObserver({
+      onReady: function (aScratchpad) {
+        aScratchpad.removeObserver(this);
 
-    ok(isStar(win), "star with scratchpad restored with unsaved text");
+        ok(isStar(win), "star with scratchpad restored with unsaved text");
 
-    win.close();
-    done();
-  });
+        win.close();
+        done();
+      }
+    });
+  }, false);
 }
 
 function isStar(win)
 {
   return win.document.title.match(/^\*[^\*]/);
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_679467_falsy.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_679467_falsy.js
@@ -25,19 +25,16 @@ function testFalsy(sp)
   gScratchpadWindow.removeEventListener("load", testFalsy, false);
 
   let sp = gScratchpadWindow.Scratchpad;
   verifyFalsies(sp);
   
   sp.setBrowserContext();
   verifyFalsies(sp);
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
 
 function verifyFalsies(sp)
 {
   sp.setText("undefined");
   sp.display();
   is(sp.selectedText, "/*\nundefined\n*/", "'undefined' is displayed");
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js
@@ -1,39 +1,35 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 Cu.import("resource:///modules/source-editor.jsm");
 
-// Reference to the Scratchpad chrome window object.
-let gScratchpadWindow;
-
 function test()
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
 
     gScratchpadWindow = Scratchpad.openScratchpad();
-    gScratchpadWindow.addEventListener("load", function onScratchpadLoad() {
-      gScratchpadWindow.removeEventListener("load", onScratchpadLoad, false);
-      waitForFocus(runTests, gScratchpadWindow);
-    }, false);
+    gScratchpadWindow.addEventListener("load", runTests, false);
   }, true);
 
   content.location = "data:text/html,test Edit menu updates Scratchpad - bug 699130";
 }
 
 function runTests()
 {
+  gScratchpadWindow.removeEventListener("load", runTests, false);
+
   let sp = gScratchpadWindow.Scratchpad;
   let doc = gScratchpadWindow.document;
   let winUtils = gScratchpadWindow.QueryInterface(Ci.nsIInterfaceRequestor).
                  getInterface(Ci.nsIDOMWindowUtils);
   let OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
 
   info("will test the Edit menu");
 
@@ -121,33 +117,40 @@ function runTests()
 
   let showAfterSelect = function() {
     ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after select");
     closeMenu(hideAfterSelect);
   };
 
   let hideAfterSelect = function() {
     sp.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onCut);
-    EventUtils.synthesizeKey("x", {accelKey: true}, gScratchpadWindow);
+    waitForFocus(function () {
+      let selectedText = sp.editor.getSelectedText();
+      ok(selectedText.length > 0, "non-empty selected text will be cut");
+
+      EventUtils.synthesizeKey("x", {accelKey: true}, gScratchpadWindow);
+    }, gScratchpadWindow);
   };
 
   let onCut = function() {
     sp.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onCut);
     openMenu(12, 12, showAfterCut);
   };
 
   let showAfterCut = function() {
     ok(cutItem.hasAttribute("disabled"), "cut menuitem is disabled after cut");
     ok(!pasteItem.hasAttribute("disabled"), "paste menuitem is enabled after cut");
     closeMenu(hideAfterCut);
   };
 
   let hideAfterCut = function() {
     sp.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste);
-    EventUtils.synthesizeKey("v", {accelKey: true}, gScratchpadWindow);
+    waitForFocus(function () {
+      EventUtils.synthesizeKey("v", {accelKey: true}, gScratchpadWindow);
+    }, gScratchpadWindow);
   };
 
   let onPaste = function() {
     sp.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste);
     openMenu(13, 13, showAfterPaste);
   };
 
   let showAfterPaste = function() {
@@ -156,17 +159,17 @@ function runTests()
     closeMenu(hideAfterPaste);
   };
 
   let hideAfterPaste = function() {
     if (pass == 0) {
       pass++;
       testContextMenu();
     } else {
-      finishTest();
+      finish();
     }
   };
 
   let testContextMenu = function() {
     info("will test the context menu");
 
     editMenu = null;
     isContextMenu = true;
@@ -177,17 +180,10 @@ function runTests()
     ok(cutItem, "the Cut menuitem");
     pasteItem = doc.getElementById("menu_paste");
     ok(pasteItem, "the Paste menuitem");
 
     sp.setText("bug 699130: hello world! (context menu)");
     openMenu(10, 10, firstShow);
   };
 
-  let finishTest = function() {
-    gScratchpadWindow.close();
-    gScratchpadWindow = null;
-    gBrowser.removeCurrentTab();
-    finish();
-  };
-
   openMenu(10, 10, firstShow);
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_contexts.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_contexts.js
@@ -118,13 +118,10 @@ function runTests()
   sp.setContentContext();
 
   is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
      "executionContext is content");
 
   is(sp.run()[2], "undefined",
      "global variable no longer exists after changing the context");
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_execute_print.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_execute_print.js
@@ -1,15 +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/ */
 
-// Reference to the Scratchpad chrome window object.
-let gScratchpadWindow;
-
 function test()
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
@@ -124,13 +121,10 @@ function runTests()
   sp.setText("foo1");
   sp.setText("foo2");
   is(sp.getText(), "foo2", "editor content updated");
   sp.undo();
   is(sp.getText(), "foo1", "undo() works");
   sp.redo();
   is(sp.getText(), "foo2", "redo() works");
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_files.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_files.js
@@ -133,13 +133,10 @@ function fileRead(aInputStream, aStatus)
     NetUtil.readInputStreamToString(aInputStream, aInputStream.available());;
 
   is(updatedContent, gFileContent, "file properly updated");
 
   // Done!
   gFile.remove(false);
   gFile = null;
   gScratchpad = null;
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_initialization.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_initialization.js
@@ -45,13 +45,10 @@ function runTests()
      "Error console command is disabled");
 
   let chromeContextCommand = gScratchpadWindow.document.
                             getElementById("sp-cmd-browserContext");
   ok(chromeContextCommand, "Chrome context command element exists");
   is(chromeContextCommand.getAttribute("disabled"), "true",
      "Chrome context command is disabled");
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
@@ -50,15 +50,12 @@ function runTests()
         break;
       }
     }
     ok(found, "found the document.title property");
 
     executeSoon(function() {
       propPanel.hidePopup();
 
-      gScratchpadWindow.close();
-      gScratchpadWindow = null;
-      gBrowser.removeCurrentTab();
       finish();
     });
   }, false);
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_open.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_open.js
@@ -23,47 +23,51 @@ function test()
   testOpenWithState();
   testOpenInvalidState();
 }
 
 function testOpen()
 {
   let win = ScratchpadManager.openScratchpad();
 
-  win.addEventListener("load", function() {
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
+
     is(win.Scratchpad.filename, undefined, "Default filename is undefined");
     is(win.Scratchpad.getText(),
        win.Scratchpad.strings.GetStringFromName("scratchpadIntro"),
        "Default text is loaded")
     is(win.Scratchpad.executionContext, win.SCRATCHPAD_CONTEXT_CONTENT,
       "Default execution context is content");
 
     win.close();
     done();
-  });
+  }, false);
 }
 
 function testOpenWithState()
 {
   let state = {
     filename: "testfile",
     executionContext: 2,
     text: "test text"
   };
 
   let win = ScratchpadManager.openScratchpad(state);
 
-  win.addEventListener("load", function() {
+  win.addEventListener("load", function onScratchpadLoad() {
+    win.removeEventListener("load", onScratchpadLoad, false);
+
     is(win.Scratchpad.filename, state.filename, "Filename loaded from state");
     is(win.Scratchpad.executionContext, state.executionContext, "Execution context loaded from state");
     is(win.Scratchpad.getText(), state.text, "Content loaded from state");
 
     win.close();
     done();
-  });
+  }, false);
 }
 
 function testOpenInvalidState()
 {
   let state = 7;
 
   let win = ScratchpadManager.openScratchpad(state);
   ok(!win, "no scratchpad opened if state is not an object");
--- a/browser/devtools/scratchpad/test/browser_scratchpad_restore.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_restore.js
@@ -44,19 +44,20 @@ function testRestore()
       text: "text3",
       executionContext: 1
     }
   ];
 
   asyncMap(states, function(state, done) {
     // Open some scratchpad windows
     let win = ScratchpadManager.openScratchpad(state);
-    win.addEventListener("load", function() {
+    win.addEventListener("load", function onScratchpadLoad() {
+      removeEventListener("load", onScratchpadLoad, false);
       done(win);
-    })
+    }, false)
   }, function(wins) {
     // Then save the windows to session store
     ScratchpadManager.saveOpenWindows();
 
     // Then get their states
     let session = ScratchpadManager.getSessionState();
 
     // Then close them
@@ -68,21 +69,22 @@ function testRestore()
     ScratchpadManager.saveOpenWindows();
 
     // Then restore them
     let restoredWins = ScratchpadManager.restoreSession(session);
 
     is(restoredWins.length, 3, "Three scratchad windows restored");
 
     asyncMap(restoredWins, function(restoredWin, done) {
-      restoredWin.addEventListener("load", function() {
+      restoredWin.addEventListener("load", function onScratchpadLoad() {
+        restoredWin.removeEventListener("load", onScratchpadLoad, false);
         let state = restoredWin.Scratchpad.getState();
         restoredWin.close();
         done(state);
-      });
+      }, false);
     }, function(restoredStates) {
       // Then make sure they were restored with the right states
       ok(statesMatch(restoredStates, states),
         "All scratchpad window states restored correctly");
 
       // Yay, we're done!
       finish();
     });
--- a/browser/devtools/scratchpad/test/browser_scratchpad_tab_switch.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_tab_switch.js
@@ -94,17 +94,13 @@ function runTests2() {
 
 function runTests3() {
   gBrowser.selectedBrowser.removeEventListener("load", runTests3, true);
   // Check that the sandbox is not cached.
 
   sp.setText("typeof foosbug653108;");
   is(sp.run()[2], "undefined", "global variable does not exist");
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
   tab1 = null;
   tab2 = null;
   sp = null;
-  gBrowser.removeCurrentTab();
-  gBrowser.removeCurrentTab();
   finish();
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_ui.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_ui.js
@@ -70,13 +70,10 @@ function runTests()
     ok(lastMethodCalled == methodName,
        "method " + methodName + " invoked by the associated menuitem");
 
     sp[methodName] = oldMethod;
   }
 
   delete sp.__noSuchMethod__;
 
-  gScratchpadWindow.close();
-  gScratchpadWindow = null;
-  gBrowser.removeCurrentTab();
   finish();
 }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/head.js
@@ -0,0 +1,20 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let gScratchpadWindow; // Reference to the Scratchpad chrome window object
+
+function cleanup()
+{
+  if (gScratchpadWindow) {
+    gScratchpadWindow.close();
+    gScratchpadWindow = null;
+  }
+  while (gBrowser.tabs.length > 1) {
+    gBrowser.removeCurrentTab();
+  }
+}
+
+registerCleanupFunction(cleanup);
--- a/browser/devtools/sourceeditor/orion/README
+++ b/browser/devtools/sourceeditor/orion/README
@@ -20,16 +20,18 @@ Orion version: git clone from 2011-10-26
     https://github.com/mihaisucan/orion.client/tree/bug-362107
       see https://bugs.eclipse.org/bugs/show_bug.cgi?id=362107
   + patch for Eclipse Bug 362428 - _getXToOffset() throws:
     https://github.com/mihaisucan/orion.client/tree/bug-362428
       see https://bugs.eclipse.org/bugs/show_bug.cgi?id=362428
   + patch for Eclipse Bug 362835 - Pasted HTML shows twice:
     https://github.com/mihaisucan/orion.client/tree/bug-362835
       see https://bugs.eclipse.org/bugs/show_bug.cgi?id=362835
+  + patch for Eclipse Bug 363508 - Selection is broken after TextView hide/unhide
+    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=363508
 
 # License
 
 The following files are licensed according to the contents in the LICENSE
 file:
   orion.js
   orion.css
 
--- a/browser/devtools/sourceeditor/orion/orion.js
+++ b/browser/devtools/sourceeditor/orion/orion.js
@@ -1947,17 +1947,17 @@ if (typeof window !== "undefined" && typ
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
- *		Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#358623 Bug#362286 Bug#362107 Bug#362428 Bug#362835
+ *		Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#358623 Bug#362286 Bug#362107 Bug#362428 Bug#362835 Bug#363508
  ******************************************************************************/
 
 /*global window document navigator setTimeout clearTimeout XMLHttpRequest define */
 
 /**
  * @namespace The global container for Orion APIs.
  */ 
 var orion = orion || {};
@@ -3859,16 +3859,18 @@ orion.textview.TextView = (function() {
 				}
 
 				this._isMouseDown = true;
 				this._handleMouse(e);
 				if (isOpera || isChrome) {
 					if (!this._hasFocus) {
 						this.focus();
 					}
+				}
+				if (e.preventDefault) {
 					e.preventDefault();
 				}
 			}
 		},
 		_handleMouseMove: function (e) {
 			if (!e) { e = window.event; }
 			this._setLinksVisible(!this._isMouseDown && (isMac ? e.metaKey : e.ctrlKey));
 			if (!this._isMouseDown) {
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -217,17 +217,27 @@ SourceEditor.prototype = {
       this._view.setKeyBinding(binding, aKey.action);
 
       if (aKey.callback) {
         this._view.setAction(aKey.action, aKey.callback);
       }
     }, this);
 
     if (aCallback) {
-      aCallback(this);
+      let iframe = this._view._frame;
+      let document = iframe.contentDocument;
+      if (!document || document.readyState != "complete") {
+        let onIframeLoad = function () {
+          iframe.contentWindow.removeEventListener("load", onIframeLoad, false);
+          aCallback(this);
+        }.bind(this);
+        iframe.contentWindow.addEventListener("load", onIframeLoad, false);
+      } else {
+        aCallback(this);
+      }
     }
   },
 
   /**
    * Initialize the custom Orion editor features.
    * @private
    */
   _initEditorFeatures: function SE__initEditorFeatures()
@@ -543,16 +553,38 @@ SourceEditor.prototype = {
    * Focus the editor.
    */
   focus: function SE_focus()
   {
     this._view.focus();
   },
 
   /**
+   * Get the first visible line number.
+   *
+   * @return number
+   *         The line number, counting from 0.
+   */
+  getTopIndex: function SE_getTopIndex()
+  {
+    return this._view.getTopIndex();
+  },
+
+  /**
+   * Set the first visible line number.
+   *
+   * @param number aTopIndex
+   *         The line number, counting from 0.
+   */
+  setTopIndex: function SE_setTopIndex(aTopIndex)
+  {
+    this._view.setTopIndex(aTopIndex);
+  },
+
+  /**
    * Check if the editor has focus.
    *
    * @return boolean
    *         True if the editor is focused, false otherwise.
    */
   hasFocus: function SE_hasFocus()
   {
     return this._iframe.ownerDocument.activeElement === this._iframe;
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/Makefile.in
@@ -0,0 +1,54 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Style Editor code.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+#
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#    Cedric Vivier <cedricv@neonux.com>  (Original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifdef ENABLE_TESTS
+  ifneq (mobile,$(MOZ_BUILD_APP))
+  	  DIRS += test
+  endif
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+libs::
+	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/SplitView.jsm
@@ -0,0 +1,489 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Style Editor code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Cedric Vivier <cedricv@neonux.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["SplitView"];
+
+/* this must be kept in sync with CSS (ie. splitview.css) */
+const LANDSCAPE_MEDIA_QUERY = "(min-aspect-ratio: 5/3)";
+
+const BINDING_USERDATA = "splitview-binding";
+
+
+/**
+ * SplitView constructor
+ *
+ * Initialize the split view UI on an existing DOM element.
+ *
+ * A split view contains items, each of those having one summary and one details
+ * elements.
+ * It is adaptive as it behaves similarly to a richlistbox when there the aspect
+ * ratio is narrow or as a pair listbox-box otherwise.
+ *
+ * @param DOMElement aRoot
+ * @see appendItem
+ */
+function SplitView(aRoot)
+{
+  this._root = aRoot;
+  this._controller = aRoot.querySelector(".splitview-controller");
+  this._nav = aRoot.querySelector(".splitview-nav");
+  this._side = aRoot.querySelector(".splitview-side-details");
+  this._activeSummary = null
+
+  this._mql = aRoot.ownerDocument.defaultView.matchMedia(LANDSCAPE_MEDIA_QUERY);
+
+  this._filter = aRoot.querySelector(".splitview-filter");
+  if (this._filter) {
+    this._setupFilterBox();
+  }
+
+  // items list focus and search-on-type handling
+  this._nav.addEventListener("keydown", function onKeyCatchAll(aEvent) {
+    function getFocusedItemWithin(nav) {
+      let node = nav.ownerDocument.activeElement;
+      while (node && node.parentNode != nav) {
+        node = node.parentNode;
+      }
+      return node;
+    }
+
+    // do not steal focus from inside iframes or textboxes
+    if (aEvent.target.ownerDocument != this._nav.ownerDocument ||
+        aEvent.target.tagName == "input" ||
+        aEvent.target.tagName == "textbox" ||
+        aEvent.target.tagName == "textarea" ||
+        aEvent.target.classList.contains("textbox")) {
+      return false;
+    }
+
+    // handle keyboard navigation within the items list
+    let newFocusOrdinal;
+    if (aEvent.keyCode == aEvent.DOM_VK_PAGE_UP ||
+        aEvent.keyCode == aEvent.DOM_VK_HOME) {
+      newFocusOrdinal = 0;
+    } else if (aEvent.keyCode == aEvent.DOM_VK_PAGE_DOWN ||
+               aEvent.keyCode == aEvent.DOM_VK_END) {
+      newFocusOrdinal = this._nav.childNodes.length - 1;
+    } else if (aEvent.keyCode == aEvent.DOM_VK_UP) {
+      newFocusOrdinal = getFocusedItemWithin(this._nav).getAttribute("data-ordinal");
+      newFocusOrdinal--;
+    } else if (aEvent.keyCode == aEvent.DOM_VK_DOWN) {
+      newFocusOrdinal = getFocusedItemWithin(this._nav).getAttribute("data-ordinal");
+      newFocusOrdinal++;
+    }
+    if (newFocusOrdinal !== undefined) {
+      aEvent.stopPropagation();
+      let el = this.getSummaryElementByOrdinal(newFocusOrdinal);
+      if (el) {
+        el.focus();
+      }
+      return false;
+    }
+
+    // search-on-type when any non-whitespace character is pressed while list
+    // has the focus
+    if (this._filter &&
+        !/\s/.test(String.fromCharCode(aEvent.which))) {
+      this._filter.focus();
+    }
+  }.bind(this), false);
+}
+
+SplitView.prototype = {
+  /**
+    * Retrieve whether the UI currently has a landscape orientation.
+    *
+    * @return boolean
+    */
+  get isLandscape() this._mql.matches,
+
+  /**
+    * Retrieve the root element.
+    *
+    * @return DOMElement
+    */
+  get rootElement() this._root,
+
+  /**
+    * Retrieve the active item's summary element or null if there is none.
+    *
+    * @return DOMElement
+    */
+  get activeSummary() this._activeSummary,
+
+  /**
+    * Set the active item's summary element.
+    *
+    * @param DOMElement aSummary
+    */
+  set activeSummary(aSummary)
+  {
+    if (aSummary == this._activeSummary) {
+      return;
+    }
+
+    if (this._activeSummary) {
+      let binding = this._activeSummary.getUserData(BINDING_USERDATA);
+
+      if (binding.onHide) {
+        binding.onHide(this._activeSummary, binding._details, binding.data);
+      }
+
+      this._activeSummary.classList.remove("splitview-active");
+      binding._details.classList.remove("splitview-active");
+    }
+
+    if (!aSummary) {
+      return;
+    }
+
+    let binding = aSummary.getUserData(BINDING_USERDATA);
+    aSummary.classList.add("splitview-active");
+    binding._details.classList.add("splitview-active");
+
+    this._activeSummary = aSummary;
+
+    if (binding.onShow) {
+      binding.onShow(aSummary, binding._details, binding.data);
+    }
+    aSummary.scrollIntoView();
+  },
+
+  /**
+    * Retrieve the active item's details element or null if there is none.
+    * @return DOMElement
+    */
+  get activeDetails()
+  {
+    let summary = this.activeSummary;
+    return summary ? summary.getUserData(BINDING_USERDATA)._details : null;
+  },
+
+  /**
+   * Retrieve the summary element for a given ordinal.
+   *
+   * @param number aOrdinal
+   * @return DOMElement
+   *         Summary element with given ordinal or null if not found.
+   * @see appendItem
+   */
+  getSummaryElementByOrdinal: function SEC_getSummaryElementByOrdinal(aOrdinal)
+  {
+    return this._nav.querySelector("* > li[data-ordinal='" + aOrdinal + "']");
+  },
+
+  /**
+   * Append an item to the split view.
+   *
+   * @param DOMElement aSummary
+   *        The summary element for the item.
+   * @param DOMElement aDetails
+   *        The details element for the item.
+   * @param object aOptions
+   *     Optional object that defines custom behavior and data for the item.
+   *     All properties are optional :
+   *     - function(DOMElement summary, DOMElement details, object data) onCreate
+   *         Called when the item has been added.
+   *     - function(summary, details, data) onShow
+   *         Called when the item is shown/active.
+   *     - function(summary, details, data) onHide
+   *         Called when the item is hidden/inactive.
+   *     - function(summary, details, data) onDestroy
+   *         Called when the item has been removed.
+   *     - function(summary, details, data, query) onFilterBy
+   *         Called when the user performs a filtering search.
+   *         If the function returns false, the item does not match query
+   *         string and will be hidden.
+   *     - object data
+   *         Object to pass to the callbacks above.
+   *     - boolean disableAnimations
+   *         If true there is no animation or scrolling when this item is
+   *         appended. Set this when batch appending (eg. initial population).
+   *     - number ordinal
+   *         Items with a lower ordinal are displayed before those with a
+   *         higher ordinal.
+   */
+  appendItem: function ASV_appendItem(aSummary, aDetails, aOptions)
+  {
+    let binding = aOptions || {};
+
+    binding._summary = aSummary;
+    binding._details = aDetails;
+    aSummary.setUserData(BINDING_USERDATA, binding, null);
+
+    if (!binding.disableAnimations) {
+      aSummary.classList.add("splitview-slide");
+      aSummary.classList.add("splitview-flash");
+    }
+    this._nav.appendChild(aSummary);
+
+    aSummary.addEventListener("click", function onSummaryClick(aEvent) {
+      aEvent.stopPropagation();
+      this.activeSummary = aSummary;
+    }.bind(this), false);
+
+    this._side.appendChild(aDetails);
+
+    if (binding.onCreate) {
+      // queue onCreate handler
+      this._root.ownerDocument.defaultView.setTimeout(function () {
+        binding.onCreate(aSummary, aDetails, binding.data);
+      }, 0);
+    }
+
+    if (!binding.disableAnimations) {
+      scheduleAnimation(aSummary, "splitview-slide", "splitview-flash");
+      aSummary.scrollIntoView();
+    }
+  },
+
+  /**
+   * Append an item to the split view according to two template elements
+   * (one for the item's summary and the other for the item's details).
+   *
+   * @param string aName
+   *        Name of the template elements to instantiate.
+   *        Requires two (hidden) DOM elements with id "splitview-tpl-summary-"
+   *        and "splitview-tpl-details-" suffixed with aName.
+   * @param object aOptions
+   *        Optional object that defines custom behavior and data for the item.
+   *        See appendItem for full description.
+   * @return object{summary:,details:}
+   *         Object with the new DOM elements created for summary and details.
+   * @see appendItem
+   */
+  appendTemplatedItem: function ASV_appendTemplatedItem(aName, aOptions)
+  {
+    aOptions = aOptions || {};
+    let summary = this._root.querySelector("#splitview-tpl-summary-" + aName);
+    let details = this._root.querySelector("#splitview-tpl-details-" + aName);
+
+    summary = summary.cloneNode(true);
+    summary.id = "";
+    if (aOptions.ordinal !== undefined) { // can be zero
+      summary.style.MozBoxOrdinalGroup = aOptions.ordinal;
+      summary.setAttribute("data-ordinal", aOptions.ordinal);
+    }
+    details = details.cloneNode(true);
+    details.id = "";
+
+    this.appendItem(summary, details, aOptions);
+    return {summary: summary, details: details};
+  },
+
+  /**
+    * Remove an item from the split view.
+    *
+    * @param DOMElement aSummary
+    *        Summary element of the item to remove.
+    */
+  removeItem: function ASV_removeItem(aSummary)
+  {
+    if (aSummary == this._activeSummary) {
+      this.activeSummary = null;
+    }
+
+    let binding = aSummary.getUserData(BINDING_USERDATA);
+    aSummary.parentNode.removeChild(aSummary);
+    binding._details.parentNode.removeChild(binding._details);
+
+    if (binding.onDestroy) {
+      binding.onDestroy(aSummary, binding._details, binding.data);
+    }
+  },
+
+  /**
+   * Remove all items from the split view.
+   */
+  removeAll: function ASV_removeAll()
+  {
+    while (this._nav.hasChildNodes()) {
+      this.removeItem(this._nav.firstChild);
+    }
+  },
+
+  /**
+    * Filter items by given string.
+    * Matching is performed on every item by calling onFilterBy when defined
+    * and then by searching aQuery in the summary element's text item.
+    * Non-matching item is hidden.
+    *
+    * If no item matches, 'splitview-all-filtered' class is set on the filter
+    * input element and the splitview-nav element.
+    *
+    * @param string aQuery
+    *        The query string. Use null to reset (no filter).
+    * @return number
+    *         The number of filtered (non-matching) item.
+    */
+  filterItemsBy: function ASV_filterItemsBy(aQuery)
+  {
+    if (!this._nav.hasChildNodes()) {
+      return 0;
+    }
+    if (aQuery) {
+      aQuery = aQuery.trim();
+    }
+    if (!aQuery) {
+      for (let i = 0; i < this._nav.childNodes.length; ++i) {
+        this._nav.childNodes[i].classList.remove("splitview-filtered");
+      }
+      this._filter.classList.remove("splitview-all-filtered");
+      this._nav.classList.remove("splitview-all-filtered");
+      return 0;
+    }
+
+    let count = 0;
+    let filteredCount = 0;
+    for (let i = 0; i < this._nav.childNodes.length; ++i) {
+      let summary = this._nav.childNodes[i];
+
+      let matches = false;
+      let binding = summary.getUserData(BINDING_USERDATA);
+      if (binding.onFilterBy) {
+        matches = binding.onFilterBy(summary, binding._details, binding.data, aQuery);
+      }
+      if (!matches) { // try text content
+        let content = summary.textContent.toUpperCase();
+        matches = (content.indexOf(aQuery.toUpperCase()) > -1);
+      }
+
+      count++;
+      if (!matches) {
+        summary.classList.add("splitview-filtered");
+        filteredCount++;
+      } else {
+        summary.classList.remove("splitview-filtered");
+      }
+    }
+
+    if (count > 0 && filteredCount == count) {
+      this._filter.classList.add("splitview-all-filtered");
+      this._nav.classList.add("splitview-all-filtered");
+    } else {
+      this._filter.classList.remove("splitview-all-filtered");
+      this._nav.classList.remove("splitview-all-filtered");
+    }
+    return filteredCount;
+  },
+
+  /**
+   * Set the item's CSS class name.
+   * This sets the class on both the summary and details elements, retaining
+   * any SplitView-specific classes.
+   *
+   * @param DOMElement aSummary
+   *        Summary element of the item to set.
+   * @param string aClassName
+   *        One or more space-separated CSS classes.
+   */
+  setItemClassName: function ASV_setItemClassName(aSummary, aClassName)
+  {
+    let binding = aSummary.getUserData(BINDING_USERDATA);
+    let viewSpecific;
+
+    viewSpecific = aSummary.className.match(/(splitview\-[\w-]+)/g);
+    viewSpecific = viewSpecific ? viewSpecific.join(" ") : "";
+    aSummary.className = viewSpecific + " " + aClassName;
+
+    viewSpecific = binding._details.className.match(/(splitview\-[\w-]+)/g);
+    viewSpecific = viewSpecific ? viewSpecific.join(" ") : "";
+    binding._details.className = viewSpecific + " " + aClassName;
+  },
+
+  /**
+   * Set up filter search box.
+   */
+  _setupFilterBox: function ASV__setupFilterBox()
+  {
+    let clearFilter = function clearFilter(aEvent) {
+      this._filter.value = "";
+      this.filterItemsBy("");
+      return false;
+    }.bind(this);
+
+    this._filter.addEventListener("command", function onFilterInput(aEvent) {
+      this.filterItemsBy(this._filter.value);
+    }.bind(this), false);
+
+    this._filter.addEventListener("keyup", function onFilterKeyUp(aEvent) {
+      if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
+        clearFilter();
+      }
+      if (aEvent.keyCode == aEvent.DOM_VK_ENTER ||
+          aEvent.keyCode == aEvent.DOM_VK_RETURN) {
+        // autofocus matching item if there is only one
+        let matches = this._nav.querySelectorAll("* > li:not(.splitview-filtered)");
+        if (matches.length == 1) {
+          this.activeSummary = matches[0];
+        }
+      }
+    }.bind(this), false);
+
+    let clearButtons = this._root.querySelectorAll(".splitview-filter-clearButton");
+    for (let i = 0; i < clearButtons.length; ++i) {
+      clearButtons[i].addEventListener("click", clearFilter, false);
+    }
+  }
+};
+
+//
+// private helpers
+
+/**
+ * Schedule one or multiple CSS animation(s) on an element.
+ *
+ * @param DOMElement aElement
+ * @param string ...
+ *        One or multiple animation class name(s).
+ */
+function scheduleAnimation(aElement)
+{
+  let classes = Array.prototype.slice.call(arguments, 1);
+  for each (let klass in classes) {
+    aElement.classList.add(klass);
+  }
+
+  let window = aElement.ownerDocument.defaultView;
+  window.mozRequestAnimationFrame(function triggerAnimation() {
+    for each (let klass in classes) {
+      aElement.classList.remove(klass);
+    }
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -0,0 +1,1135 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Style Editor code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Cedric Vivier <cedricv@neonux.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["StyleEditor", "StyleEditorFlags"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource:///modules/devtools/StyleEditorUtil.jsm");
+Cu.import("resource:///modules/source-editor.jsm");
+
+const LOAD_ERROR = "error-load";
+const SAVE_ERROR = "error-save";
+
+// max update frequency in ms (avoid potential typing lag and/or flicker)
+// @see StyleEditor.updateStylesheet
+const UPDATE_STYLESHEET_THROTTLE_DELAY = 500;
+
+// @see StyleEditor._persistExpando
+const STYLESHEET_EXPANDO = "-moz-styleeditor-stylesheet-";
+
+
+/**
+ * StyleEditor constructor.
+ *
+ * The StyleEditor is initialized 'headless', it does not display source
+ * or receive input. Setting inputElement attaches a DOMElement to handle this.
+ *
+ * An editor can be created stand-alone or created by StyleEditorChrome to
+ * manage all the style sheets of a document, including @import'ed sheets.
+ *
+ * @param DOMDocument aDocument
+ *        The content document where changes will be applied to.
+ * @param DOMStyleSheet aStyleSheet
+ *        Optional. The DOMStyleSheet to edit.
+ *        If not set, a new empty style sheet will be appended to the document.
+ * @see inputElement
+ * @see StyleEditorChrome
+ */
+function StyleEditor(aDocument, aStyleSheet)
+{
+  assert(aDocument, "Argument 'aDocument' is required.");
+
+  this._document = aDocument; // @see contentDocument
+  this._inputElement = null;  // @see inputElement
+  this._sourceEditor = null;  // @see sourceEditor
+
+  this._state = {             // state to handle inputElement attach/detach
+    text: "",                 // seamlessly
+    selection: {start: 0, end: 0},
+    readOnly: false,
+    topIndex: 0,              // the first visible line
+  };
+
+  this._styleSheet = aStyleSheet;
+  this._styleSheetIndex = -1; // unknown for now, will be set after load
+
+  this._loaded = false;
+
+  this._flags = [];           // @see flags
+  this._savedFile = null;     // @see savedFile
+
+  this._errorMessage = null;  // @see errorMessage
+
+  // listeners for significant editor actions. @see addActionListener
+  this._actionListeners = [];
+
+  // this is to perform pending updates before editor closing
+  this._onWindowUnloadBinding = this._onWindowUnload.bind(this);
+  this._focusOnSourceEditorReady = false;
+}
+
+StyleEditor.prototype = {
+  /**
+   * Retrieve the content document this editor will apply changes to.
+   *
+   * @return DOMDocument
+   */
+  get contentDocument() this._document,
+
+  /**
+   * Retrieve the stylesheet this editor is attached to.
+   *
+   * @return DOMStyleSheet
+   */
+  get styleSheet()
+  {
+    assert(this._styleSheet, "StyleSheet must be loaded first.")
+    return this._styleSheet;
+  },
+
+  /**
+   * Retrieve the index (order) of stylesheet in the document.
+   *
+   * @return number
+   */
+  get styleSheetIndex()
+  {
+    let document = this.contentDocument;
+    if (this._styleSheetIndex == -1) {
+      for (let i = 0; i < document.styleSheets.length; ++i) {
+        if (document.styleSheets[i] == this.styleSheet) {
+          this._styleSheetIndex = i;
+          break;
+        }
+      }
+    }
+    return this._styleSheetIndex;
+  },
+
+  /**
+   * Retrieve the input element that handles display and input for this editor.
+   * Can be null if the editor is detached/headless, which means that this
+   * StyleEditor is not attached to an input element.
+   *
+   * @return DOMElement
+   */
+  get inputElement() this._inputElement,
+
+  /**
+   * Set the input element that handles display and input for this editor.
+   * This detaches the previous input element if previously set.
+   *
+   * @param DOMElement aElement
+   */
+  set inputElement(aElement)
+  {
+    if (aElement == this._inputElement) {
+      return; // no change
+    }
+
+    if (this._inputElement) {
+      // detach from current input element
+      if (this._sourceEditor) {
+        // save existing state first (for seamless reattach)
+        this._state = {
+          text: this._sourceEditor.getText(),
+          selection: this._sourceEditor.getSelection(),
+          readOnly: this._sourceEditor.readOnly,
+          topIndex: this._sourceEditor.getTopIndex(),
+        };
+        this._sourceEditor.destroy();
+        this._sourceEditor = null;
+      }
+
+      this.window.removeEventListener("unload",
+                                      this._onWindowUnloadBinding, false);
+      this._triggerAction("Detach");
+    }
+
+    this._inputElement = aElement;
+    if (!aElement) {
+      return;
+    }
+
+    // attach to new input element
+    this.window.addEventListener("unload", this._onWindowUnloadBinding, false);
+    this._focusOnSourceEditorReady = false;
+
+    this._sourceEditor = null; // set it only when ready (safe to use)
+
+    let sourceEditor = new SourceEditor();
+    let config = {
+      placeholderText: this._state.text, //! this is initialText (bug 680371)
+      showLineNumbers: true,
+      mode: SourceEditor.MODES.CSS,
+      readOnly: this._state.readOnly,
+      keys: this._getKeyBindings()
+    };
+
+    sourceEditor.init(aElement, config, function onSourceEditorReady() {
+      sourceEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
+                                    function onTextChanged(aEvent) {
+        this.updateStyleSheet();
+      }.bind(this));
+
+      this._sourceEditor = sourceEditor;
+
+      if (this._focusOnSourceEditorReady) {
+        this._focusOnSourceEditorReady = false;
+        sourceEditor.focus();
+      }
+
+      sourceEditor.setTopIndex(this._state.topIndex);
+      sourceEditor.setSelection(this._state.selection.start,
+                                this._state.selection.end);
+
+      this._triggerAction("Attach");
+    }.bind(this));
+  },
+
+  /**
+   * Retrieve the underlying SourceEditor instance for this StyleEditor.
+   * Can be null if not ready or Style Editor is detached/headless.
+   *
+   * @return SourceEditor
+   */
+  get sourceEditor() this._sourceEditor,
+
+  /**
+   * Setter for the read-only state of the editor.
+   *
+   * @param boolean aValue
+   *        Tells if you want the editor to be read-only or not.
+   */
+  set readOnly(aValue)
+  {
+    this._state.readOnly = aValue;
+    if (this._sourceEditor) {
+      this._sourceEditor.readOnly = aValue;
+    }
+  },
+
+  /**
+   * Getter for the read-only state of the editor.
+   *
+   * @return boolean
+   */
+  get readOnly()
+  {
+    return this._state.readOnly;
+  },
+
+  /**
+   * Retrieve the window that contains the editor.
+   * Can be null if the editor is detached/headless.
+   *
+   * @return DOMWindow
+   */
+  get window()
+  {
+    if (!this.inputElement) {
+      return null;
+    }
+    return this.inputElement.ownerDocument.defaultView;
+  },
+
+  /**
+   * Retrieve the last file this editor has been saved to or null if none.
+   *
+   * @return nsIFile
+   */
+  get savedFile() this._savedFile,
+
+  /**
+   * Import style sheet from file and load it into the editor asynchronously.
+   * "Load" action triggers when complete.
+   *
+   * @param mixed aFile
+   *        Optional nsIFile or filename string.
+   *        If not set a file picker will be shown.
+   * @param nsIWindow aParentWindow
+   *        Optional parent window for the file picker.
+   */
+  importFromFile: function SE_importFromFile(aFile, aParentWindow)
+  {
+    aFile = this._showFilePicker(aFile, false, aParentWindow);
+    if (!aFile) {
+      return;
+    }
+    this._savedFile = aFile; // remember filename for next save if any
+
+    NetUtil.asyncFetch(aFile, function onAsyncFetch(aStream, aStatus) {
+      if (!Components.isSuccessCode(aStatus)) {
+        return this._signalError(LOAD_ERROR);
+      }
+      let source = NetUtil.readInputStreamToString(aStream, aStream.available());
+      aStream.close();
+
+      this._appendNewStyleSheet(source);
+      this.clearFlag(StyleEditorFlags.ERROR);
+    }.bind(this));
+  },
+
+  /**
+    * Retrieve localized error message of last error condition, or null if none.
+    * This is set when the editor has flag StyleEditorFlags.ERROR.
+    *
+    * @see addActionListener
+    */
+  get errorMessage() this._errorMessage,
+
+  /**
+   * Tell whether the stylesheet has been loaded and ready for modifications.
+   *
+   * @return boolean
+   */
+  get isLoaded() this._loaded,
+
+  /**
+   * Load style sheet source into the editor, asynchronously.
+   * "Load" handler triggers when complete.
+   *
+   * @see addActionListener
+   */
+  load: function SE_load()
+  {
+    if (!this._styleSheet) {
+      this._flags.push(StyleEditorFlags.NEW);
+      this._appendNewStyleSheet();
+    }
+    this._loadSource();
+  },
+
+  /**
+   * Get a user-friendly name for the style sheet.
+   *
+   * @return string
+   */
+  getFriendlyName: function SE_getFriendlyName()
+  {
+    if (this.savedFile) { // reuse the saved filename if any
+      return this.savedFile.leafName;
+    }
+
+    if (this.hasFlag(StyleEditorFlags.NEW)) {
+      let index = this.styleSheetIndex + 1; // 0-indexing only works for devs
+      return _("newStyleSheet", index);
+    }
+
+    if (this.hasFlag(StyleEditorFlags.INLINE)) {
+      let index = this.styleSheetIndex + 1; // 0-indexing only works for devs
+      return _("inlineStyleSheet", index);
+    }
+
+    if (!this._friendlyName) {
+      let sheetURI = this.styleSheet.href;
+      let contentURI = this.contentDocument.baseURIObject;
+      let contentURIScheme = contentURI.scheme;
+      let contentURILeafIndex = contentURI.specIgnoringRef.lastIndexOf("/");
+      contentURI = contentURI.specIgnoringRef;
+
+      // get content base URI without leaf name (if any)
+      if (contentURILeafIndex > contentURIScheme.length) {
+        contentURI = contentURI.substring(0, contentURILeafIndex + 1);
+      }
+
+      // avoid verbose repetition of absolute URI when the style sheet URI
+      // is relative to the content URI
+      this._friendlyName = (sheetURI.indexOf(contentURI) == 0)
+                           ? sheetURI.substring(contentURI.length)
+                           : sheetURI;
+    }
+    return this._friendlyName;
+  },
+
+  /**
+   * Add a listener for significant StyleEditor actions.
+   *
+   * The listener implements IStyleEditorActionListener := {
+   *   onLoad:                 Called when the style sheet has been loaded and
+   *                           parsed.
+   *                           Arguments: (StyleEditor editor)
+   *                           @see load
+   *
+   *   onFlagChange:           Called when a flag has been set or cleared.
+   *                           Arguments: (StyleEditor editor, string flagName)
+   *                           @see setFlag
+   *
+   *   onAttach:               Called when an input element has been attached.
+   *                           Arguments: (StyleEditor editor)
+   *                           @see inputElement
+   *
+   *   onDetach:               Called when input element has been detached.
+   *                           Arguments: (StyleEditor editor)
+   *                           @see inputElement
+   *
+   *   onCommit:               Called when changes have been committed/applied
+   *                           to the live DOM style sheet.
+   *                           Arguments: (StyleEditor editor)
+   * }
+   *
+   * All listener methods are optional.
+   *
+   * @param IStyleEditorActionListener aListener
+   * @see removeActionListener
+   */
+  addActionListener: function SE_addActionListener(aListener)
+  {
+    this._actionListeners.push(aListener);
+  },
+
+  /**
+   * Remove a listener for editor actions from the current list of listeners.
+   *
+   * @param IStyleEditorActionListener aListener
+   * @see addActionListener
+   */
+  removeActionListener: function SE_removeActionListener(aListener)
+  {
+    let index = this._actionListeners.indexOf(aListener);
+    if (index != -1) {
+      this._actionListeners.splice(index, 1);
+    }
+  },
+
+  /**
+   * Editor UI flags.
+   *
+   * These are 1-bit indicators that can be used for UI feedback/indicators or
+   * extensions to track the editor status.
+   * Since they are simple strings, they promote loose coupling and can simply
+   * map to CSS class names, which allows to 'expose' indicators declaratively
+   * via CSS (including possibly complex combinations).
+   *
+   * Flag changes can be tracked via onFlagChange (@see addActionListener).
+   *
+   * @see StyleEditorFlags
+   */
+
+  /**
+   * Retrieve a space-separated string of all UI flags set on this editor.
+   *
+   * @return string
+   * @see setFlag
+   * @see clearFlag
+   */
+  get flags() this._flags.join(" "),
+
+  /**
+   * Set a flag.
+   *
+   * @param string aName
+   *        Name of the flag to set. One of StyleEditorFlags members.
+   * @return boolean
+   *         True if the flag has been set, false if flag is already set.
+   * @see StyleEditorFlags
+   */
+  setFlag: function SE_setFlag(aName)
+  {
+    let prop = aName.toUpperCase();
+    assert(StyleEditorFlags[prop], "Unknown flag: " + prop);
+
+    if (this.hasFlag(aName)) {
+      return false;
+    }
+    this._flags.push(aName);
+    this._triggerAction("FlagChange", [aName]);
+    return true;
+  },
+
+  /**
+   * Clear a flag.
+   *
+   * @param string aName
+   *        Name of the flag to clear.
+   * @return boolean
+   *         True if the flag has been cleared, false if already clear.
+   */
+  clearFlag: function SE_clearFlag(aName)
+  {
+    let index = this._flags.indexOf(aName);
+    if (index == -1) {
+      return false;
+    }
+    this._flags.splice(index, 1);
+    this._triggerAction("FlagChange", [aName]);
+    return true;
+  },
+
+  /**
+   * Toggle a flag, according to a condition.
+   *
+   * @param aCondition
+   *        If true the flag is set, otherwise cleared.
+   * @param string aName
+   *        Name of the flag to toggle.
+   * @return boolean
+   *        True if the flag has been set or cleared, ie. the flag got switched.
+   */
+  toggleFlag: function SE_toggleFlag(aCondition, aName)
+  {
+    return (aCondition) ? this.setFlag(aName) : this.clearFlag(aName);
+  },
+
+  /**
+   * Check if given flag is set.
+   *
+   * @param string aName
+   *        Name of the flag to check presence for.
+   * @return boolean
+   *         True if the flag is set, false otherwise.
+   */
+  hasFlag: function SE_hasFlag(aName) (this._flags.indexOf(aName) != -1),
+
+  /**
+   * Enable or disable style sheet.
+   *
+   * @param boolean aEnabled
+   */
+  enableStyleSheet: function SE_enableStyleSheet(aEnabled)
+  {
+    this.styleSheet.disabled = !aEnabled;
+    this.toggleFlag(this.styleSheet.disabled, StyleEditorFlags.DISABLED);
+
+    if (this._updateTask) {
+      this._updateStyleSheet(); // perform cancelled update
+    }
+  },
+
+  /**
+   * Save the editor contents into a file and set savedFile property.
+   * A file picker UI will open if file is not set and editor is not headless.
+   *
+   * @param mixed aFile
+   *        Optional nsIFile or string representing the filename to save in the
+   *        background, no UI will be displayed.
+   *        To implement 'Save' instead of 'Save as', you can pass savedFile here.
+   * @param function(nsIFile aFile) aCallback
+   *        Optional callback called when the operation has finished.
+   *        aFile has the nsIFile object for saved file or null if the operation
+   *        has failed or has been canceled by the user.
+   * @see savedFile
+   */
+  saveToFile: function SE_saveToFile(aFile, aCallback)
+  {
+    aFile = this._showFilePicker(aFile, true);
+    if (!aFile) {
+      if (aCallback) {
+        aCallback(null);
+      }
+      return;
+    }
+
+    if (this._sourceEditor) {
+      this._state.text = this._sourceEditor.getText();
+    }
+
+    let ostream = FileUtils.openSafeFileOutputStream(aFile);
+    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+                      .createInstance(Ci.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+    let istream = converter.convertToInputStream(this._state.text);
+
+    NetUtil.asyncCopy(istream, ostream, function SE_onStreamCopied(status) {
+      if (!Components.isSuccessCode(status)) {
+        if (aCallback) {
+          aCallback(null);
+        }
+        this._signalError(SAVE_ERROR);
+        return;
+      }
+      FileUtils.closeSafeFileOutputStream(ostream);
+
+      // remember filename for next save if any
+      this._friendlyName = null;
+      this._savedFile = aFile;
+      this._persistExpando();
+
+      if (aCallback) {
+        aCallback(aFile);
+      }
+      this.clearFlag(StyleEditorFlags.UNSAVED);
+      this.clearFlag(StyleEditorFlags.ERROR);
+    }.bind(this));
+  },
+
+  /**
+   * Queue a throttled task to update the live style sheet.
+   *
+   * @param boolean aImmediate
+   *        Optional. If true the update is performed immediately.
+   */
+  updateStyleSheet: function SE_updateStyleSheet(aImmediate)
+  {
+    let window = this.window;
+
+    if (this._updateTask) {
+      // cancel previous queued task not executed within throttle delay
+      window.clearTimeout(this._updateTask);
+    }
+
+    if (aImmediate) {
+      this._updateStyleSheet();
+    } else {
+      this._updateTask = window.setTimeout(this._updateStyleSheet.bind(this),
+                                           UPDATE_STYLESHEET_THROTTLE_DELAY);
+    }
+  },
+
+  /**
+   * Update live style sheet according to modifications.
+   */
+  _updateStyleSheet: function SE__updateStyleSheet()
+  {
+    this.setFlag(StyleEditorFlags.UNSAVED);
+
+    if (this.styleSheet.disabled) {
+      return;
+    }
+
+    this._updateTask = null; // reset only if we actually perform an update
+                             // (stylesheet is enabled) so that 'missed' updates
+                             // while the stylesheet is disabled can be performed
+                             // when it is enabled back. @see enableStylesheet
+
+    if (this.sourceEditor) {
+      this._state.text = this.sourceEditor.getText();
+    }
+    let source = this._state.text;
+    let oldNode = this.styleSheet.ownerNode;
+    let oldIndex = this.styleSheetIndex;
+
+    let newNode = this.contentDocument.createElement("style");
+    newNode.setAttribute("type", "text/css");
+    newNode.appendChild(this.contentDocument.createTextNode(source));
+    oldNode.parentNode.replaceChild(newNode, oldNode);
+
+    this._styleSheet = this.contentDocument.styleSheets[oldIndex];
+    this._persistExpando();
+
+    this._triggerAction("Commit");
+  },
+
+  /**
+   * Show file picker and return the file user selected.
+   *
+   * @param mixed aFile
+   *        Optional nsIFile or string representing the filename to auto-select.
+   * @param boolean aSave
+   *        If true, the user is selecting a filename to save.
+   * @param nsIWindow aParentWindow
+   *        Optional parent window. If null the parent window of the file picker
+   *        will be the window of the attached input element.
+   * @return nsIFile
+   *         The selected file or null if the user did not pick one.
+   */
+  _showFilePicker: function SE__showFilePicker(aFile, aSave, aParentWindow)
+  {
+    if (typeof(aFile) == "string") {
+      try {
+        let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+        file.initWithPath(aFile);
+        return file;
+      } catch (ex) {
+        this._signalError(aSave ? SAVE_ERROR : LOAD_ERROR);
+        return null;
+      }
+    }
+    if (aFile) {
+      return aFile;
+    }
+
+    let window = aParentWindow
+                 ? aParentWindow
+                 : this.inputElement.ownerDocument.defaultView;
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let mode = aSave ? fp.modeSave : fp.modeOpen;
+    let key = aSave ? "saveStyleSheet" : "importStyleSheet";
+
+    fp.init(window, _(key + ".title"), mode);
+    fp.appendFilters(_(key + ".filter"), "*.css");
+    fp.appendFilters(fp.filterAll);
+
+    let rv = fp.show();
+    return (rv == fp.returnCancel) ? null : fp.file;
+  },
+
+  /**
+   * Retrieve the style sheet source from the cache or from a local file.
+   */
+  _loadSource: function SE__loadSource()
+  {
+    if (!this.styleSheet.href) {
+      // this is an inline <style> sheet
+      this._flags.push(StyleEditorFlags.INLINE);
+      this._onSourceLoad(this.styleSheet.ownerNode.textContent);
+      return;
+    }
+
+    let scheme = Services.io.extractScheme(this.styleSheet.href);
+    switch (scheme) {
+      case "file":
+      case "chrome":
+      case "resource":
+        this._loadSourceFromFile(this.styleSheet.href);
+        break;
+      default:
+        this._loadSourceFromCache(this.styleSheet.href);
+        break;
+    }
+  },
+
+  /**
+   * Load source from a file or file-like resource.
+   *
+   * @param string aHref
+   *        URL for the stylesheet.
+   */
+  _loadSourceFromFile: function SE__loadSourceFromFile(aHref)
+  {
+    try {
+      NetUtil.asyncFetch(aHref, function onFetch(aStream, aStatus) {
+        if (!Components.isSuccessCode(aStatus)) {
+          return this._signalError(LOAD_ERROR);
+        }
+        let source = NetUtil.readInputStreamToString(aStream, aStream.available());
+        aStream.close();
+        this._onSourceLoad(source);
+      }.bind(this));
+    } catch (ex) {
+      this._signalError(LOAD_ERROR);
+    }
+  },
+
+  /**
+   * Load source from the HTTP cache.
+   *
+   * @param string aHref
+   *        URL for the stylesheet.
+   */
+  _loadSourceFromCache: function SE__loadSourceFromCache(aHref)
+  {
+    try {
+      let cacheService = Cc["@mozilla.org/network/cache-service;1"]
+                           .getService(Ci.nsICacheService);
+      let session = cacheService.createSession("HTTP", Ci.nsICache.STORE_ANYWHERE, true);
+      session.doomEntriesIfExpired = false;
+      session.asyncOpenCacheEntry(aHref, Ci.nsICache.ACCESS_READ, {
+        onCacheEntryAvailable: this._onCacheEntryAvailable.bind(this)
+      });
+    } catch (ex) {
+      this._signalError(LOAD_ERROR);
+    }
+  },
+
+   /**
+    * The nsICacheListener.onCacheEntryAvailable method implementation used when
+    * the style sheet source is loaded from the browser cache.
+    *
+    * @param nsICacheEntryDescriptor aEntry
+    * @param nsCacheAccessMode aMode
+    * @param integer aStatus
+    */
+  _onCacheEntryAvailable: function SE__onCacheEntryAvailable(aEntry, aMode, aStatus)
+  {
+    if (!Components.isSuccessCode(aStatus)) {
+      return this._signalError(LOAD_ERROR);
+    }
+
+    let stream = aEntry.openInputStream(0);
+    let chunks = [];
+    let streamListener = { // nsIStreamListener inherits nsIRequestObserver
+      onStartRequest: function (aRequest, aContext, aStatusCode) {
+      },
+      onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
+        chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
+      },
+      onStopRequest: function (aRequest, aContext, aStatusCode) {
+        this._onSourceLoad(chunks.join(""));
+      }.bind(this),
+    };
+
+    let head = aEntry.getMetaDataElement("response-head");
+    if (/^Content-Encoding:\s*gzip/mi.test(head)) {
+      let converter = Cc["@mozilla.org/streamconv;1?from=gzip&to=uncompressed"]
+                        .createInstance(Ci.nsIStreamConverter);
+      converter.asyncConvertData("gzip", "uncompressed", streamListener, null);
+      streamListener = converter; // proxy original listener via converter
+    }
+
+    try {
+      streamListener.onStartRequest(null, null);
+      while (stream.available()) {
+        streamListener.onDataAvailable(null, null, stream, 0, stream.available());
+      }
+      streamListener.onStopRequest(null, null, 0);
+    } catch (ex) {
+      this._signalError(LOAD_ERROR);
+    } finally {
+      try {
+        stream.close();
+      } catch (ex) {
+        // swallow (some stream implementations can auto-close at eos)
+      }
+      aEntry.close();
+    }
+  },
+
+  /**
+   * Called when source has been loaded.
+   *
+   * @param string aSourceText
+   */
+  _onSourceLoad: function SE__onSourceLoad(aSourceText)
+  {
+    this._restoreExpando();
+    this._state.text = prettifyCSS(aSourceText);
+    this._loaded = true;
+    this._triggerAction("Load");
+  },
+
+  /**
+   * Create a new style sheet and append it to the content document.
+   *
+   * @param string aText
+   *        Optional CSS text.
+   */
+  _appendNewStyleSheet: function SE__appendNewStyleSheet(aText)
+  {
+    let document = this.contentDocument;
+    let parent = document.documentElement;
+    let style = document.createElement("style");
+    style.setAttribute("type", "text/css");
+    if (aText) {
+      style.appendChild(document.createTextNode(aText));
+    }
+    parent.appendChild(style);
+
+    this._styleSheet = document.styleSheets[document.styleSheets.length - 1];
+    this._flags.push(aText ? StyleEditorFlags.IMPORTED : StyleEditorFlags.NEW);
+    if (aText) {
+      this._onSourceLoad(aText);
+    }
+  },
+
+  /**
+   * Signal an error to the user.
+   *
+   * @param string aErrorCode
+   *        String name for the localized error property in the string bundle.
+   * @param ...rest
+   *        Optional arguments to pass for message formatting.
+   * @see StyleEditorUtil._
+   */
+  _signalError: function SE__signalError(aErrorCode)
+  {
+    this._errorMessage = _.apply(null, arguments);
+    this.setFlag(StyleEditorFlags.ERROR);
+  },
+
+  /**
+   * Trigger named action handler in listeners.
+   *
+   * @param string aName
+   *        Name of the action to trigger.
+   * @param Array aArgs
+   *        Optional array of arguments to pass to the listener(s).
+   * @see addActionListener
+   */
+  _triggerAction: function SE__triggerAction(aName, aArgs)
+  {
+    // insert the origin editor instance as first argument
+    if (!aArgs) {
+      aArgs = [this];