Merge last green changeset of mozilla-inbound to mozilla-central
authorEd Morley <bmo@edmorley.co.uk>
Wed, 07 Dec 2011 09:27:36 +0000
changeset 84130 489f2d51b01124a50fb76e6efc795b07e95d4f3a
parent 84051 658fad825c36eae247dbd43df3b1d456d95fb39f (current diff)
parent 84129 3080aa9f675d8fc53be2771a7bc825190b9c4903 (diff)
child 84131 dfff3e59ef235a8b0906d7f135d3c5efe2edb338
child 84147 f4b31a1c0dcd2533a8b41caf398ffb45784a9e54
push id114
push userffxbld
push dateFri, 09 Mar 2012 01:01:18 +0000
treeherdermozilla-release@c081ebf13261 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.0a1
first release with
nightly win64
489f2d51b011 / 11.0a1 / 20111207031110 / files
nightly linux32
nightly linux64
nightly mac
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win64
Merge last green changeset of mozilla-inbound to mozilla-central
b2g/installer/package-manifest.in
content/base/public/nsIDOMGCParticipant.h
dom/telephony/Radio.cpp
dom/telephony/Radio.h
dom/telephony/worker-component/Makefile.in
dom/telephony/worker-component/nsIRadioInterface.idl
dom/telephony/worker-component/nsITelephonyWorker.idl
dom/telephony/worker-component/nsTelephonyWorker.js
dom/telephony/worker-component/nsTelephonyWorker.manifest
dom/telephony/worker-component/ril_consts.js
dom/telephony/worker-component/ril_worker.js
embedding/android/AndroidManifest.xml.in
embedding/android/GeckoAppShell.java
embedding/android/Makefile.in
js/src/jit-test/tests/basic/arith.js
js/src/jit-test/tests/basic/bug489098.js
js/src/jit-test/tests/basic/jitstatsArchFlags.js
js/src/jit-test/tests/basic/testArrayIn.js
js/src/jit-test/tests/basic/testBreak.js
js/src/jit-test/tests/basic/testCallNull.js
js/src/jit-test/tests/basic/testContinueWithLabel2.js
js/src/jit-test/tests/basic/testHOTLOOPCorrectness.js
js/src/jit-test/tests/basic/testInitMethod.js
js/src/jit-test/tests/basic/testMethodInitDeref.js
js/src/jit-test/tests/basic/testMethodInitUneval.js
js/src/jit-test/tests/basic/testMethodOverride.js
js/src/jit-test/tests/basic/testNewDate.js
js/src/jit-test/tests/basic/testRUNLOOPCorrectness.js
js/src/jit-test/tests/basic/testRegExpLiteral.js
js/src/jit-test/tests/basic/testSetMethod.js
js/src/jit-test/tests/basic/testSideExitInConstructor.js
js/src/jit-test/tests/basic/testStringPropIncrement.js
js/src/jit-test/tests/basic/wrap-primitive-this.js
js/src/jit-test/tests/jaeger/bug580884-2.js
mobile/xul/installer/package-manifest.in
testing/mozbase/manifestdestiny/README.txt
testing/mozbase/manifestdestiny/manifestparser.py
testing/mozbase/mozhttpd/mozhttpd.py
testing/mozbase/mozinfo/mozinfo.py
testing/mozbase/mozinstall/mozinstall.py
copy from mobile/xul/LICENSE
copy to b2g/LICENSE
copy from mobile/xul/Makefile.in
copy to b2g/Makefile.in
--- a/mobile/xul/Makefile.in
+++ b/b2g/Makefile.in
@@ -10,49 +10,39 @@
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
 # The Original Code is Mozilla.
 #
 # The Initial Developer of the Original Code is
 # the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2007
+# Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Mark Finkle <mfinkle@mozilla.com>
-#   Joel Maher <jmaher@mozilla.com>
+#   Chris Jones <jones.chris.g@gmail.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-DEPTH      = ../..
+DEPTH      = ..
 topsrcdir  = @top_srcdir@
 srcdir     = @srcdir@
 VPATH      = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS = chrome locales components modules themes/core app
-
-ifndef LIBXUL_SDK
-PARALLEL_DIRS += $(DEPTH)/xulrunner/tools/redit
-endif
+DIRS = chrome locales app
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/testing/testsuite-targets.mk
-
-package-mobile-tests:
-	$(MAKE) stage-mochitest DIST_BIN=$(DEPTH)/$(DIST)/bin/xulrunner
-	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
-	@(cd $(PKG_STAGE) && tar $(TAR_CREATE_FLAGS) - *) | bzip2 -f > $(DIST)/$(PKG_PATH)$(TEST_PACKAGE)
copy from mobile/xul/app/Makefile.in
copy to b2g/app/Makefile.in
--- a/mobile/xul/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -10,99 +10,100 @@
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
 # The Original Code is Mozilla.
 #
 # The Initial Developer of the Original Code is
 # the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2007
+# Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Mark Finkle <mfinkle@mozilla.com>
+#   Chris Jones <jones.chris.g@gmail.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-DEPTH     = ../../..
+DEPTH     = ../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS = profile/extensions
-
-PREF_JS_EXPORTS = $(srcdir)/mobile.js
+PREF_JS_EXPORTS = $(srcdir)/b2g.js
 
 ifndef LIBXUL_SDK
-ifneq (Android,$(OS_TARGET))
 PROGRAM=$(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
 LOCAL_INCLUDES += -I$(DEPTH)/build
 
 DEFINES += -DXPCOM_GLUE
 STL_FLAGS=
 
+LIBS += $(JEMALLOC_LIBS)
+
 LIBS += \
   $(EXTRA_DSO_LIBS) \
   $(XPCOM_STANDALONE_GLUE_LDOPTS) \
   $(NULL)
 
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-LIBS += \
-  $(LIBXUL_DIST)/../widget/src/qt/faststartupqt/$(LIB_PREFIX)faststartupqt.$(LIB_SUFFIX) \
-  $(MOZ_QT_LIBS) \
-  $(NULL)
-LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/qt/faststartupqt $(TK_CFLAGS)
-endif
-
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS += $(call EXPAND_LIBNAME,version)
 endif
 
 ifdef _MSC_VER
 # Always enter a Windows program through wmain, whether or not we're
 # a console application.
 WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
 endif
-endif
 endif #LIBXUL_SDK
 
-# Make sure the standalone glue doesn't try to get libxpcom.so from mobile/app.
+# Make sure the standalone glue doesn't try to get libxpcom.so from b2g/app.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/rules.mk
 
-APP_ICON = mobile
+APP_ICON = b2g
 
 DEFINES += \
   -DAPP_NAME=$(MOZ_APP_NAME) \
   -DAPP_VERSION=$(MOZ_APP_VERSION) \
   -DMOZ_UPDATER=$(MOZ_UPDATER) \
   $(NULL)
 
+# strip a trailing slash from the repo URL because it's not always present,
+# and we want to construct a working URL in buildconfig.html
+# make+shell+sed = awful
+_dollar=$$
+SOURCE_REPO := $(shell cd $(srcdir)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
+# extra sanity check for old versions of hg
+# that don't support showconfig
+ifeq (http,$(patsubst http%,http,$(SOURCE_REPO)))
+DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
+endif
+
 ifeq ($(OS_ARCH),WINNT)
 REDIT_PATH = $(LIBXUL_DIST)/bin
 endif
 
 APP_BINARY = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 
@@ -126,17 +127,17 @@ else
 APPFILES = MacOS
 endif
 
 libs repackage::
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
-	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%APP_BINARY%/$(APP_BINARY)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
+	sed -e "s/%MOZ_APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MOZ_APP_NAME%/$(MOZ_APP_NAME)/" -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%APP_BINARY%/$(APP_BINARY)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/xulrunner$(BIN_SUFFIX) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(APP_BINARY)
 	rsync -a --exclude nsinstall --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(DIST)/$(APP_NAME).app/Contents/Frameworks
 else
 	rm -f $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
@@ -152,21 +153,16 @@ ifdef LIBXUL_SDK
 endif
 ifndef SKIP_COPY_XULRUNNER
 ifdef LIBXUL_SDK
 	$(NSINSTALL) -D $(DIST)/bin/xulrunner
 	(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
 endif
 endif # SKIP_COPY_XULRUNNER
 
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-	$(NSINSTALL) -D $(DIST)/bin/res/drawable
-	cp $(srcdir)/maemo/* $(DIST)/bin/res/drawable/
-	cp $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/favicon32.png $(DIST)/bin/res/drawable/
-endif
 	$(NSINSTALL) -D $(DIST)/bin/chrome/icons/default
 
 ifeq ($(OS_ARCH),WINNT)
 	cp $(srcdir)/$(APP_ICON).ico $(DIST)/bin/chrome/icons/default/$(APP_ICON).ico
 	$(REDIT_PATH)/redit$(HOST_BIN_SUFFIX) $(DIST)/bin/$(APP_BINARY) $(srcdir)/$(APP_ICON).ico
 endif
 
 endif
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..38312abac42830818edef700470cf1c59b25bb81
GIT binary patch
literal 4286
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
new file mode 100644
--- /dev/null
+++ b/b2g/app/b2g.js
@@ -0,0 +1,395 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Brubeck <mbrubeck@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#filter substitution
+
+pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.xul");
+pref("general.useragent.compatMode.firefox", true);
+pref("browser.chromeURL", "chrome://browser/content/");
+#ifdef MOZ_OFFICIAL_BRANDING
+pref("browser.homescreenURL", "file:///system/home/homescreen.html");
+#else
+pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system/home/homescreen.html");
+#endif
+
+// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
+pref("browser.viewport.scaleRatio", -1);
+
+/* allow scrollbars to float above chrome ui */
+pref("ui.scrollbarsCanOverlapContent", 1);
+
+/* cache prefs */
+pref("browser.cache.disk.enable", false);
+pref("browser.cache.disk.capacity", 0); // kilobytes
+pref("browser.cache.disk.smart_size.enabled", false);
+pref("browser.cache.disk.smart_size.first_run", false);
+
+pref("browser.cache.memory.enable", true);
+pref("browser.cache.memory.capacity", 1024); // kilobytes
+
+/* image cache prefs */
+pref("image.cache.size", 1048576); // bytes
+
+/* offline cache prefs */
+pref("browser.offline-apps.notify", true);
+pref("browser.cache.offline.enable", true);
+pref("browser.cache.offline.capacity", 5120); // kilobytes
+pref("offline-apps.quota.max", 2048); // kilobytes
+pref("offline-apps.quota.warn", 1024); // kilobytes
+
+/* protocol warning prefs */
+pref("network.protocol-handler.warn-external.tel", false);
+pref("network.protocol-handler.warn-external.mailto", false);
+pref("network.protocol-handler.warn-external.vnd.youtube", false);
+
+/* http prefs */
+pref("network.http.pipelining", true);
+pref("network.http.pipelining.ssl", true);
+pref("network.http.proxy.pipelining", true);
+pref("network.http.pipelining.maxrequests" , 6);
+pref("network.http.keep-alive.timeout", 600);
+pref("network.http.max-connections", 6);
+pref("network.http.max-connections-per-server", 4);
+pref("network.http.max-persistent-connections-per-server", 4);
+pref("network.http.max-persistent-connections-per-proxy", 4);
+
+// See bug 545869 for details on why these are set the way they are
+pref("network.buffer.cache.count", 24);
+pref("network.buffer.cache.size",  16384);
+
+/* session history */
+pref("browser.sessionhistory.max_total_viewers", 1);
+pref("browser.sessionhistory.max_entries", 50);
+
+/* session store */
+pref("browser.sessionstore.resume_session_once", false);
+pref("browser.sessionstore.resume_from_crash", true);
+pref("browser.sessionstore.resume_from_crash_timeout", 60); // minutes
+pref("browser.sessionstore.interval", 10000); // milliseconds
+pref("browser.sessionstore.max_tabs_undo", 1);
+
+/* these should help performance */
+pref("mozilla.widget.force-24bpp", true);
+pref("mozilla.widget.use-buffer-pixmap", true);
+pref("mozilla.widget.disable-native-theme", true);
+pref("layout.reflow.synthMouseMove", false);
+
+/* download manager (don't show the window or alert) */
+pref("browser.download.useDownloadDir", true);
+pref("browser.download.folderList", 1); // Default to ~/Downloads
+pref("browser.download.manager.showAlertOnComplete", false);
+pref("browser.download.manager.showAlertInterval", 2000);
+pref("browser.download.manager.retention", 2);
+pref("browser.download.manager.showWhenStarting", false);
+pref("browser.download.manager.closeWhenDone", true);
+pref("browser.download.manager.openDelay", 0);
+pref("browser.download.manager.focusWhenStarting", false);
+pref("browser.download.manager.flashCount", 2);
+pref("browser.download.manager.displayedHistoryDays", 7);
+
+/* download alerts (disabled above) */
+pref("alerts.slideIncrement", 1);
+pref("alerts.slideIncrementTime", 10);
+pref("alerts.totalOpenTime", 6000);
+pref("alerts.height", 50);
+
+/* download helper */
+pref("browser.helperApps.deleteTempFileOnExit", false);
+
+/* password manager */
+pref("signon.rememberSignons", true);
+pref("signon.expireMasterPassword", false);
+pref("signon.SignonFileName", "signons.txt");
+
+/* autocomplete */
+pref("browser.formfill.enable", true);
+
+/* spellcheck */
+pref("layout.spellcheckDefault", 0);
+
+/* block popups by default, and notify the user about blocked popups */
+pref("dom.disable_open_during_load", true);
+pref("privacy.popups.showBrowserMessage", true);
+
+pref("keyword.enabled", true);
+pref("keyword.URL", "http://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
+
+pref("accessibility.typeaheadfind", false);
+pref("accessibility.typeaheadfind.timeout", 5000);
+pref("accessibility.typeaheadfind.flashBar", 1);
+pref("accessibility.typeaheadfind.linksonly", false);
+pref("accessibility.typeaheadfind.casesensitive", 0);
+
+// pointer to the default engine name
+pref("browser.search.defaultenginename", "chrome://browser/locale/region.properties");
+
+// SSL error page behaviour
+pref("browser.ssl_override_behavior", 2);
+pref("browser.xul.error_pages.expert_bad_cert", false);
+
+// disable logging for the search service by default
+pref("browser.search.log", false);
+
+// disable updating
+pref("browser.search.update", false);
+pref("browser.search.update.log", false);
+pref("browser.search.updateinterval", 6);
+
+// enable search suggestions by default
+pref("browser.search.suggest.enabled", true);
+
+// tell the search service that we don't really expose the "current engine"
+pref("browser.search.noCurrentEngine", true);
+
+// enable xul error pages
+pref("browser.xul.error_pages.enabled", true);
+
+// disable color management
+pref("gfx.color_management.mode", 0);
+
+// don't allow JS to move and resize existing windows
+pref("dom.disable_window_move_resize", true);
+
+// prevent click image resizing for nsImageDocument
+pref("browser.enable_click_image_resizing", false);
+
+// controls which bits of private data to clear. by default we clear them all.
+pref("privacy.item.cache", true);
+pref("privacy.item.cookies", true);
+pref("privacy.item.offlineApps", true);
+pref("privacy.item.history", true);
+pref("privacy.item.formdata", true);
+pref("privacy.item.downloads", true);
+pref("privacy.item.passwords", true);
+pref("privacy.item.sessions", true);
+pref("privacy.item.geolocation", true);
+pref("privacy.item.siteSettings", true);
+pref("privacy.item.syncAccount", true);
+
+// URL to the Learn More link XXX this is the firefox one.  Bug 495578 fixes this.
+pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/geolocation/");
+
+// base url for the wifi geolocation network provider
+pref("geo.wifi.uri", "https://maps.googleapis.com/maps/api/browserlocation/json");
+
+// enable geo
+pref("geo.enabled", true);
+
+// content sink control -- controls responsiveness during page load
+// see https://bugzilla.mozilla.org/show_bug.cgi?id=481566#c9
+pref("content.sink.enable_perf_mode",  2); // 0 - switch, 1 - interactive, 2 - perf
+pref("content.sink.pending_event_mode", 0);
+pref("content.sink.perf_deflect_count", 1000000);
+pref("content.sink.perf_parse_time", 50000000);
+
+pref("javascript.options.mem.high_water_mark", 32);
+
+// Maximum scripts runtime before showing an alert
+pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
+pref("dom.max_script_run_time", 20);
+
+// plugins
+pref("plugin.disable", true);
+pref("dom.ipc.plugins.enabled", true);
+
+// product URLs
+// The breakpad report server to link to in about:crashes
+pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
+pref("app.releaseNotesURL", "http://www.mozilla.com/%LOCALE%/b2g/%VERSION%/releasenotes/");
+pref("app.support.baseURL", "http://support.mozilla.com/b2g");
+pref("app.feedbackURL", "http://input.mozilla.com/feedback/");
+pref("app.privacyURL", "http://www.mozilla.com/%LOCALE%/m/privacy.html");
+pref("app.creditsURL", "http://www.mozilla.org/credits/");
+pref("app.featuresURL", "http://www.mozilla.com/%LOCALE%/b2g/features/");
+pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/b2g/faq/");
+
+// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
+pref("security.alternate_certificate_error_page", "certerror");
+
+pref("security.warn_viewing_mixed", false); // Warning is disabled.  See Bug 616712.
+
+// Override some named colors to avoid inverse OS themes
+pref("ui.-moz-dialog", "#efebe7");
+pref("ui.-moz-dialogtext", "#101010");
+pref("ui.-moz-field", "#fff");
+pref("ui.-moz-fieldtext", "#1a1a1a");
+pref("ui.-moz-buttonhoverface", "#f3f0ed");
+pref("ui.-moz-buttonhovertext", "#101010");
+pref("ui.-moz-combobox", "#fff");
+pref("ui.-moz-comboboxtext", "#101010");
+pref("ui.buttonface", "#ece7e2");
+pref("ui.buttonhighlight", "#fff");
+pref("ui.buttonshadow", "#aea194");
+pref("ui.buttontext", "#101010");
+pref("ui.captiontext", "#101010");
+pref("ui.graytext", "#b1a598");
+pref("ui.highlight", "#fad184");
+pref("ui.highlighttext", "#1a1a1a");
+pref("ui.infobackground", "#f5f5b5");
+pref("ui.infotext", "#000");
+pref("ui.menu", "#f7f5f3");
+pref("ui.menutext", "#101010");
+pref("ui.threeddarkshadow", "#000");
+pref("ui.threedface", "#ece7e2");
+pref("ui.threedhighlight", "#fff");
+pref("ui.threedlightshadow", "#ece7e2");
+pref("ui.threedshadow", "#aea194");
+pref("ui.window", "#efebe7");
+pref("ui.windowtext", "#101010");
+pref("ui.windowframe", "#efebe7");
+
+// replace newlines with spaces on paste into single-line text boxes
+pref("editor.singleLine.pasteNewlines", 2);
+
+// threshold where a tap becomes a drag, in 1/240" reference pixels
+// The names of the preferences are to be in sync with nsEventStateManager.cpp
+pref("ui.dragThresholdX", 25);
+pref("ui.dragThresholdY", 25);
+
+// Layers Acceleration
+pref("layers.acceleration.disabled", false);
+
+// Web Notifications
+pref("notification.feature.enabled", true);
+
+// IndexedDB
+pref("indexedDB.feature.enabled", true);
+pref("dom.indexedDB.warningQuota", 5);
+
+// prevent video elements from preloading too much data
+pref("media.preload.default", 1); // default to preload none
+pref("media.preload.auto", 2);    // preload metadata if preload=auto
+
+//  0: don't show fullscreen keyboard
+//  1: always show fullscreen keyboard
+// -1: show fullscreen keyboard based on threshold pref
+pref("widget.ime.android.landscape_fullscreen", -1);
+pref("widget.ime.android.fullscreen_threshold", 250); // in hundreths of inches
+
+// optimize images memory usage
+pref("image.mem.decodeondraw", true);
+pref("content.image.allow_locking", false);
+pref("image.mem.min_discard_timeout_ms", 10000);
+
+// enable touch events interfaces
+pref("dom.w3c_touch_events.enabled", true);
+pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
+pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
+
+#ifdef MOZ_SAFE_BROWSING
+// Safe browsing does nothing unless this pref is set
+pref("browser.safebrowsing.enabled", true);
+
+// Prevent loading of pages identified as malware
+pref("browser.safebrowsing.malware.enabled", true);
+
+// Non-enhanced mode (local url lists) URL list to check for updates
+pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.2");
+
+pref("browser.safebrowsing.dataProvider", 0);
+
+// Does the provider name need to be localizable?
+pref("browser.safebrowsing.provider.0.name", "Google");
+pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.2");
+pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
+pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.2");
+
+// HTML report pages
+pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
+pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
+pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
+pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}");
+pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}");
+
+// FAQ URLs
+pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/phishing-protection/");
+pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/geolocation/");
+
+// Name of the about: page contributed by safebrowsing to handle display of error
+// pages on phishing/malware hits.  (bug 399233)
+pref("urlclassifier.alternate_error_page", "blocked");
+
+// The number of random entries to send with a gethash request.
+pref("urlclassifier.gethashnoise", 4);
+
+// The list of tables that use the gethash request to confirm partial results.
+pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
+
+// If an urlclassifier table has not been updated in this number of seconds,
+// a gethash request will be forced to check that the result is still in
+// the database.
+pref("urlclassifier.confirm-age", 2700);
+
+// Maximum size of the sqlite3 cache during an update, in bytes
+pref("urlclassifier.updatecachemax", 4194304);
+
+// URL for checking the reason for a malware warning.
+pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
+#endif
+
+// True if this is the first time we are showing about:firstrun
+pref("browser.firstrun.show.uidiscovery", true);
+pref("browser.firstrun.show.localepicker", true);
+
+// initiated by a user
+pref("content.ime.strict_policy", true);
+
+// True if you always want dump() to work
+//
+// On Android, you also need to do the following for the output
+// to show up in logcat:
+//
+// $ adb shell stop
+// $ adb shell setprop log.redirect-stdio true
+// $ adb shell start
+pref("browser.dom.window.dump.enabled", false);
+
+
+
+// Temporarily relax file:// origin checks so that we can use <img>s
+// from other dirs as webgl textures and more.  Remove me when we have
+// installable apps or wifi support.
+pref("security.fileuri.strict_origin_policy", false);
+
+// Temporarily force-enable GL compositing.  This is default-disabled
+// deep within the bowels of the widgetry system.  Remove me when GL
+// compositing isn't default disabled in widget/src/android.
+pref("layers.acceleration.force-enabled", true);
+
+// screen.enabled and screen.brightness properties.
+pref("dom.screenEnabledProperty.enabled", true);
+pref("dom.screenBrightnessProperty.enabled", true);
copy from mobile/xul/app/macbuild/Contents/Info.plist.in
copy to b2g/app/macbuild/Contents/Info.plist.in
--- a/mobile/xul/app/macbuild/Contents/Info.plist.in
+++ b/b2g/app/macbuild/Contents/Info.plist.in
@@ -24,17 +24,17 @@
 				<string>HTML</string>
 			</array>
 			<key>CFBundleTypeRole</key>
 			<string>Viewer</string>
 		</dict>
 		<dict>
 			<key>CFBundleTypeExtensions</key>
 			<array>
-			    <string>text</string>
+			  <string>text</string>
 				<string>txt</string>
 				<string>js</string>
 				<string>log</string>
 				<string>css</string>
 				<string>xul</string>
 				<string>rdf</string>
 			</array>
 			<key>CFBundleTypeIconFile</key>
@@ -67,25 +67,25 @@
 				<string>JPEG</string>
 				<string>PNGf</string>
 			</array>
 			<key>CFBundleTypeRole</key>
 			<string>Viewer</string>
 		</dict>
 	</array>
 	<key>CFBundleExecutable</key>
-	<string>fennec</string>
+	<string>%MOZ_APP_NAME%</string>
 	<key>CFBundleGetInfoString</key>
 	<string>%APP_NAME% %APP_VERSION%</string>
 	<key>CFBundleIconFile</key>
-	<string>fennec</string>
+	<string>%MOZ_APP_NAME%</string>
 	<key>CFBundleIdentifier</key>
-	<string>org.mozilla.fennec</string>
+	<string>org.mozilla.b2g</string>
 	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
+	<string>%MOZ_APP_VERSION%</string>
 	<key>CFBundleName</key>
 	<string>%APP_NAME%</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
 	<string>%APP_VERSION%</string>
 	<key>CFBundleSignature</key>
 	<string>MOZB</string>
copy from mobile/xul/app/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
copy to b2g/app/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
copy from mobile/xul/app/nsBrowserApp.cpp
copy to b2g/app/nsBrowserApp.cpp
--- a/mobile/xul/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -64,23 +64,16 @@
 #define snprintf _snprintf
 #define strcasecmp _stricmp
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
-#if MOZ_PLATFORM_MAEMO == 6
-#include "nsFastStartupQt.h"
-// this used by nsQAppInstance, but defined only in nsAppRunner
-// FastStartupQt using gArgc/v so we need to define it here
-int    gArgc;
-char **gArgv;
-#endif
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   PRUnichar msg[2048];
@@ -206,35 +199,16 @@ static int do_main(const char *exePath, 
       return 255;
     }
     result = XRE_main(argc, argv, &sAppData);
   }
 
   return result;
 }
 
-#if MOZ_PLATFORM_MAEMO == 6
-static bool
-GeckoPreLoader(const char* execPath)
-{
-  nsresult rv = XPCOMGlueStartup(execPath);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't load XPCOM.\n");
-    return false;
-  }
-
-  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't load XRE functions.\n");
-    return false;
-  }
-  return true;
-}
-#endif
-
 int main(int argc, char* argv[])
 {
   char exePath[MAXPATHLEN];
 
   nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't calculate the application directory.\n");
     return 255;
@@ -259,34 +233,30 @@ int main(int argc, char* argv[])
   IO_COUNTERS ioCounters;
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
   if (gotCounters && !ioCounters.ReadOperationCount)
 #endif
   {
       XPCOMGlueEnablePreload();
   }
 
-#if MOZ_PLATFORM_MAEMO == 6
-  nsFastStartup startup;
-  startup.CreateFastStartup(argc, argv, exePath, GeckoPreLoader);
-#else
+
   rv = XPCOMGlueStartup(exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XPCOM.\n");
     return 255;
   }
   // Reset exePath so that it is the directory name and not the xpcom dll name
   *lastSlash = 0;
 
   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XRE functions.\n");
     return 255;
   }
-#endif
 
 #ifdef XRE_HAS_DLL_BLOCKLIST
   XRE_SetupDllBlocklist();
 #endif
 
   if (gotCounters) {
 #if defined(XP_WIN)
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
copy from mobile/xul/branding/official/Makefile.in
copy to b2g/branding/official/Makefile.in
--- a/mobile/xul/branding/official/Makefile.in
+++ b/b2g/branding/official/Makefile.in
@@ -29,17 +29,17 @@
 # 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 = ../../../..
+DEPTH = ../../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
 	content \
copy from mobile/xul/branding/official/android-resources.mn
copy to b2g/branding/official/android-resources.mn
--- a/mobile/xul/branding/official/android-resources.mn
+++ b/b2g/branding/official/android-resources.mn
@@ -1,6 +1,1 @@
-mobile/xul/app/android/drawable/alertaddons.png
-mobile/xul/app/android/drawable/alertdownloads.png
-mobile/xul/branding/official/content/splash.png
-mobile/xul/branding/official/content/splash_v9.9.png
-mobile/xul/branding/official/content/splash_v8.9.png
-mobile/xul/branding/official/content/favicon32.png
+b2g/branding/official/content/splash.png
copy from mobile/xul/branding/official/configure.sh
copy to b2g/branding/official/configure.sh
--- a/mobile/xul/branding/official/configure.sh
+++ b/b2g/branding/official/configure.sh
@@ -1,3 +1,3 @@
-MOZ_APP_DISPLAYNAME=Firefox
-ANDROID_PACKAGE_NAME=org.mozilla.firefox
+MOZ_APP_DISPLAYNAME=B2G
+ANDROID_PACKAGE_NAME=org.mozilla.b2g
 MOZ_UPDATER=
copy from mobile/xul/branding/official/content/Makefile.in
copy to b2g/branding/official/content/Makefile.in
--- a/mobile/xul/branding/official/content/Makefile.in
+++ b/b2g/branding/official/content/Makefile.in
@@ -1,25 +1,12 @@
 # Branding Makefile
 #  - jars chrome artwork
 
-DEPTH = ../../../../..
+DEPTH = ../../../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
 
-LINUX_BRANDING_FILES = \
-	fennec_26x26.png \
-	fennec_40x40.png \
-	fennec_48x48.png \
-	fennec_72x72.png \
-	fennec_scalable.png \
-	fennec_maemo_icon26.txt \
-	$(NULL)
-
-export::
-	$(NSINSTALL) -D $(DIST)/branding
-	cp $(addprefix $(srcdir)/, $(LINUX_BRANDING_FILES)) $(DIST)/branding/
-	$(NSINSTALL) -D $(DIST)/install
copy from mobile/xul/branding/official/content/about.png
copy to b2g/branding/official/content/about.png
copy from mobile/xul/branding/official/content/favicon32.png
copy to b2g/branding/official/content/favicon32.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b7513c2e4689ae656c99a0e79ae266a5931594e3
GIT binary patch
literal 5302
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
IM6N<$g8mX-d;kCd
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c8bee8fca98d4e57315f1198594ff31d48caefad
GIT binary patch
literal 8267
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
JPDHLkV1lvM5PJXs
copy from mobile/xul/branding/official/content/jar.mn
copy to b2g/branding/official/content/jar.mn
copy from mobile/xul/branding/official/content/logo.png
copy to b2g/branding/official/content/logo.png
copy from mobile/xul/branding/official/content/logoWordmark.png
copy to b2g/branding/official/content/logoWordmark.png
copy from mobile/xul/branding/official/content/splash.png
copy to b2g/branding/official/content/splash.png
copy from mobile/xul/branding/official/locales/Makefile.in
copy to b2g/branding/official/locales/Makefile.in
--- a/mobile/xul/branding/official/locales/Makefile.in
+++ b/b2g/branding/official/locales/Makefile.in
@@ -29,19 +29,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 *****
 
-DEPTH          = ../../../../..
+DEPTH          = ../../../..
 topsrcdir      = @top_srcdir@
 srcdir         = @srcdir@
 VPATH          = @srcdir@
-relativesrcdir = mobile/branding/official/locales
+relativesrcdir = b2g/branding/official/locales
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(AB_CD)
 
 include $(topsrcdir)/config/rules.mk
copy from mobile/xul/branding/official/locales/en-US/brand.dtd
copy to b2g/branding/official/locales/en-US/brand.dtd
--- a/mobile/xul/branding/official/locales/en-US/brand.dtd
+++ b/b2g/branding/official/locales/en-US/brand.dtd
@@ -1,4 +1,4 @@
-<!ENTITY  brandShortName  "Firefox">
-<!ENTITY  brandFullName   "Mozilla Firefox">
+<!ENTITY  brandShortName  "B2G">
+<!ENTITY  brandFullName   "Mozilla B2G">
 <!ENTITY  vendorShortName "Mozilla">
-<!ENTITY  logoTrademark   "Firefox and the Firefox logos are trademarks of the Mozilla Foundation.">
+<!ENTITY  logoTrademark   "B2G and the B2G logos are trademarks of the Mozilla Foundation.">
copy from mobile/xul/branding/official/locales/en-US/brand.properties
copy to b2g/branding/official/locales/en-US/brand.properties
--- a/mobile/xul/branding/official/locales/en-US/brand.properties
+++ b/b2g/branding/official/locales/en-US/brand.properties
@@ -1,2 +1,2 @@
-brandShortName=Firefox
-brandFullName=Mozilla Firefox
+brandShortName=B2G
+brandFullName=Mozilla B2G
copy from mobile/xul/branding/official/locales/jar.mn
copy to b2g/branding/official/locales/jar.mn
copy from mobile/xul/branding/unofficial/Makefile.in
copy to b2g/branding/unofficial/Makefile.in
--- a/mobile/xul/branding/unofficial/Makefile.in
+++ b/b2g/branding/unofficial/Makefile.in
@@ -29,17 +29,17 @@
 # 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 = ../../../..
+DEPTH = ../../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
 	content \
copy from mobile/xul/branding/unofficial/android-resources.mn
copy to b2g/branding/unofficial/android-resources.mn
--- a/mobile/xul/branding/unofficial/android-resources.mn
+++ b/b2g/branding/unofficial/android-resources.mn
@@ -1,6 +1,1 @@
-mobile/xul/app/android/drawable/alertaddons.png
-mobile/xul/app/android/drawable/alertdownloads.png
-mobile/xul/branding/unofficial/content/splash.png
-mobile/xul/branding/unofficial/content/splash_v9.9.png
-mobile/xul/branding/unofficial/content/splash_v8.9.png
-mobile/xul/branding/unofficial/content/favicon32.png
+b2g/branding/unofficial/content/splash.png
copy from mobile/xul/branding/unofficial/configure.sh
copy to b2g/branding/unofficial/configure.sh
--- a/mobile/xul/branding/unofficial/configure.sh
+++ b/b2g/branding/unofficial/configure.sh
@@ -1,3 +1,3 @@
-ANDROID_PACKAGE_NAME=org.mozilla.fennec_`echo $USER`
-MOZ_APP_DISPLAYNAME=Fennec
+ANDROID_PACKAGE_NAME=org.mozilla.b2g_`echo $USER`
+MOZ_APP_DISPLAYNAME=B2G
 MOZ_UPDATER=
copy from mobile/xul/branding/unofficial/content/Makefile.in
copy to b2g/branding/unofficial/content/Makefile.in
--- a/mobile/xul/branding/unofficial/content/Makefile.in
+++ b/b2g/branding/unofficial/content/Makefile.in
@@ -1,25 +1,11 @@
 # Branding Makefile
 #  - jars chrome artwork
 
-DEPTH = ../../../../..
+DEPTH = ../../../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
-
-LINUX_BRANDING_FILES = \
-	fennec_26x26.png \
-	fennec_40x40.png \
-	fennec_48x48.png \
-	fennec_72x72.png \
-	fennec_scalable.png \
-	fennec_maemo_icon26.txt \
-	$(NULL)
-
-export::
-	$(NSINSTALL) -D $(DIST)/branding
-	cp $(addprefix $(srcdir)/, $(LINUX_BRANDING_FILES)) $(DIST)/branding/
-	$(NSINSTALL) -D $(DIST)/install
copy from mobile/xul/branding/unofficial/content/about.png
copy to b2g/branding/unofficial/content/about.png
copy from mobile/xul/branding/unofficial/content/favicon32.png
copy to b2g/branding/unofficial/content/favicon32.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3ae248c857d7010eee72e3f20f5a8fbaeed4f196
GIT binary patch
literal 4053
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
Hu0mjfcGdKw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fe980153be29d7d4d01066de16a0fd28ae0e223c
GIT binary patch
literal 5897
zc$@(V7xw6hP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^02Z-HL_t(|+U=Tol%2(S=6_Y+_uYNzzP+z%wYs$-
z0TKd(7Ft3Afw7H=V>1SC9DD58vE$54CNqh1W+plIEcVRAah&mt6Z;(7B*qilU@#J5
zlRzMZ5Su_-x3*UA>%D#VZ>g&J<2D#(#tC2r&!Xp?I^Q4n+*|cNRqyjX?|Ta_;vz2M
zA}-=0F5)8oKZW>pP5kV^$0M%i#f-6xutFtE3L~TluD*Js`G1ap=bnDjnk&1##frP_
z)al}~^HZ}|lw7gIm#RU!f$Ioik|8m+v^{gaqqF{nM8Z1YgrY~H5jnSU(-!l8EdftF
z^+a-Zyt4C&!O1VaFs0TEE(CRMJVmm(j^@@BjjJ-aQ+Y;*ip=MV6z8%ei#gUtJ$*%I
zWb%qNJ$o~a;(O6>a_^RF2ZDbv0`B_mU&Onb;-9dbC<RYS8BQFvtk982G%~k&)26q)
z1N)zP(i$DjeR%irso#HeDs)NSiOXe6n_1q|NK4uwY8#eyCkQ)+lIt)sQovUhS+~U5
z$pS|YpJid_G;Ng`ZdlXmZ{E1{r!6h<|B#M0ym<ANtKZg%IB?*A@T!%hW9z2E{CHSc
z&g9Pb-aan?9=PYOy4ILCS)YuCJtYZb$jlYIxm;O2X-8A{#iQ|`Y~8vo|MyMu%;CpH
zIqUb|e{l4V?mZveHXLaR^>xPCa#;`QhyWuIMi7e$mb8blBxnJFFF8L}q3VG&E_eaQ
zUOLU*-H&5UPSR;>K6LAqrFB;>`${IA`udiEt(7+u^y7OUw}PP3S1lKAjE909nPlWD
zl$)@Pik+US{EPSA_NlK5fc^U(%h<)ULv=Bk(b`~)BA!YRPuDY@t1vND8u4`a2jNuu
zzec06(M=mS|8I9;_s<```8$scesg!euBVcSaQX5UHm~kPNP_?j27v$s%X^}PEil5u
z^*zpxdics9b%0%UaVk}^Ba__o{d>?8(}aS6O<UKf-~7PFhg+NCpWd?lhLK+y`2Kw{
zw=jEK)Ha`J&O|pP!^GTDfoiFQk&?iN!8v<>TlcbU0$}eWk2ZSqgJ)NCrxHqODis&k
z^-xBWu1nG0)yhn+%Fysap{k<aOs49;dfoQzxz|s6_YZgP{MJ3sfA47;TKse!%^ex8
zzGexIptkcsjWvT5hD&=>ge?QYLSr~FT%zPEETwQN6`WFuP^HZ5$@4t+!+Qw%J{rmL
zt5)(`w{1Du(viG*$M&74-w^m?k0#3b>DwDK;os|OODqcsUrvrrP%U`~DY2!6WeKKp
zE)!mAu(PXYP3;8ie<G3{9XzqDQ7(zaLL?iKM5A#^#R_vXv*h!6+B-XGX>aAs`B_d5
z7tYzShJTevCVwn!Lt(b`k+1*d-mg7Yu+uu3fmnpguDy(8Qvzk#fF|TfloBWdosAAX
zZ85+gkOW$Bep)d;Q^wIQQMZbnD-bRg373kzbl^D(E4opq#)#aonI*3r=g#fR4!5?o
zeQd|}t;hF0b}&>fjPA%J&7UmmtXrRm+T!e)VRG|Xq_B`uV%Zj!5J<~n=zJD0vE;EO
z-Ca9u0LQl6Kt`U-m-9=iZkegMERJo_)Y8bZ<voC5YI2sr6NB_F>!Q6i(evyp<KG(}
zoBu;w+WKevMwY)6N!oH^5(EetM;D7^wU10iSl-u2D(-M%cpd}9(h+i19}pM<s#<Yk
zG>0WDx|*Z3)TPOtljNQq$63hX6w8$F-A7<aBDY-2(E7Ff_1@<;d~ARx@45H>-R1n*
z)>Xa9&7EzD@XXi(&%SsXO@I^<%UYCr1xO3f%$F6JO!&aYjT?;wxcZt+CY)%vKVQ~b
zDTPs*N~OxVGv|5s;0sJm&eGn|!irUWEMylDDqvtkmsrthuYCCN=T{$0rfjKQB84o;
z?ljHYE<uY5mFZbjrG$_^dACSwTZE3b7)9S@&Z{!-SIPP=746gCpQNupN;qZ61uiti
zn4Qm&pUG3L`UuY@Vu3$Z1V=L1)yI8%U&>G(zGKt6rtO{0@$ku)PV>r(ui#dz=s=@&
zZ78KsN)aecsZ_xiF%t_%_5j$g=1(*leq>?RTBr*L^~!+O3Z*oj7jXRO5Mv{gtX{i<
zmbM0bPhk{Xwz7@Se{z6hPt0+C+#!736^P6G@ggBi&ZTr_oYu>_n5|YZLLj980Y=n>
zP`uuSm_>~+24M`sKx}<Kb3fTjrBFhq(*)%*j&ZSr0Fer_?Z(yIytSLaR~$O<BDuK&
zmJ|piD1$-Qe%idM*@~%bg+!`rG#QT^d4myp`st^|<hjA0rRCgv9RW%QD5cR#qqRY6
zjS!Mc)~=+rwT@D;N+=p491e3f@9~cxn&y;9AS{6nOF~YVWF(9USr}Wus|3he<|71R
zk%&cgtS!_S&<0D_h;YwOGWWy_*qhd3l{{1`N!%~-<;x<xe^n!H+2iRa4^hgOu%(R@
z0%==d)#kHofn~{>4oI6L!$q3AR(|^fAN<YF{4Y*$*REY3^rnv8osMX!ltycX)(WFR
zD^N<IwWeojJ00!Klq)WEP4&c6F^2Ps&+HlFgh?W7dyxnmVL2#EBBTIIfE2Y8Amr=Z
zn85(XXe?t;8Z4txN+Wy)zCkL3QdN>}l|Ne_<@)}5s+B7H9z95<P{xu1+p=qUAF>HY
zLqsADPS{2u@v0sRMUQjEnCa<Ve&bCy?R@ABDF6_T#`l&*Y|7|TTPm3%k&Kh7Poi}|
zxmYHbEiyeh%h1UY7IFpJ+gmw*YLxE2PL`x&{Q0(KKCx?pDIG<HB!MTvk~Q(MBu4NW
z0aA!X_5}t|XoNNxW2hV(CKLo%ZH?$;450#~uSvN9|NdP`cJ$Zbc|Q9dewuu)ge5KF
z@hF|$tu(bZP~T9G?*&Xv&XAkWk<S+~I$$E_lWuH39*V}E`lYqN&wl!ouba7{FUBm5
z(mn`?CgOB-x6{$tj3sTd^EplrouyJPQ&*S9^8+qjcM0Kmh{NX=_{7ggDOwK3u|P_U
zB`{K8UL!%imjA*Ci~xUd43P+9HD{<i`4XkGBZQI(G6U<8j*ST5OIIfO<dyB1z~bRO
zk1;zv&ypqWtXRE_rlt%A!Pv+o!)Jym<comBk`}_UP)2hm>(Je|>UVE>-~0aTmlCk&
zp-1}WM@}40>ulO+g)#=MG)ilPCFtsIW5wz|Vu=WD#ba_}nvvmg1cGa}tOMKO?nA?T
zY3~?;6GBLVwq@=0C@h4O7%9-gAcQ~~fi{|%T~A^BfM`nwsRD{)Q%I%BT(O#PYb&>}
zi1Ow4tU+Qpu>UZXipz#8*HWKJqO{=LnGsGL9im#UVhM?5*+^N_0bxs~^9ottJKo;W
zarutxcg*~q)!@B<`#0ZoXU_h1RJe--D3p5j&7crM(zl|QOV_W!aU`XM3P)caL|B3=
zuf7Z=H2>`G!~FPo5p9961V&1PkRat^8oauIngSFLzCvX-hY=c~6-EU}ZHTvK*fww}
z-~Zee61HJ<WFB-t$C5TA7E=>*9D3#j7IOJo&_dK4pZtaRDIpjshUn~D^RI7x|NH*r
z?=6QPdias$Gv|&UjJi|x+Gw<*_BK!oV+=|KXsvN#5jI_WB~A57ip3)1<1^GZH_+A9
zOt#{4>wkKPQwwS_Xjv1!MIAuYa$f*OKy_@Ag_CD7T7lM}1Eex^_cZg+fB7uSniF6w
zwDGY7Xe~K>_!Z`6W@&0_AQ}xLErA~>iVG!XCT20lU|ANEB}JrV#rcko?)5u%Y@2&i
z{eYj}`{OUq4<G+hRF~0OVOf&KmL`(*Ny1SF6$Iq-W%AiPsbqwuJ>8V6Whxbq{*`@1
zA{K{+X1VP@KZuKkkrqOj+9?pA<r}BA47k&CRHi1V<nsunu}#2t|J|M3e$$3Usr<#8
zBUdO83CD08o2ltJX66gzvIX+<3$^c?+SziAATR4^@4e*n?|<LTfAK%ZY5y_;!gVd*
z2<7u1cBh7V1qNUFoF5*+8ncMTqck@+vZSYz)_1K(8;?q{jO$nNJfD-thgiFAH5>XH
z`0ed0_}YChAca5)iM6PHLJD4AQfk0<z|CjD^ASe!(OcieZ8u#77)qrIv1lA*fDw>L
z)H7Q)%uE@iY#|bj<BiUfo5>=K!LkHMi&@vEZE4q2iCFBf-f~B1_XGFeG;{96Pfc+;
zVw8tg2D502l-4M%h{dBUzod`LFI|c6drVKwGdVFyTW32<d%JMmfZM-vH%}j*MoWQ%
zCJ}Z>#==;RMW6$U6_;XF<5gU8L#Gi&arv?q9{m0vQCF9skk4b3qOKv0N0>rTN7-`_
zrb1n)Ow0+;fs5-^DHUAKoEqiKsk0PZi*W18d|Ow?z)d@MzWA02*uQ_j%uY{zdG_op
ze?VmxG(_r}i8r*7OlJ^I2;XyYiwi8wj?>$jq@|^S+(MD;Y?jN`ts$L`F_A0r<^T2o
z{oNThty{seo=#%nRLv|2(1B)hF3Sr?PjTq*agH86$)En4J6Yb@M8$*Qv*+mOU4otN
zrliv7Kx0wH#>WdZrDB<}^XJITOi`E~#doWCA_S=p-L-W2KY7o4-}8;P-4ooqZ(l4s
zHFnSR>6dR1ZfVgOYOq2?Q)!yJ`)Td%r>VJ}N~uJC>NK)4Np3caF#+$|cm<dMWdt%X
z7~3IK*M>nN1q8~+2(T5nZVuz-K^SZt5H<%6K10XSRkSUC7fOcl14UpIzFTJE)F~!L
zhR9BipsE!>U<-wBIRw!TI(wIWzoDt=lUx6ee&U;Iiazr2BW>BK(fg;*9Jzu@5#JcX
zc8E|ijg%pLtw^NmS#jAFboQ=9NSGTw%E=d==8_eyG&MG(P&IK!;G|l?i6C_a?Q5hE
zRP$2^9bid;77n&lOw2A&@akB7<p91B1WMr+@|=9}5F@8gfbp>`2ftdST*xB{5YoX<
zHq*9r<%2CPjUU>&^}50Z=?d@Jv!{1{dhEfOQ%C!CIg8R7846L~)In26FI~%4;%iMf
zo}#(AiBQN!RZHZ@UL<B!F{Y*++5k?HaI6mPS87UKSwJcmBWey&2!SO)Bs++=T~443
zK@d=`78xHMAs&j7%gr%5bd-gO^OW-QNTI=spzB&`>skJ6Q)BbZJ9hlS@cc4ZZ<c_&
z?z$`c>Cb+CmlciQP+BN98n;|iTPKWV8FIOKBJm{Y`bLb=1V-UR<2X8xUtXxy<JzEo
zL*Q4?K>$kOSMvm}i`JkP)61AzO<=|9k+Ei6*Tr>RylREQ+!T|;Cn(NM)$D}h;QAhA
zA4FX{9ZOd}Q{U9`8#nCOKKW+il5eH8yz_?ZPiLCj-`mi)cKE5|qiErvgMfU#NDyeM
z#XNqwfFVF@aEr54<|haOMc^9(PvHjvf#*{#X7Q>ERLVts-^2HP0$<~MhQK#?o~AfI
zj#r$+*FFe^<wR-j>8EMQ3Y=sE)k=k8eu3ks$I$Us+LrVkZ)j+|^~UYjjlJ2J?6=xq
zzv22FryltEu74>KjeqkWzjvRwY4bYP^fZH4L1Hl2G>aY*ks>O02IEyxT4S_8zixMp
zG5CJ)hK|Uq$6u+MhnKoYe(VT|j!W@~Ff(?Nq2~`VeSQeM663ilyZ1kj4#oMxmYr@x
zeZy~EfBlY$w-V1=CIBFriu`ozz?K*GJh*554<Fc1cY6cZUa^|~t_ecUv-B@t%8Hf!
zn8kjAHVUl-#^~3P@QWshc-0)eS|&?@6o6%6m1oJGJBW$2FgG!dv}{x;$*w0}<e3*w
zpp4;;k6cGXV|rJ*KE3~~#v<Pi0oPu8owsyp@7FeN++?Jbj7`jQ=;c#Hl6Bm0<5pI!
z>_ux2rF@hM2z*5l1o-~zhmYrZuRUv@`*^-j;05?fp#mQjC~zxSg%RrPEHA(E9RKzk
z-{rvb#|Y50wY9Ke!-jG)p8Df!uDRwd|7&FNHu0Iye0s2<p<!U({->6#=<DLDwM&UP
zFf%p7*yt?9LJ_0Ewj7kwH6oOH%|R+tbCcTChA|rby7bUmW0WAjP-c95lF{=M%uddO
z)^xPBP^@@l7m9rFL%+f5)vJDR%PqHj`|ZSGzg+?b2CnsX?|$eHKYqst9~~P!67Foy
z5VkA|`65M8A)C!HpRHoslBR|fsronuh0^9VrGI@hR4x`tQVKAFg>0Ezu7F$d$>rv1
zJwzlLO?^B>XLCK7rWQ7ASU;6YrM~iZ<9ORA0N}Hq{mf`%Q*&hBf#<gTY|j&7zEGj3
zy@iM)5z?V=)moAb%?u8nV>a)Rh)2N$=-|~J!=ff=&{~7mxH`n(nHh2mC6+8-O~?te
zkexvagXe3WJbaQz4jrRVt#HT3KjwFKcKpG+-+l8#Z#M?{s}Qhx^JbH2sQc=tKK1dZ
zI=Z`g{@5_zy=O1Ra)?A6TDrPfx@rycg%aQS(JsFIqeq!va0!Bdz|$ySp?poS_&hy2
z&$s@17k~bp|IX;d3`<vCO1!>~a5RK3Lj2{ukMrpBgOvS%58QqS-QAscrBdl{|0*&3
zN(2CG-MTH`*wl3U7k}pqFZcF!GdW-8$lwU^SeU@~$+UNH&6cZiEX`~&;BW8WkMAo2
z-zV?`0^dh@0Sm<<KlsVREL04s#uPW)bRC)24l1P_@mQ2+kDO#;c7a49%E#~g7?-VC
z^FUoX@y`baezki878d|_-E~*~bD#U{<EvM%eE-<QRBB~s9ev#`l-(kImt0LpcPITl
z%}kv?MI;oZv#kls=*3>6L1{xE6Xc2|n$l5z_X{6o{pKB1ih0f)d4`Z}aqQG6^Ch2;
zeDn_1U4H4IhK9_Cc3i)6?*FJ8A`jgEvro<pAOEYEDG>=tY{#LcXEkfD*?~41<rVRj
z#kmtlIQ8t~H4lKmlbV}8{5v2t5yv1x3B0Py;YaSFT9`(;id@O##B`ay)tBem+S)hW
zc;k)7F2tJc3rRqJe)gqMto~F`^!n<PQM82o^l6@ZbdHAh9;{H5&c1alUA2y*2Ob4s
zu(T$cX(!##L_Rmi=<pC;Wr3NIGl-x{Bo;=64D(Y9v^O`APQ>@5QmNw?YR&RO642Az
z`+UT%PB&$e6kJ20tO){%6?iO+4Pks2%XUblGYBV!?|FEErmcG!NQ*=&MQM7N^5hxf
zA&ADK*mjgqD8l+nm(g4oCTxj)8#i9Kn`9UC1YEOan|}0xyFaE(?7CvPbZ4bp>3556
zTFsT5bVRYCI|9N&AV@W|GM%488HlGdHES$wL@2_UGeu?#3MFi8J4!eb_F~cKNV2~1
zo@{ph;DucC1tkDr`_2F8G;n(V{{7!kN+o>XZ*^Vws$#Kt=Mx8yT$`^7`|>NUB9&=i
zd{ARhL=tI~^4R;(&w2Uf<J32{6q~y19*#sJ4?2!>%(m^RP$)DpFfdTO(CfY61iXqZ
zTefH*zc>c>?|<@#3#s%6PM$dary$zHp)f%ZpwZZl;QpWfn6dE*)7`sjPo|;%_af2I
zvCSK|{DWVbe8+E!?%KU)LvCjLzB)&@oqpi}KG1jhH4IPY=v>nOtxRLxKOGntsJ>I{
zk?%AC@4jj0;rhnrJI_zgm!BOR<H+eL&W_L0+TC+seJ1|<?_}`576JfL>GVTO`c~hW
zXz7~lTE3>#)!YB0Os3)ETes~fzSC>@wOy75czoYuDG&{|<BV+Dv^n4+F5)6C;vz2M
fA}-=0-Z}ga{hD}SA@#s?00000NkvXXu0mjfo`IZI
copy from mobile/xul/branding/unofficial/content/jar.mn
copy to b2g/branding/unofficial/content/jar.mn
copy from mobile/xul/branding/unofficial/content/logo.png
copy to b2g/branding/unofficial/content/logo.png
copy from mobile/xul/branding/unofficial/content/logoWordmark.png
copy to b2g/branding/unofficial/content/logoWordmark.png
copy from mobile/xul/branding/unofficial/content/splash.png
copy to b2g/branding/unofficial/content/splash.png
copy from mobile/xul/branding/unofficial/locales/Makefile.in
copy to b2g/branding/unofficial/locales/Makefile.in
--- a/mobile/xul/branding/unofficial/locales/Makefile.in
+++ b/b2g/branding/unofficial/locales/Makefile.in
@@ -30,19 +30,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 *****
 
-DEPTH          = ../../../../..
+DEPTH          = ../../../..
 topsrcdir      = @top_srcdir@
 srcdir         = @srcdir@
 VPATH          = @srcdir@
-relativesrcdir = mobile/branding/unofficial/locales
+relativesrcdir = b2g/branding/unofficial/locales
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(AB_CD)
 
 include $(topsrcdir)/config/rules.mk
copy from mobile/xul/branding/unofficial/locales/en-US/brand.dtd
copy to b2g/branding/unofficial/locales/en-US/brand.dtd
--- a/mobile/xul/branding/unofficial/locales/en-US/brand.dtd
+++ b/b2g/branding/unofficial/locales/en-US/brand.dtd
@@ -1,4 +1,4 @@
-<!ENTITY  brandShortName  "Fennec">
-<!ENTITY  brandFullName   "Mozilla Fennec">
+<!ENTITY  brandShortName  "B2G">
+<!ENTITY  brandFullName   "Mozilla B2G">
 <!ENTITY  vendorShortName "Mozilla">
 <!ENTITY  logoTrademark   "">
copy from mobile/xul/branding/unofficial/locales/en-US/brand.properties
copy to b2g/branding/unofficial/locales/en-US/brand.properties
--- a/mobile/xul/branding/unofficial/locales/en-US/brand.properties
+++ b/b2g/branding/unofficial/locales/en-US/brand.properties
@@ -1,2 +1,2 @@
-brandShortName=Fennec
-brandFullName=Mozilla Fennec
+brandShortName=B2G
+brandFullName=Mozilla B2G
copy from mobile/xul/branding/unofficial/locales/jar.mn
copy to b2g/branding/unofficial/locales/jar.mn
copy from mobile/xul/build.mk
copy to b2g/build.mk
--- a/mobile/xul/build.mk
+++ b/b2g/build.mk
@@ -31,19 +31,16 @@
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 ifndef LIBXUL_SDK
-# Needed for building our components as part of libxul
-APP_LIBXUL_DIRS += mobile/xul/components/build
-
 include $(topsrcdir)/toolkit/toolkit-tiers.mk
 else
 ifdef ENABLE_TESTS
 tier_testharness_dirs += \
   testing/mochitest \
   $(NULL)
 endif
 endif
@@ -55,43 +52,37 @@ tier_app_dirs += extensions
 endif
 
 ifdef MOZ_SERVICES_SYNC
 tier_app_dirs += services
 endif
 
 tier_app_dirs += \
   $(MOZ_BRANDING_DIRECTORY) \
-  mobile/xul \
+  b2g \
   $(NULL)
 
 
 installer: 
-	@$(MAKE) -C mobile/xul/installer installer
+	@$(MAKE) -C b2g/installer installer
 
 package:
-	@$(MAKE) -C mobile/xul/installer
+	@$(MAKE) -C b2g/installer
 
 install::
-	@echo "Mobile can't be installed directly."
+	@echo "B2G can't be installed directly."
 	@exit 1
 
-deb: package
-	@$(MAKE) -C mobile/xul/installer deb
-
 upload::
-	@$(MAKE) -C mobile/xul/installer upload
+	@$(MAKE) -C b2g/installer upload
 
 ifdef ENABLE_TESTS
 # Implemented in testing/testsuite-targets.mk
 
 mochitest-browser-chrome:
 	$(RUN_MOCHITEST) --browser-chrome
 	$(CHECK_TEST_ERROR)
 
 mochitest:: mochitest-browser-chrome
 
 .PHONY: mochitest-browser-chrome
 endif
 
-ifeq ($(OS_TARGET),Linux)
-deb: installer
-endif
copy from mobile/xul/chrome/Makefile.in
copy to b2g/chrome/Makefile.in
--- a/mobile/xul/chrome/Makefile.in
+++ b/b2g/chrome/Makefile.in
@@ -30,26 +30,21 @@
 # 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     = ../../..
+DEPTH     = ../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(MOZ_UI_LOCALE) \
            -DPACKAGE=browser \
            -DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
            $(NULL)
 
-
-ifdef ENABLE_TESTS
-DIRS += tests
-endif
-
 include $(topsrcdir)/config/rules.mk
copy from mobile/xul/chrome/content/commandUtil.js
copy to b2g/chrome/content/commandUtil.js
--- a/mobile/xul/chrome/content/commandUtil.js
+++ b/b2g/chrome/content/commandUtil.js
@@ -34,164 +34,164 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 /**
  * Command Updater
  */
-var CommandUpdater = {
+let CommandUpdater = {
   /**
    * Gets a controller that can handle a particular command.
-   * @param   command
-   *          A command to locate a controller for, preferring controllers that
-   *          show the command as enabled.
-   * @returns In this order of precedence:
+   * @param {string} command
+   *        A command to locate a controller for, preferring controllers that
+   *        show the command as enabled.
+   * @return {object} In this order of precedence:
    *            - the first controller supporting the specified command
    *              associated with the focused element that advertises the
-   *              command as ENABLED
+   *              command as ENABLED.
    *            - the first controller supporting the specified command
    *              associated with the global window that advertises the
-   *              command as ENABLED
+   *              command as ENABLED.
    *            - the first controller supporting the specified command
-   *              associated with the focused element
+   *              associated with the focused element.
    *            - the first controller supporting the specified command
-   *              associated with the global window
+   *              associated with the global window.
    */
   _getControllerForCommand: function(command) {
     try {
-      var controller = top.document.commandDispatcher.getControllerForCommand(command);
+      let commandDispatcher = top.document.commandDispatcher;
+      let controller = commandDispatcher.getControllerForCommand(command);
       if (controller && controller.isCommandEnabled(command))
         return controller;
     }
-    catch(e) {
-    }
-    var controllerCount = window.controllers.getControllerCount();
-    for (var i = 0; i < controllerCount; ++i) {
-      var current = window.controllers.getControllerAt(i);
+    catch (e) { }
+
+    let controllerCount = window.controllers.getControllerCount();
+    for (let i = 0; i < controllerCount; ++i) {
+      let current = window.controllers.getControllerAt(i);
       try {
-        if (current.supportsCommand(command) && current.isCommandEnabled(command))
+        if (current.supportsCommand(command) &&
+            current.isCommandEnabled(command))
           return current;
       }
-      catch (e) {
-      }
+      catch (e) { }
     }
     return controller || window.controllers.getControllerForCommand(command);
   },
 
   /**
    * Updates the state of a XUL <command> element for the specified command
    * depending on its state.
-   * @param   command
-   *          The name of the command to update the XUL <command> element for
+   * @param {string} command
+   *        The name of the command to update the XUL <command> element for.
    */
   updateCommand: function(command) {
-    var enabled = false;
+    let enabled = false;
     try {
-      var controller = this._getControllerForCommand(command);
+      let controller = this._getControllerForCommand(command);
       if (controller) {
         enabled = controller.isCommandEnabled(command);
       }
     }
-    catch(ex) { }
+    catch (ex) { }
 
     this.enableCommand(command, enabled);
   },
 
   /**
    * Updates the state of a XUL <command> element for the specified command
    * depending on its state.
-   * @param   command
-   *          The name of the command to update the XUL <command> element for
+   * @param {string} command
+   *        The name of the command to update the XUL <command> element for.
    */
   updateCommands: function(_commands) {
-    var commands = _commands.split(",");
-    for (var command in commands) {
+    let commands = _commands.split(',');
+    for (let command in commands) {
       this.updateCommand(commands[command]);
     }
   },
 
   /**
    * Enables or disables a XUL <command> element.
-   * @param   command
-   *          The name of the command to enable or disable
-   * @param   enabled
+   * @param {string} command
+   *          The name of the command to enable or disable.
+   * @param {bool} enabled
    *          true if the command should be enabled, false otherwise.
    */
   enableCommand: function(command, enabled) {
-    var element = document.getElementById(command);
+    let element = document.getElementById(command);
     if (!element)
       return;
+
     if (enabled)
-      element.removeAttribute("disabled");
+      element.removeAttribute('disabled');
     else
-      element.setAttribute("disabled", "true");
+      element.setAttribute('disabled', 'true');
   },
 
   /**
    * Performs the action associated with a specified command using the most
    * relevant controller.
-   * @param   command
+   * @param {string} command
    *          The command to perform.
    */
   doCommand: function(command) {
-    var controller = this._getControllerForCommand(command);
+    let controller = this._getControllerForCommand(command);
     if (!controller)
       return;
     controller.doCommand(command);
   },
 
   /**
    * Changes the label attribute for the specified command.
-   * @param   command
+   * @param {string} command
    *          The command to update.
-   * @param   labelAttribute
+   * @param {string} labelAttribute
    *          The label value to use.
    */
   setMenuValue: function(command, labelAttribute) {
-    var commandNode = top.document.getElementById(command);
-    if (commandNode)
-    {
-      var label = commandNode.getAttribute(labelAttribute);
-      if ( label )
+    let commandNode = top.document.getElementById(command);
+    if (commandNode) {
+      let label = commandNode.getAttribute(labelAttribute);
+      if (label)
         commandNode.setAttribute('label', label);
     }
   },
 
   /**
    * Changes the accesskey attribute for the specified command.
-   * @param   command
+   * @param {string} command
    *          The command to update.
-   * @param   valueAttribute
+   * @param {string} valueAttribute
    *          The value attribute to use.
    */
   setAccessKey: function(command, valueAttribute) {
-    var commandNode = top.document.getElementById(command);
-    if (commandNode)
-    {
-      var value = commandNode.getAttribute(valueAttribute);
-      if ( value )
+    let commandNode = top.document.getElementById(command);
+    if (commandNode) {
+      let value = commandNode.getAttribute(valueAttribute);
+      if (value)
         commandNode.setAttribute('accesskey', value);
     }
   },
 
   /**
    * Inform all the controllers attached to a node that an event has occurred
-   * (e.g. the tree controllers need to be informed of blur events so that they can change some of the
-   * menu items back to their default values)
-   * @param   node
-   *          The node receiving the event
-   * @param   event
+   * (e.g. the tree controllers need to be informed of blur events so that they
+   * can change some of the menu items back to their default values)
+   * @param  {node} node
+   *          The node receiving the event.
+   * @param  {event} event
    *          The event.
    */
   onEvent: function(node, event) {
-    var numControllers = node.controllers.getControllerCount();
-    var controller;
+    let numControllers = node.controllers.getControllerCount();
+    let controller;
 
-    for ( var controllerIndex = 0; controllerIndex < numControllers; controllerIndex++ )
-    {
-      controller = node.controllers.getControllerAt(controllerIndex);
-      if ( controller )
+    for (let i = 0; i < numControllers; i++) {
+      controller = node.controllers.getControllerAt(i);
+      if (controller)
         controller.onEvent(event);
     }
   }
 };
+
copy from mobile/xul/chrome/content/netError.xhtml
copy to b2g/chrome/content/netError.xhtml
--- a/mobile/xul/chrome/content/netError.xhtml
+++ b/b2g/chrome/content/netError.xhtml
@@ -313,17 +313,16 @@
         <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
         <h1 id="et_malformedURI">&malformedURI.title;</h1>
         <h1 id="et_protocolNotFound">&protocolNotFound.title;</h1>
         <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
         <h1 id="et_netTimeout">&netTimeout.title;</h1>
         <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
         <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
         <h1 id="et_netReset">&netReset.title;</h1>
-        <h1 id="et_notCached">&notCached.title;</h1>
         <h1 id="et_netOffline">&netOffline.title;</h1>
         <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
         <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
         <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
         <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
         <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
         <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
         <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
@@ -338,17 +337,16 @@
         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
         <div id="ed_malformedURI">&malformedURI.longDesc;</div>
         <div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
         <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
         <div id="ed_netTimeout">&netTimeout.longDesc;</div>
         <div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
         <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
         <div id="ed_netReset">&netReset.longDesc;</div>
-        <div id="ed_notCached">&notCached.longDesc;</div>
         <div id="ed_netOffline">&netOffline.longDesc2;</div>
         <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
         <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
         <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc2;</div>
         <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
         <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
         <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
         <div id="ed_nssFailure2">&nssFailure2.longDesc;</div>
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/shell.js
@@ -0,0 +1,220 @@
+/* ***** 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 B2G.
+ *
+ * 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):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const CC = Components.Constructor;
+
+Cu.import('resource://gre/modules/Services.jsm');
+
+const LocalFile = CC('@mozilla.org/file/local;1',
+                     'nsILocalFile',
+                     'initWithPath');
+var shell = {
+  get home() {
+    delete this.home;
+    return this.home = document.getElementById('homescreen');
+  },
+
+  get homeSrc() {
+    try {
+      let homeSrc = Cc['@mozilla.org/process/environment;1']
+                      .getService(Ci.nsIEnvironment)
+                      .get('B2G_HOMESCREEN');
+      if (homeSrc)
+        return homeSrc;
+    } catch (e) {}
+
+    let urls = Services.prefs.getCharPref('browser.homescreenURL').split(',');
+    for (let i = 0; i < urls.length; i++) {
+      let url = urls[i];
+      if (url.substring(0, 7) != 'file://')
+        return url;
+
+      let file = new LocalFile(url.substring(7, url.length));
+      if (file.exists())
+        return url;
+    }
+    return null;
+  },
+
+  start: function shell_init() {
+    window.controllers.appendController(this);
+    window.addEventListener('keypress', this);
+    this.home.addEventListener('load', this, true);
+
+    let ioService = Cc['@mozilla.org/network/io-service;1']
+                      .getService(Ci.nsIIOService2);
+    ioService.offline = false;
+
+    let browser = this.home;
+    browser.homePage = this.homeSrc;
+    browser.goHome();
+  },
+
+  stop: function shell_stop() {
+    window.controllers.removeController(this);
+    window.removeEventListener('keypress', this);
+  },
+
+  supportsCommand: function shell_supportsCommand(cmd) {
+    let isSupported = false;
+    switch (cmd) {
+      case 'cmd_close':
+        isSupported = true;
+        break;
+      default:
+        isSupported = false;
+        break;
+    }
+    return isSupported;
+  },
+
+  isCommandEnabled: function shell_isCommandEnabled(cmd) {
+    return true;
+  },
+
+  doCommand: function shell_doCommand(cmd) {
+    switch (cmd) {
+      case 'cmd_close':
+        this.sendEvent(this.home.contentWindow, 'appclose');
+        break;
+    }
+  },
+
+  handleEvent: function shell_handleEvent(evt) {
+    switch (evt.type) {
+      case 'keypress':
+        switch (evt.keyCode) {
+          case evt.DOM_VK_HOME:
+            this.sendEvent(this.home.contentWindow, 'home');
+            break;
+          case evt.DOM_VK_SLEEP:
+            screen.mozEnabled = !screen.mozEnabled;
+            break;
+          case evt.DOM_VK_ESCAPE:
+            if (evt.getPreventDefault())
+              return;
+            this.doCommand('cmd_close');
+            break;
+        }
+        break;
+      case 'load':
+        this.home.removeEventListener('load', this, true);
+        this.sendEvent(window, 'ContentStart');
+        break;
+    }
+  },
+  sendEvent: function shell_sendEvent(content, type, details) {
+    let event = content.document.createEvent('CustomEvent');
+    event.initCustomEvent(type, true, true, details ? details : {});
+    content.dispatchEvent(event);
+  }
+};
+
+(function VirtualKeyboardManager() {
+  let activeElement = null;
+  let isKeyboardOpened = false;
+
+  let constructor = {
+    handleEvent: function vkm_handleEvent(evt) {
+      let contentWindow = shell.home.contentWindow.wrappedJSObject;
+
+      switch (evt.type) {
+        case 'ContentStart':
+          contentWindow.navigator.mozKeyboard = new MozKeyboard();
+          break;
+        case 'keypress':
+          if (evt.keyCode != evt.DOM_VK_ESCAPE || !isKeyboardOpened)
+            return;
+
+          shell.sendEvent(contentWindow, 'hideime');
+          isKeyboardOpened = false;
+
+          evt.preventDefault();
+          evt.stopPropagation();
+          break;
+        case 'mousedown':
+          if (evt.target != activeElement || isKeyboardOpened)
+            return;
+
+          let type = activeElement.type;
+          shell.sendEvent(contentWindow, 'showime', { type: type });
+          isKeyboardOpened = true;
+          break;
+      }
+    },
+    observe: function vkm_observe(subject, topic, data) {
+      let contentWindow = shell.home.contentWindow;
+
+      let shouldOpen = parseInt(data);
+      if (shouldOpen && !isKeyboardOpened) {
+        activeElement = Cc['@mozilla.org/focus-manager;1']
+                          .getService(Ci.nsIFocusManager)
+                          .focusedElement;
+        if (!activeElement)
+          return;
+
+        let type = activeElement.type;
+        shell.sendEvent(contentWindow, 'showime', { type: type });
+      } else if (!shouldOpen && isKeyboardOpened) {
+        shell.sendEvent(contentWindow, 'hideime');
+      }
+      isKeyboardOpened = shouldOpen;
+    }
+  };
+
+  Services.obs.addObserver(constructor, "ime-enabled-state-changed", false);
+  ['ContentStart', 'keypress', 'mousedown'].forEach(function vkm_events(type) {
+    window.addEventListener(type, constructor, true);
+  });
+})();
+
+
+function MozKeyboard() {
+}
+
+MozKeyboard.prototype = {
+  sendKey: function mozKeyboardSendKey(keyCode) {
+    var utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                      .getInterface(Ci.nsIDOMWindowUtils);
+    ['keydown', 'keypress', 'keyup'].forEach(function sendKeyEvents(type) {
+      utils.sendKeyEvent(type, keyCode, keyCode, null);
+    });
+  }
+};
+
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/shell.xul
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is Mozilla Mobile Browser.
+   -
+   - The Initial Developer of the Original Code is
+   - Mozilla Corporation.
+   - Portions created by the Initial Developer are Copyright (C) 2011
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Chris Jones <jones.chris.g@gmail.com>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the LGPL or the GPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        id="shell"
+        width="480" height="800"
+#ifdef ANDROID
+        sizemode="fullscreen"
+#endif
+        style="background: black; overflow: hidden;"
+        onload="shell.start();"
+        onunload="shell.stop();">
+
+  <script type="application/javascript" src="chrome://browser/content/commandUtil.js"/>
+  <script type="application/javascript" src="chrome://browser/content/shell.js"/>
+  <script type="application/javascript" src="chrome://browser/content/touch.js"/>
+
+  <commandset id="mainCommandSet">
+    <command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
+  </commandset>
+
+  <browser id="homescreen" type="content-primary" flex="1" style="overflow: hidden;"/>
+</window>
+
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/touch.js
@@ -0,0 +1,240 @@
+/* ***** 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 B2G.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+(function touchEventHandler() {
+  let debugging = false;
+  function debug(str) {
+    if (debugging)
+      dump(str + '\n');
+  };
+
+  let contextMenuTimeout = 0;
+
+  // This guard is used to not re-enter the events processing loop for
+  // self dispatched events
+  let ignoreEvents = false;
+
+  // During a 'touchstart' and the first 'touchmove' mouse events can be
+  // prevented for the current touch sequence.
+  let canPreventMouseEvents = false;
+
+  // Used to track the first mousemove and to cancel click dispatc if it's not
+  // true.
+  let isNewTouchAction = false;
+
+  // If this is set to true all mouse events will be cancelled by calling
+  // both evt.preventDefault() and evt.stopPropagation().
+  // This will not prevent a contextmenu event to be fired.
+  // This can be turned on if canPreventMouseEvents is true and the consumer
+  // application call evt.preventDefault();
+  let preventMouseEvents = false;
+
+  let TouchEventHandler = {
+    events: ['mousedown', 'mousemove', 'mouseup', 'click', 'unload'],
+    start: function teh_start() {
+      this.events.forEach((function(evt) {
+        shell.home.addEventListener(evt, this, true);
+      }).bind(this));
+    },
+    stop: function teh_stop() {
+      this.events.forEach((function(evt) {
+        shell.home.removeEventListener(evt, this, true);
+      }).bind(this));
+    },
+    handleEvent: function teh_handleEvent(evt) {
+      if (evt.button || ignoreEvents)
+        return;
+
+      let eventTarget = this.target;
+      let type = '';
+      switch (evt.type) {
+        case 'mousedown':
+          debug('mousedown:');
+
+          this.target = evt.target;
+          this.timestamp = evt.timeStamp;
+          evt.target.setCapture(false);
+
+          preventMouseEvents = false;
+          canPreventMouseEvents = true;
+          isNewTouchAction = true;
+
+          contextMenuTimeout =
+            this.sendContextMenu(evt.target, evt.pageX, evt.pageY, 2000);
+          this.startX = evt.pageX;
+          this.startY = evt.pageY;
+          type = 'touchstart';
+          break;
+
+        case 'mousemove':
+          if (!eventTarget)
+            return;
+
+          // On device a mousemove event if fired right after the mousedown
+          // because of the size of the finger, so let's ignore what happens
+          // below 5ms
+          if (evt.timeStamp - this.timestamp < 30)
+            break;
+
+          if (isNewTouchAction) {
+            canPreventMouseEvents = true;
+            isNewTouchAction = false;
+          }
+
+          if (Math.abs(this.startX - evt.pageX) > 15 ||
+              Math.abs(this.startY - evt.pageY) > 15)
+            window.clearTimeout(contextMenuTimeout);
+          type = 'touchmove';
+          break;
+
+        case 'mouseup':
+          if (!eventTarget)
+            return;
+          debug('mouseup:');
+
+          window.clearTimeout(contextMenuTimeout);
+          eventTarget.ownerDocument.releaseCapture();
+          this.target = null;
+          type = 'touchend';
+          break;
+
+        case 'unload':
+          if (!eventTarget)
+            return;
+
+          window.clearTimeout(contextMenuTimeout);
+          eventTarget.ownerDocument.releaseCapture();
+          this.target = null;
+          TouchEventHandler.stop();
+          return;
+
+        case 'click':
+          if (!isNewTouchAction) {
+            debug('click: cancel');
+
+            evt.preventDefault();
+            evt.stopPropagation();
+          } else {
+            // Mouse events has been cancelled so dispatch a sequence
+            // of events to where touchend has been fired
+            if (preventMouseEvents) {
+              let target = evt.target;
+              ignoreEvents = true;
+              try {
+                this.fireMouseEvent('mousemove', evt);
+                this.fireMouseEvent('mousedown', evt);
+                this.fireMouseEvent('mouseup', evt);
+              } catch (e) {
+                alert(e);
+              }
+              evt.preventDefault();
+              evt.stopPropagation();
+              ignoreEvents = false;
+            }
+
+            debug('click: fire');
+          }
+          return;
+      }
+
+      let target = eventTarget || this.target;
+      if (target && type) {
+        let touchEvent = this.sendTouchEvent(evt, target, type);
+        if (touchEvent.getPreventDefault() && canPreventMouseEvents)
+          preventMouseEvents = true;
+      }
+
+      if (preventMouseEvents) {
+        evt.preventDefault();
+        evt.stopPropagation();
+
+        if (type != 'touchmove')
+          debug('cancelled (fire ' + type + ')');
+      }
+    },
+    fireMouseEvent: function teh_fireMouseEvent(type, evt)  {
+      debug(type + ': fire');
+
+      let content = evt.target.ownerDocument.defaultView;
+      var utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIDOMWindowUtils);
+      utils.sendMouseEvent(type, evt.pageX, evt.pageY, 0, 1, 0, true);
+    },
+    sendContextMenu: function teh_sendContextMenu(target, x, y, delay) {
+      let doc = target.ownerDocument;
+      let evt = doc.createEvent('MouseEvent');
+      evt.initMouseEvent('contextmenu', true, true, doc.defaultView,
+                         0, x, y, x, y, false, false, false, false,
+                         0, null);
+
+      let timeout = window.setTimeout((function contextMenu() {
+        debug('fire context-menu');
+
+        target.dispatchEvent(evt);
+        if (!evt.getPreventDefault())
+          return;
+
+        doc.releaseCapture();
+        this.target = null;
+
+        isNewTouchAction = false;
+      }).bind(this), delay);
+      return timeout;
+    },
+    sendTouchEvent: function teh_sendTouchEvent(evt, target, name) {
+      let touchEvent = document.createEvent('touchevent');
+      let point = document.createTouch(window, target, 0,
+                                     evt.pageX, evt.pageY,
+                                     evt.screenX, evt.screenY,
+                                     evt.clientX, evt.clientY,
+                                     1, 1, 0, 0);
+      let touches = document.createTouchList(point);
+      let targetTouches = touches;
+      let changedTouches = touches;
+      touchEvent.initTouchEvent(name, true, true, window, 0,
+                                false, false, false, false,
+                                touches, targetTouches, changedTouches);
+      target.dispatchEvent(touchEvent);
+      return touchEvent;
+    }
+  };
+
+  window.addEventListener('ContentStart', function touchStart(evt) {
+    window.removeEventListener('ContentStart', touchStart);
+    TouchEventHandler.start();
+  });
+})();
+
copy from mobile/xul/chrome/jar.mn
copy to b2g/chrome/jar.mn
--- a/mobile/xul/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -1,89 +1,13 @@
 #filter substitution
 
 chrome.jar:
+% content branding %content/branding/
 % content browser %content/
 
-* content/about.xhtml                  (content/about.xhtml)
-  content/config.xul                   (content/config.xul)
-  content/config.js                    (content/config.js)
-  content/aboutCertError.xhtml         (content/aboutCertError.xhtml)
-  content/aboutHome.xhtml              (content/aboutHome.xhtml)
-  content/localePicker.xul             (content/localePicker.xul)
-  content/localePicker.js              (content/localePicker.js)
-* content/aboutRights.xhtml            (content/aboutRights.xhtml)
-  content/blockedSite.xhtml            (content/blockedSite.xhtml)
-  content/languages.properties         (content/languages.properties)
-* content/browser.xul                  (content/browser.xul)
-* content/browser.js                   (content/browser.js)
-* content/browser-ui.js                (content/browser-ui.js)
-* content/browser-scripts.js           (content/browser-scripts.js)
-* content/common-ui.js                 (content/common-ui.js)
-* content/AlertsHelper.js              (content/AlertsHelper.js)
-  content/AppMenu.js                   (content/AppMenu.js)
-* content/AwesomePanel.js              (content/AwesomePanel.js)
-  content/BookmarkHelper.js            (content/BookmarkHelper.js)
-  content/BookmarkPopup.js             (content/BookmarkPopup.js)
-  content/CharsetMenu.js               (content/CharsetMenu.js)
-  content/ContentPopupHelper.js        (content/ContentPopupHelper.js)
-* content/ContextCommands.js           (content/ContextCommands.js)
-  content/IndexedDB.js                 (content/IndexedDB.js)
-  content/MenuListHelperUI.js          (content/MenuListHelperUI.js)
-  content/OfflineApps.js               (content/OfflineApps.js)
-* content/PageActions.js               (content/PageActions.js)
-  content/SelectHelperUI.js            (content/SelectHelperUI.js)
-  content/SelectionHelper.js           (content/SelectionHelper.js)
-  content/SharingUI.js                 (content/SharingUI.js)
-  content/TabletSidebar.js             (content/TabletSidebar.js)
-  content/TabsPopup.js                 (content/TabsPopup.js)
-  content/MasterPasswordUI.js          (content/MasterPasswordUI.js)
-* content/content.js                   (content/content.js)
-  content/commandUtil.js               (content/commandUtil.js)
-* content/bindings.xml                 (content/bindings.xml)
-  content/tabs.xml                     (content/tabs.xml)
-  content/bindings/checkbox.xml        (content/bindings/checkbox.xml)
-* content/bindings/browser.xml         (content/bindings/browser.xml)
-  content/bindings/browser.js          (content/bindings/browser.js)
-  content/notification.xml             (content/notification.xml)
-  content/bindings/extensions.xml      (content/bindings/extensions.xml)
-  content/bindings/downloads.xml       (content/bindings/downloads.xml)
-  content/bindings/console.xml         (content/bindings/console.xml)
-  content/bindings/dialog.xml          (content/bindings/dialog.xml)
-  content/bindings/pageaction.xml      (content/bindings/pageaction.xml)
-  content/bindings/arrowbox.xml        (content/bindings/arrowbox.xml)
-  content/browser.css                  (content/browser.css)
-  content/cursor.css                   (content/cursor.css)
-% content branding %content/branding/
-  content/sanitize.js                  (content/sanitize.js)
-* content/input.js                     (content/input.js)
-* content/Util.js                      (content/Util.js)
-  content/forms.js                     (content/forms.js)
-* content/preferences.js               (content/preferences.js)
-  content/exceptions.js                (content/exceptions.js)
-* content/extensions.js                (content/extensions.js)
-* content/downloads.js                 (content/downloads.js)
-  content/console.js                   (content/console.js)
-  content/prompt/alert.xul             (content/prompt/alert.xul)
-  content/prompt/confirm.xul           (content/prompt/confirm.xul)
-  content/prompt/prompt.xul            (content/prompt/prompt.xul)
-  content/prompt/promptPassword.xul    (content/prompt/promptPassword.xul)
-  content/prompt/select.xul            (content/prompt/select.xul)
-  content/prompt/prompt.js             (content/prompt/prompt.js)
-  content/share.xul                    (content/share.xul)
-  content/webapps.xul                  (content/webapps.xul)
-  content/WebappsUI.js                 (content/WebappsUI.js)
-  content/masterPassword.xul           (content/masterPassword.xul)
-  content/removeMasterPassword.xul     (content/removeMasterPassword.xul)
-  content/AnimatedZoom.js              (content/AnimatedZoom.js)
-#ifdef MOZ_SERVICES_SYNC
-  content/sync.js                      (content/sync.js)
-#endif
-  content/LoginManagerChild.js         (content/LoginManagerChild.js)
-  content/fullscreen-video.js          (content/fullscreen-video.js)
-  content/fullscreen-video.xhtml       (content/fullscreen-video.xhtml)
-  content/netError.xhtml               (content/netError.xhtml)
-  content/CapturePickerUI.js           (content/CapturePickerUI.js)
-  content/CaptureDialog.js             (content/CaptureDialog.js)
-  content/CaptureDialog.xul            (content/CaptureDialog.xul)
-  
-% override chrome://global/content/config.xul chrome://browser/content/config.xul
+* content/shell.xul                     (content/shell.xul)
+  content/shell.js                      (content/shell.js)
+  content/touch.js                      (content/touch.js)
+  content/commandUtil.js                (content/commandUtil.js)
+
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
+  content/netError.xhtml                (content/netError.xhtml)
copy from mobile/xul/confvars.sh
copy to b2g/confvars.sh
--- a/mobile/xul/confvars.sh
+++ b/b2g/confvars.sh
@@ -30,44 +30,40 @@
 # 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 *****
 
-MOZ_APP_BASENAME=Fennec
+MOZ_APP_BASENAME=B2G
 MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=11.0a1
 
-MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial
-MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official
+MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
+MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
-MOZ_SERVICES_SYNC=1
+MOZ_SERVICES_SYNC=
 
 MOZ_DISABLE_DOMCRYPTO=1
+MOZ_APP_STATIC_INI=1
+
+if test "$OS_TARGET" = "Android"; then
+MOZ_CAPTURE=1
+MOZ_RAW=1
+fi
+
+# use custom widget for html:select
+MOZ_USE_NATIVE_POPUP_WINDOWS=1
 
 if test "$LIBXUL_SDK"; then
 MOZ_XULRUNNER=1
 else
 MOZ_XULRUNNER=
 MOZ_PLACES=1
 fi
 
-if test "$OS_TARGET" = "Android"; then
-MOZ_CAPTURE=1
-MOZ_RAW=1
-fi
-
-# Needed for building our components as part of libxul
-MOZ_APP_COMPONENT_LIBS="browsercomps"
-MOZ_APP_COMPONENT_INCLUDE=nsBrowserComponents.h
-
-# use custom widget for html:select
-MOZ_USE_NATIVE_POPUP_WINDOWS=1
-
-MOZ_APP_ID={a23983c0-fd0e-11dc-95ff-0800200c9a66}
+MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 MOZ_EXTENSION_MANAGER=1
-MOZ_APP_STATIC_INI=1
copy from mobile/xul/installer/Makefile.in
copy to b2g/installer/Makefile.in
--- a/mobile/xul/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -31,41 +31,35 @@
 # 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     = ../../..
+DEPTH     = ../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
-
-# overwrite mobile-l10n.js with a matchOS=true one for multi-locale builds
-ifeq ($(AB_CD),multi)
-PREF_JS_EXPORTS = $(srcdir)/mobile-l10n.js
-endif
-
 include $(topsrcdir)/config/rules.mk
 
 MOZ_PKG_REMOVALS = $(srcdir)/removed-files.in
 
 MOZ_PKG_MANIFEST_P = $(srcdir)/package-manifest.in
 
 MOZ_NONLOCALIZED_PKG_LIST = \
 	xpcom \
 	browser \
-	mobile \
+	b2g \
 	$(NULL)
 
-MOZ_LOCALIZED_PKG_LIST = $(AB_CD) multilocale
+MOZ_LOCALIZED_PKG_LIST = $(AB_CD)
 
 DEFINES += \
 	-DAB_CD=$(AB_CD) \
 	-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
 	-DPREF_DIR=$(PREF_DIR) \
 	$(NULL)
 
 ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
@@ -93,24 +87,16 @@ else
 # Every other platform just winds up in dist/bin
 BINPATH = bin
 endif
 DEFINES += -DBINPATH=$(BINPATH)
 
 ifdef MOZ_PKG_MANIFEST_P
 $(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) FORCE
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $< > $@
-ifdef MOZ_CHROME_MULTILOCALE
-	printf "\n[multilocale]\n" >> $@
-	for LOCALE in en-US $(MOZ_CHROME_MULTILOCALE) ;\
-	do \
-	  printf "$(BINPATH)/chrome/$$LOCALE$(JAREXT)\n" >> $@; \
-	  printf "$(BINPATH)/chrome/$$LOCALE.manifest\n" >> $@; \
-	done
-endif
 
 GARBAGE += $(MOZ_PKG_MANIFEST)
 endif
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 PACKAGE_XULRUNNER =
 UNPACKAGE =
 else
@@ -124,134 +110,17 @@ else
 MOZ_GRE_PKG_DIR=$(MOZ_PKG_DIR)
 endif
 
 package-xulrunner:
 ifdef LIBXUL_SDK
 ifndef SYSTEM_LIBXUL
 	@echo "Packaging xulrunner..."
 	@rm -rf $(LIBXUL_DIST)/xulrunner*
-	@$(MAKE) -C $(LIBXUL_DIST)/.. package || echo "Perhaps you're trying to package a prebuilt SDK. See 'https://wiki.mozilla.org/Mobile/Build/Fennec#Build' for more information."
+	@$(MAKE) -C $(LIBXUL_DIST)/.. package || echo "Perhaps you're trying to package a prebuilt SDK. See 'https://wiki.mozilla.org/B2G' for more information."
 	@cd $(DIST)/$(MOZ_PKG_DIR); $(UNMAKE_PACKAGE)
 	@echo "Removing unpackaged files... (the ones xulrunner/installer keeps)"
 	@cd $(DIST)/$(MOZ_PKG_DIR)/xulrunner; rm -rf $(NO_PKG_FILES)
 else
 	@echo "Using system xulrunner..."
 endif
 endif
 
-ifeq ($(OS_TARGET),Linux)
-GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
-GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
-ABS_OBJDIR=`cd $(DEPTH); pwd`
-ABS_TOPSRCDIR=$(shell cd $(topsrcdir); pwd)
-BASE64_ICON = dist/branding/fennec_maemo_icon26.txt
-MOZ_DEB_TIMESTAMP = "$(shell date  +"%a, %d  %b %Y %T %z" )"
-
-DEB_PKG_VERSION = $(shell echo $(MOZ_APP_VERSION) | $(PERL) -pe 's/pre/~$(GRE_BUILDID)/; s/^([0-9.]+)([a-z][0-9]+)/$$1~$$2/')
-
-DEB_BUILD_ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH)
-# package name should match mobile/installer/debian/changelog.in
-DEB_PKG_NAME = $(MOZ_PKG_APPNAME)_$(DEB_PKG_VERSION)_$(DEB_BUILD_ARCH).deb
-
-DEFINES += \
-	-DGRE_MILESTONE=$(GRE_MILESTONE) \
-	-DGRE_BUILDID=$(GRE_BUILDID) \
-	-Dinstalldir=$(installdir) \
-	-DMOZ_APP_DISPLAYNAME="$(MOZ_APP_DISPLAYNAME)" \
-	-DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
-	-DABS_OBJDIR=$(ABS_OBJDIR) \
-	-DBASE64_ICON=$(BASE64_ICON) \
-	-DMOZ_DEB_TIMESTAMP=$(MOZ_DEB_TIMESTAMP) \
-	-DDEB_PKG_VERSION=$(DEB_PKG_VERSION) \
-	$(NULL)
-
-DEBDESTDIR=debian/$(MOZ_APP_NAME)
-
-PP_DEB_FILES =	debian/control \
-		debian/changelog \
-		debian/$(MOZ_APP_NAME).desktop \
-		debian/$(MOZ_APP_NAME).links \
-		debian/$(MOZ_APP_NAME).service \
-		debian/compat \
-		debian/files \
-		debian/menu \
-		debian/fennec.preinst \
-		debian/fennec.prerm \
-		debian/fennec.postinst \
-		$(NULL)
-
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-PP_DEB_FILES += debian/fennec.aegis \
-		debian/backup \
-		debian/restore \
-		debian/fennec.conf \
-		debian/fennec-cud.sh \
-		debian/fennec-rfs.sh \
-		 debian/fennec.policy \
-                $(NULL)
-endif
-
-$(PP_DEB_FILES):
-	@$(EXIT_ON_ERROR) \
-	for f in $(PP_DEB_FILES); do \
-           src=$(srcdir)/debian/`basename $$f`.in; \
-	   echo $$src ">" $$f ;\
-           $(RM) -f $$f; \
-           mkdir -p debian;  \
-           $(PYTHON) $(topsrcdir)/config/Preprocessor.py \
-             $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $$src > $$f; \
-         done
-
-deb: $(PP_DEB_FILES) $(DIST)/branding/$(MOZ_APP_NAME)_scalable.png \
-	$(DIST)/branding/$(MOZ_APP_NAME)_26x26.png \
-	$(DIST)/branding/$(MOZ_APP_NAME)_40x40.png
-	rm -rf $(DEBDESTDIR)/$(installdir)/*
-	$(NSINSTALL) -D $(DEBDESTDIR)/$(installdir)
-	cp -pRL $(DIST)/$(MOZ_APP_NAME)/* $(DEBDESTDIR)/$(installdir)
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-	$(NSINSTALL)  debian/$(MOZ_APP_NAME).desktop $(DEBDESTDIR)/usr/share/applications/
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/dbus-1/services/
-	cp debian/$(MOZ_APP_NAME).service $(DEBDESTDIR)/usr/share/dbus-1/services/org.mozilla.$(MOZ_APP_NAME).service
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/themes/blanco/meegotouch/icons/
-	cp $(DIST)/branding/$(MOZ_APP_NAME)_scalable.png $(DEBDESTDIR)/usr/share/themes/blanco/meegotouch/icons/$(MOZ_APP_NAME).png
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/backup-framework/applications
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/$(MOZ_APP_NAME)
-	$(NSINSTALL) -D $(DEBDESTDIR)/etc/osso-cud-scripts
-	$(NSINSTALL) -D $(DEBDESTDIR)/etc/osso-rfs-scripts
-	$(NSINSTALL) -m 755 debian/backup  $(DEBDESTDIR)/usr/share/$(MOZ_APP_NAME)/
-	$(NSINSTALL) -m 755 debian/restore $(DEBDESTDIR)/usr/share/$(MOZ_APP_NAME)/
-	cp debian/$(MOZ_APP_NAME).conf $(DEBDESTDIR)/usr/share/backup-framework/applications/$(MOZ_APP_NAME).conf
-	cp debian/$(MOZ_APP_NAME)-cud.sh $(DEBDESTDIR)/etc/osso-cud-scripts/$(MOZ_APP_NAME)-cud.sh
-	cp debian/$(MOZ_APP_NAME)-rfs.sh $(DEBDESTDIR)/etc/osso-rfs-scripts/$(MOZ_APP_NAME)-rfs.sh
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/policy/etc/syspart.conf.d
-	cp debian/$(MOZ_APP_NAME).policy $(DEBDESTDIR)/usr/share/policy/etc/syspart.conf.d/$(MOZ_APP_NAME)
-else
-	$(NSINSTALL)  debian/$(MOZ_APP_NAME).desktop $(DEBDESTDIR)/usr/share/applications/hildon/
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/dbus-1/services/
-	cp debian/$(MOZ_APP_NAME).service $(DEBDESTDIR)/usr/share/dbus-1/services/org.mozilla.$(MOZ_APP_NAME).service
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/icons/hicolor/scalable/hildon/
-	cp $(DIST)/branding/$(MOZ_APP_NAME)_scalable.png $(DEBDESTDIR)/usr/share/icons/hicolor/scalable/hildon/$(MOZ_APP_NAME).png
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/icons/hicolor/26x26/hildon/
-	cp $(DIST)/branding/$(MOZ_APP_NAME)_26x26.png $(DEBDESTDIR)/usr/share/icons/hicolor/26x26/hildon/$(MOZ_APP_NAME).png
-	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/icons/hicolor/40x40/hildon/
-	cp $(DIST)/branding/$(MOZ_APP_NAME)_40x40.png $(DEBDESTDIR)/usr/share/icons/hicolor/40x40/hildon/$(MOZ_APP_NAME).png
-endif
-	fakeroot dh_link; fakeroot dh_fixperms; fakeroot dh_installdeb; fakeroot dh_shlibdeps; fakeroot dh_gencontrol; fakeroot dh_md5sums; fakeroot dh_builddeb;
-
-# a defined CONTENTMANAGER implicitly means MOZ_PLATFORM_MAEMO is equals 6
-# in case you use CONTENTMANGER you need to sign your package to gain tracker access.
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-	if test -e "/usr/bin/aegis-deb-add"; then \
-	   fakeroot aegis-deb-add -control $(DEBDESTDIR)/DEBIAN/control .. debian/fennec.aegis=_aegis; \
-	else \
-	   echo aegis-builder not found, security signing failed!; \
-	fi
-endif
-
-	echo $(DEB_PKG_NAME) > $(DIST)/deb_name.txt
-
-installer: deb
-	@echo Installer DEB created!
-
-# relative to $(DIST)
-UPLOAD_EXTRA_FILES += ../mobile/$(DEB_PKG_NAME) deb_name.txt
-endif
copy from mobile/xul/installer/package-manifest.in
copy to b2g/installer/package-manifest.in
--- a/mobile/xul/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -1,9 +1,9 @@
-; Package file for the Fennec build. 
+; Package file for the B2G build. 
 ;
 ; File format:
 ;
 ; [] designates a toplevel component. Example: [xpcom]
 ; - in front of a file specifies it to be removed from the destination
 ; * wildcard support to recursively copy the entire directory
 ; ; file comment
 ;
@@ -16,17 +16,17 @@
 @APPNAME@/Contents/PkgInfo
 @APPNAME@/Contents/Plug-Ins/
 @APPNAME@/Contents/Resources/
 #endif
 
 [@AB_CD@]
 @BINPATH@/chrome/@AB_CD@@JAREXT@
 @BINPATH@/chrome/@AB_CD@.manifest
-@BINPATH@/@PREF_DIR@/mobile-l10n.js
+@BINPATH@/@PREF_DIR@/b2g-l10n.js
 @BINPATH@/searchplugins/*
 @BINPATH@/defaults/profile/bookmarks.html
 @BINPATH@/defaults/profile/localstore.rdf
 @BINPATH@/defaults/profile/mimeTypes.rdf
 @BINPATH@/defaults/profile/chrome/*
 #ifdef MOZ_UPDATER
 @BINPATH@/update.locale
 @BINPATH@/updater.ini
@@ -42,63 +42,57 @@
 #ifndef MOZ_STATIC_JS
 @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
 #endif
 @BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
-@BINPATH@/@DLL_PREFIX@mozutils@DLL_SUFFIX@
 #ifdef XP_MACOSX
 @BINPATH@/XUL
 #else
 @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
 #endif
 #ifdef XP_MACOSX
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
 #else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #ifdef XP_WIN32
+#ifndef MOZ_MEMORY
 #if _MSC_VER == 1400
 @BINPATH@/Microsoft.VC80.CRT.manifest
 @BINPATH@/msvcm80.dll
 @BINPATH@/msvcp80.dll
 @BINPATH@/msvcr80.dll
 #elif _MSC_VER == 1500
 @BINPATH@/Microsoft.VC90.CRT.manifest
 @BINPATH@/msvcm90.dll
 @BINPATH@/msvcp90.dll
 @BINPATH@/msvcr90.dll
 #elif _MSC_VER == 1600
 @BINPATH@/msvcp100.dll
 @BINPATH@/msvcr100.dll
-#elif _MSC_VER == 1700
-@BINPATH@/msvcp110.dll
-@BINPATH@/msvcr110.dll
 #endif
-
+#else
+@BINPATH@/mozcrt19.dll
+@BINPATH@/mozcpp19.dll
 #endif
-
+#endif
 #ifdef ANDROID
 @BINPATH@/AndroidManifest.xml
 @BINPATH@/resources.arsc
-@BINPATH@/package-name.txt
 @BINPATH@/classes.dex
 @BINPATH@/@DLL_PREFIX@mozutils@DLL_SUFFIX@
 @BINPATH@/res/drawable
 @BINPATH@/res/drawable-hdpi
 @BINPATH@/res/layout
 #endif
 
-#ifdef MOZ_PLATFORM_MAEMO
-@BINPATH@/res/drawable
-#endif
-
 [browser]
 ; [Base Browser Files]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
 @BINPATH@/@MOZ_APP_NAME@
 #endif
@@ -148,33 +142,32 @@
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
-@BINPATH@/components/dom_telephony_worker.xpt
+@BINPATH@/components/dom_system_b2g.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_storage.xpt
-@BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xpath.xpt
 @BINPATH@/components/dom_xul.xpt
 @BINPATH@/components/dom_loadsave.xpt
@@ -248,16 +241,19 @@
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
+#ifdef MOZ_USE_NATIVE_UCONV
+@BINPATH@/components/ucnative.xpt
+#endif
 @BINPATH@/components/uconv.xpt
 @BINPATH@/components/unicharutil.xpt
 #ifdef MOZ_UPDATER
 @BINPATH@/components/update.xpt
 #endif
 @BINPATH@/components/uriloader.xpt
 @BINPATH@/components/urlformatter.xpt
 @BINPATH@/components/webBrowser_core.xpt
@@ -280,16 +276,17 @@
 @BINPATH@/components/xpcom_threads.xpt
 @BINPATH@/components/xpcom_xpti.xpt
 @BINPATH@/components/xpconnect.xpt
 @BINPATH@/components/xulapp.xpt
 @BINPATH@/components/xul.xpt
 @BINPATH@/components/xuldoc.xpt
 @BINPATH@/components/xultmpl.xpt
 @BINPATH@/components/zipwriter.xpt
+@BINPATH@/components/webapps.xpt
 
 ; JavaScript components
 @BINPATH@/components/ConsoleAPI.manifest
 @BINPATH@/components/ConsoleAPI.js
 @BINPATH@/components/FeedProcessor.manifest
 @BINPATH@/components/FeedProcessor.js
 @BINPATH@/components/BrowserFeeds.manifest
 @BINPATH@/components/FeedConverter.js
@@ -303,16 +300,18 @@
 @BINPATH@/components/nsSetDefaultBrowser.manifest
 @BINPATH@/components/nsSetDefaultBrowser.js
 @BINPATH@/components/BrowserPlaces.manifest
 @BINPATH@/components/nsPrivateBrowsingService.manifest
 @BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
+@BINPATH@/components/nsTryToClose.manifest
+@BINPATH@/components/nsTryToClose.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
 @BINPATH@/components/storage-Legacy.js
 @BINPATH@/components/storage-mozStorage.js
 @BINPATH@/components/crypto-SDR.js
 @BINPATH@/components/jsconsole-clhandler.manifest
@@ -387,22 +386,16 @@
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/nsFilePicker.js
 @BINPATH@/components/nsFilePicker.manifest
-#ifdef MOZ_B2G_RIL
-@BINPATH@/components/nsTelephonyWorker.manifest
-@BINPATH@/components/nsTelephonyWorker.js
-@BINPATH@/components/Telephony.manifest
-@BINPATH@/components/Telephony.js
-#endif
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts_s.dylib
 #endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
 #endif
 @BINPATH@/components/nsINIProcessor.manifest
 @BINPATH@/components/nsINIProcessor.js
@@ -465,18 +458,17 @@
 #ifndef XP_MACOSX
 @BINPATH@/icons/*.xpm
 @BINPATH@/icons/*.png
 #endif
 #endif
 
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
-@BINPATH@/@PREF_DIR@/mobile.js
-@BINPATH@/@PREF_DIR@/mobile-branding.js
+@BINPATH@/@PREF_DIR@/b2g.js
 @BINPATH@/@PREF_DIR@/channel-prefs.js
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/@PREF_DIR@/services-sync.js
 #endif
 @BINPATH@/greprefs.js
 @BINPATH@/defaults/autoconfig/platform.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
 @BINPATH@/defaults/profile/prefs.js
@@ -516,17 +508,19 @@
 @BINPATH@/res/entityTables/*
 #ifdef XP_MACOSX
 @BINPATH@/res/MainMenu.nib/
 #endif
 
 ; svg
 @BINPATH@/res/svg.css
 @BINPATH@/components/dom_svg.xpt
+#ifdef MOZ_SMIL
 @BINPATH@/components/dom_smil.xpt
+#endif
 
 ; [Personal Security Manager]
 ;
 @BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
 @BINPATH@/components/pipboot.xpt
 @BINPATH@/components/pipnss.xpt
 @BINPATH@/components/pippki.xpt
 @BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
@@ -590,42 +584,12 @@ bin/libfreebl_32int64_3.so
 bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
 #endif
 
 ; [OS/2]
 #ifdef XP_OS2
 @BINPATH@/MozSounds.cmd
 #endif
 
-[mobile]
+[b2g]
 @BINPATH@/chrome/icons/
 @BINPATH@/chrome/chrome@JAREXT@
 @BINPATH@/chrome/chrome.manifest
-@BINPATH@/components/AboutRedirector.js
-@BINPATH@/components/AddonUpdateService.js
-@BINPATH@/components/AlertsService.js
-@BINPATH@/components/AutoCompleteCache.js
-@BINPATH@/components/BlocklistPrompt.js
-@BINPATH@/components/BrowserCLH.js
-@BINPATH@/components/BrowserStartup.js
-@BINPATH@/components/ContentDispatchChooser.js
-@BINPATH@/components/ContentPermissionPrompt.js
-@BINPATH@/components/DirectoryProvider.js
-@BINPATH@/components/DownloadManagerUI.js
-@BINPATH@/components/FormAutoComplete.js
-@BINPATH@/components/HelperAppDialog.js
-@BINPATH@/components/LoginManager.js
-@BINPATH@/components/LoginManagerPrompter.js
-@BINPATH@/components/MobileComponents.manifest
-@BINPATH@/components/MobileComponents.xpt
-@BINPATH@/components/PromptService.js
-@BINPATH@/components/SessionStore.js
-@BINPATH@/components/Sidebar.js
-#ifdef MOZ_SAFE_BROWSING
-@BINPATH@/components/SafeBrowsing.js
-#endif
-#ifdef MOZ_UPDATER
-@BINPATH@/components/UpdatePrompt.js
-#endif
-@BINPATH@/components/XPIDialogService.js
-@BINPATH@/components/CapturePicker.js
-@BINPATH@/components/browsercomps.xpt
-@BINPATH@/extensions/feedback@mobile.mozilla.org.xpi
copy from mobile/xul/installer/removed-files.in
copy to b2g/installer/removed-files.in
--- a/mobile/xul/installer/removed-files.in
+++ b/b2g/installer/removed-files.in
@@ -1,30 +1,1 @@
-update.locale
 README.txt
-components/nsTryToClose.js
-#if MOZ_UPDATE_CHANNEL != beta
-extensions/feedback@mobile.mozilla.org.xpi
-#endif
-#ifdef XP_WIN
-  #if _MSC_VER != 1400
-    @BINPATH@/Microsoft.VC80.CRT.manifest
-    @BINPATH@/msvcm80.dll
-    @BINPATH@/msvcp80.dll
-    @BINPATH@/msvcr80.dll
-  #endif
-  #if _MSC_VER != 1500
-    @BINPATH@/Microsoft.VC90.CRT.manifest
-    @BINPATH@/msvcm90.dll
-    @BINPATH@/msvcp90.dll
-    @BINPATH@/msvcr90.dll
-  #endif
-  #if _MSC_VER != 1600
-    @BINPATH@/msvcp100.dll
-    @BINPATH@/msvcr100.dll
-  #endif
-  #if _MSC_VER != 1700
-    @BINPATH@/msvcp110.dll
-    @BINPATH@/msvcr110.dll
-  #endif
-  mozcrt19.dll
-  mozcpp19.dll
-#endif
copy from mobile/xul/locales/Makefile.in
copy to b2g/locales/Makefile.in
--- a/mobile/xul/locales/Makefile.in
+++ b/b2g/locales/Makefile.in
@@ -1,249 +1,227 @@
+# vim:set ts=8 sw=8 sts=8 noet:
 # ***** BEGIN LICENSE BLOCK *****
 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
 #
 # The contents of this file are subject to the Mozilla Public License Version
 # 1.1 (the "License"); you may not use this file except in compliance with
 # the License. You may obtain a copy of the License at
 # http://www.mozilla.org/MPL/
 #
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
-# The Original Code is Mozilla.
+# The Original Code is the Mozilla Browser code.
 #
 # The Initial Developer of the Original Code is
-# the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2007
+# Benjamin Smedberg <bsmedberg@covad.net>
+# Portions created by the Initial Developer are Copyright (C) 2004
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Mark Finkle <mfinkle@mozilla.com>
-#   Axel Hecht <l10n@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-DEPTH     = ../../..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-relativesrcdir = mobile/xul/locales
+DEPTH		= ../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir = b2g/locales
 
 include $(DEPTH)/config/autoconf.mk
+
 include $(topsrcdir)/config/config.mk
 
 ifdef LOCALE_MERGEDIR
-vpath book%.inc $(LOCALE_MERGEDIR)/mobile/profile
-endif
-vpath book%.inc $(LOCALE_SRCDIR)/profile
-ifdef LOCALE_MERGEDIR
-vpath book%.inc @srcdir@/en-US/profile
-endif
-
-ifdef LOCALE_MERGEDIR
-vpath crashreporter%.ini $(LOCALE_MERGEDIR)/mobile/crashreporter
+vpath crashreporter%.ini $(LOCALE_MERGEDIR)/b2g/crashreporter
 endif
 vpath crashreporter%.ini $(LOCALE_SRCDIR)/crashreporter
 ifdef LOCALE_MERGEDIR
 vpath crashreporter%.ini @srcdir@/en-US/crashreporter
 endif
 
+
 SUBMAKEFILES += \
-        $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/Makefile \
-        $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales/Makefile \
-        $(NULL)
+	$(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/Makefile \
+	$(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales/Makefile \
+	$(NULL)
+
+# This makefile uses variable overrides from the libs-% target to
+# build non-default locales to non-default dist/ locations. Be aware!
 
-MOZ_LANGPACK_EID=langpack-$(AB_CD)@firefox-mobile.mozilla.org
-PREF_JS_EXPORTS = $(firstword $(wildcard $(LOCALE_SRCDIR)/mobile-l10n.js) \
-                       @srcdir@/en-US/mobile-l10n.js )
+PWD := $(CURDIR)
 
-# Shouldn't := DEB_BUILD_ARCH despite the $(shell ) as deb isn't everywhere
-DEB_BUILD_ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH)
-DATASTAGE = $(CURDIR)/data-stage
+# These are defaulted to be compatible with the files the wget-en-US target
+# pulls. You may override them if you provide your own files. You _must_
+# override them when MOZ_PKG_PRETTYNAMES is defined - the defaults will not
+# work in that case.
+ZIP_IN ?= $(_ABS_DIST)/$(PACKAGE)
+WIN32_INSTALLER_IN ?= $(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
+RETRIEVE_WINDOWS_INSTALLER = 1
 
-SEARCH_PLUGINS = $(shell cat \
-  $(firstword $(wildcard $(LOCALE_SRCDIR)/searchplugins/list.txt) \
-       @srcdir@/en-US/searchplugins/list.txt ) )
+MOZ_LANGPACK_EID=langpack-$(AB_CD)@b2g.mozilla.org
 
-tmp-search.jar.mn::
-	printf "$(AB_CD).jar:" > $@
-	printf "$(foreach plugin,$(SEARCH_PLUGINS),$(subst __PLUGIN_SUBST__,$(plugin), \n locale/$(AB_CD)/browser/searchplugins/__PLUGIN_SUBST__.xml (__PLUGIN_SUBST__.xml)))" >>  $@
-	@echo   >> $@
+PREF_JS_EXPORTS = $(call MERGE_FILE,b2g-l10n.js)
 
-searchplugins: tmp-search.jar.mn
-	$(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
-          $(QUIET) -j $(FINAL_TARGET)/chrome \
-          -s $(topsrcdir)/$(relativesrcdir)/en-US/searchplugins \
-          -s $(LOCALE_SRCDIR)/searchplugins \
-          $(MAKE_JARS_FLAGS) tmp-search.jar.mn
+ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
+MOZ_PKG_MAC_DSSTORE=$(_ABS_DIST)/branding/dsstore
+MOZ_PKG_MAC_BACKGROUND=$(_ABS_DIST)/branding/background.png
+MOZ_PKG_MAC_ICON=$(_ABS_DIST)/branding/disk.icns
+MOZ_PKG_MAC_EXTRA=--symlink "/Applications:/ "
+endif
 
-export:: searchplugins
-
-GARBAGE += tmp-search.jar.mn
+ifeq (WINNT,$(OS_ARCH))
+UNINSTALLER_PACKAGE_HOOK = $(RM) -r $(STAGEDIST)/uninstall; \
+    $(NSINSTALL) -D $(STAGEDIST)/uninstall; \
+    cp ../installer/windows/l10ngen/helper.exe $(STAGEDIST)/uninstall; \
+    $(RM) $(_ABS_DIST)/l10n-stage/setup.exe; \
+    cp ../installer/windows/l10ngen/setup.exe $(_ABS_DIST)/l10n-stage; \
+    $(NULL)
+endif
 
 include $(topsrcdir)/config/rules.mk
 
 include $(topsrcdir)/toolkit/locales/l10n.mk
 
-clobber-zip:
-	$(RM) $(STAGEDIST)/chrome/$(AB_CD).jar \
-	  $(STAGEDIST)/chrome/$(AB_CD).manifest \
-	  $(STAGEDIST)/defaults/preferences/mobile-l10n.js
-	$(RM) -r $(STAGEDIST)/dictionaries \
-	  $(STAGEDIST)/hyphenation \
-	  $(STAGEDIST)/defaults/profile \
-	  $(STAGEDIST)/chrome/$(AB_CD)
+$(STAGEDIST): $(DIST)/branding
+
+$(DIST)/branding:
+	$(NSINSTALL) -D $@
+
+libs::
+	@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
+	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+	    $(LOCALE_SRCDIR)/existing-profile-defaults.js > $(FINAL_TARGET)/defaults/existing-profile-defaults.js; \
+	fi
+install::
+	@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
+	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+	    $(LOCALE_SRCDIR)/existing-profile-defaults.js > $(DESTDIR)$(mozappdir)/defaults/existing-profile-defaults.js; \
+	fi
+
+NO_JA_JP_MAC_AB_CD := $(if $(filter ja-JP-mac, $(AB_CD)),ja,$(AB_CD))
 
 libs-%:
 	$(NSINSTALL) -D $(DIST)/install
 	@$(MAKE) -C ../../toolkit/locales libs-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
+	@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../intl/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
-	@$(MAKE) -B bookmarks.json AB_CD=$*
-	@$(MAKE) -B searchplugins AB_CD=$* XPI_NAME=locale-$*
-	@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=defaults/preferences BOTH_MANIFESTS=1
+	@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) BOTH_MANIFESTS=1
 	@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 
-# Tailored target to just add the chrome processing for multi-locale builds
-chrome-%:
-	@$(MAKE) -C $(DEPTH)/toolkit/locales chrome-$*
-	@$(MAKE) -C $(DEPTH)/services/sync/locales chrome AB_CD=$*
-	@$(MAKE) -B bookmarks.json AB_CD=$*
-	@$(MAKE) -B searchplugins AB_CD=$*
-	@$(MAKE) chrome AB_CD=$*
-	@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales chrome AB_CD=$*
-ifeq ($(OS_TARGET),Android)
-	@$(MAKE) -C $(DEPTH)/embedding/android chrome AB_CD=$*
+
+repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
+repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD)
+	@echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
+	$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
+	$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
+	$(MAKE) repackage-zip \
+	  AB_CD=$(AB_CD) \
+	  MOZ_PKG_FORMAT=SFX7Z \
+	  ZIP_IN="$(WIN32_INSTALLER_IN)" \
+	  ZIP_OUT="$(WIN32_INSTALLER_OUT)" \
+	  SFX_HEADER="$(PWD)/../installer/windows/l10ngen/7zSD.sfx \
+	              $(topsrcdir)/b2g/installer/windows/app.tag"
+
+ifeq (WINNT,$(OS_ARCH))
+repackage-win32-installer-%:
+	@$(MAKE) repackage-win32-installer AB_CD=$* WIN32_INSTALLER_IN="$(WIN32_INSTALLER_IN)"
+else
+repackage-win32-installer-%: ;
 endif
 
-# This is a generic target that will make a langpack and repack tarball
-# builds. It is called from the tinderbox scripts. Alter it with caution.
 
-installers-%: clobber-% langpack-% repackage-zip-%
+clobber-zip:
+	$(RM) $(STAGEDIST)/chrome/$(AB_CD).jar \
+	  $(STAGEDIST)/chrome/$(AB_CD).manifest \
+	  $(STAGEDIST)/defaults/pref/b2g-l10n.js
+	  $(STAGEDIST)/dictionaries \
+	  $(STAGEDIST)/hyphenation \
+	  $(STAGEDIST)/defaults/profile \
+	  $(STAGEDIST)/chrome/$(AB_CD)
+
+
+langpack: langpack-$(AB_CD)
+
+# This is a generic target that will make a langpack, repack ZIP (+tarball)
+# builds, and repack an installer if applicable. It is called from the
+# tinderbox scripts. Alter it with caution.
+
+installers-%: clobber-% langpack-% repackage-win32-installer-% repackage-zip-%
 	@echo "repackaging done"
 
-NO_JA_JP_MAC_AB_CD := $(if $(filter ja-JP-mac, $(AB_CD)),ja,$(AB_CD))
-
-bookmarks.json: bookmarks.inc generic/profile/bookmarks.json.in
-	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
-	  -I $< \
-	  -DAB_CD=$(NO_JA_JP_MAC_AB_CD) \
-	  $(srcdir)/generic/profile/bookmarks.json.in \
-	  > $@
-
-export:: bookmarks.json
-
 ifdef MOZ_UPDATER
-ifdef LOCALE_MERGEDIR
-UPDATER_INI := $(firstword $(wildcard $(LOCALE_MERGEDIR)/updater/updater.ini) \
-       $(wildcard $(LOCALE_SRCDIR)/updater/updater.ini) \
-       $(srcdir)/en-US/updater/updater.ini )
+libs:: $(call MERGE_FILE,updater/updater.ini)
+ifeq ($(OS_ARCH),WINNT)
+	cat $< $(srcdir)/../installer/windows/nsis/updater_append.ini | \
+	  sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \
+	  sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \
+	  $(FINAL_TARGET)/updater.ini
 else
-UPDATER_INI := $(addprefix $(LOCALE_SRCDIR)/,updater/updater.ini)
-endif
-libs:: $(UPDATER_INI)
 	cat $< | \
 	  sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \
 	  sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \
 	  $(FINAL_TARGET)/updater.ini
 endif
+endif
 
 ifdef MOZ_CRASHREPORTER
 libs:: crashreporter-override.ini
 	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 endif
 
-# When we unpack fennec on MacOS X the platform.ini and application.ini are in slightly
+# When we unpack b2g on MacOS X the platform.ini and application.ini are in slightly
 # different locations that on all other platforms
 ifeq (Darwin, $(OS_ARCH))
 ifdef LIBXUL_SDK
 GECKO_PLATFORM_INI_PATH="$(STAGEDIST)/../Frameworks/XUL.framework/Versions/$(MOZILLA_VERSION)/platform.ini"
 else
 GECKO_PLATFORM_INI_PATH="$(STAGEDIST)/platform.ini"
 endif
-FENNEC_APPLICATION_INI_PATH="$(STAGEDIST)/application.ini"
+B2G_APPLICATION_INI_PATH="$(STAGEDIST)/application.ini"
 else
 ifdef LIBXUL_SDK
 GECKO_PLATFORM_INI_PATH="$(STAGEDIST)/xulrunner/platform.ini"
 else
 GECKO_PLATFORM_INI_PATH="$(STAGEDIST)/platform.ini"
 endif
-FENNEC_APPLICATION_INI_PATH="$(STAGEDIST)/application.ini"
+B2G_APPLICATION_INI_PATH="$(STAGEDIST)/application.ini"
 endif
 
+
 ident:
 	@printf "gecko_revision "
 	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(GECKO_PLATFORM_INI_PATH) Build SourceStamp
-	@printf "fennec_revision "
-	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(FENNEC_APPLICATION_INI_PATH) App SourceStamp
+	@printf "b2g_revision "
+	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(B2G_APPLICATION_INI_PATH) App SourceStamp
 	@printf "buildid "
-	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(FENNEC_APPLICATION_INI_PATH) App BuildID
-
-# special targets just to do the debian single locale packages
-wget-DEB_PKG_NAME:
-ifndef WGET
-	$(error Wget not installed)
-endif
-ifndef EN_US_BINARY_URL
-	$(error EN_US_BINARY_URL not defined)
-endif
-	@$(WGET) -q -O - $(EN_US_BINARY_URL)/deb_name.txt
-
-wget-deb:
-ifndef WGET
-	$(error Wget not installed)
-endif
-ifndef EN_US_BINARY_URL
-	$(error EN_US_BINARY_URL not defined)
-endif
-ifndef DEB_PKG_NAME
-	$(error DEB_PKG_NAME not defined)
-endif
-	$(WGET) -nv -N  $(EN_US_BINARY_URL)/$(DEB_PKG_NAME)
-
-$(DATASTAGE): $(DEB_PKG_NAME)
-	$(RM) -rf $(DATASTAGE)
-	$(NSINSTALL) -D $(DATASTAGE)/DEBIAN
-	ar -p $(DEB_PKG_NAME) data.tar.gz | $(TAR) -zx -C $(DATASTAGE)
-	$(MAKE) clobber-zip AB_CD=en-US STAGEDIST=$(DATASTAGE)/$(installdir)
-	ar -p $(DEB_PKG_NAME) control.tar.gz | $(TAR) -zx -C $(DATASTAGE)/DEBIAN
-# XXX hack around multi-locale deb right now
-	$(RM) $(DATASTAGE)/$(installdir)/chrome/??.*
-	$(RM) $(DATASTAGE)/$(installdir)/chrome/??-??.*
-
-repackage-deb: $(DATASTAGE)
-	$(RM) -rf $(AB_CD)
-	$(NSINSTALL) -D $(AB_CD)/tmp
-	cd $(DIST)/xpi-stage/locale-$(AB_CD) && \
-	  $(TAR) --exclude=install.rdf --exclude=chrome.manifest --exclude=crashreporter.app $(TAR_CREATE_FLAGS) - * | ( cd $(DATASTAGE)/$(installdir) && $(TAR) -xf - )
-	cd $(DATASTAGE) && $(TAR) $(TAR_CREATE_FLAGS) - * | (cd $(CURDIR)/$(AB_CD)/tmp && $(TAR) -xf - )
-	$(MAKE) clobber-zip STAGEDIST=$(DATASTAGE)/$(installdir)
-	cd $(AB_CD) && dpkg-deb -b tmp $(DEB_PKG_NAME)
-	$(RM) -rf $(AB_CD)/tmp
-
-deb-%: AB_CD=$*
-deb-%: clobber-% langpack-%
-ifndef DEB_PKG_NAME
-	$(error DEB_PKG_NAME not defined)
-endif
-	@$(MAKE) repackage-deb AB_CD=$(AB_CD) DEB_PKG_NAME=$(DEB_PKG_NAME)
+	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(B2G_APPLICATION_INI_PATH) App BuildID
 
 merge-%:
 ifdef LOCALE_MERGEDIR
 	$(RM) -rf $(LOCALE_MERGEDIR)
 	MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
 endif
 	@echo
+
+# test target, depends on make package
+# try to repack x-test, with just toolkit/defines.inc being there
+l10n-check::
+	$(RM) -rf x-test
+	$(NSINSTALL) -D x-test/toolkit
+	echo "#define MOZ_LANG_TITLE Just testing" > x-test/toolkit/defines.inc
+	$(MAKE) installers-x-test L10NBASEDIR="$(PWD)" LOCALE_MERGEDIR="$(PWD)/mergedir"
copy from mobile/xul/locales/all-locales
copy to b2g/locales/all-locales
new file mode 100644
--- /dev/null
+++ b/b2g/locales/en-US/b2g-l10n.js
@@ -0,0 +1,39 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Firefox browser.
+#
+# The Initial Developer of the Original Code is
+# Benjamin Smedberg <bsmedberg@covad.net>
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#filter substitution
+
+pref("general.useragent.locale", "@AB_CD@");
copy from mobile/xul/locales/en-US/chrome/about.dtd
copy to b2g/locales/en-US/chrome/about.dtd
copy from mobile/xul/locales/en-US/chrome/aboutCertError.dtd
copy to b2g/locales/en-US/chrome/aboutCertError.dtd
copy from mobile/xul/locales/en-US/chrome/notification.dtd
copy to b2g/locales/en-US/chrome/notification.dtd
copy from mobile/xul/locales/en-US/chrome/overrides/appstrings.properties
copy to b2g/locales/en-US/chrome/overrides/appstrings.properties
copy from mobile/xul/locales/en-US/chrome/overrides/netError.dtd
copy to b2g/locales/en-US/chrome/overrides/netError.dtd
copy from mobile/xul/locales/en-US/chrome/overrides/passwordmgr.properties
copy to b2g/locales/en-US/chrome/overrides/passwordmgr.properties
copy from mobile/xul/locales/en-US/chrome/phishing.dtd
copy to b2g/locales/en-US/chrome/phishing.dtd
copy from mobile/xul/locales/en-US/chrome/webapps.dtd
copy to b2g/locales/en-US/chrome/webapps.dtd
copy from mobile/xul/locales/en-US/crashreporter/crashreporter-override.ini
copy to b2g/locales/en-US/crashreporter/crashreporter-override.ini
--- a/mobile/xul/locales/en-US/crashreporter/crashreporter-override.ini
+++ b/b2g/locales/en-US/crashreporter/crashreporter-override.ini
@@ -1,10 +1,10 @@
 # This file is in the UTF-8 encoding
 [Strings]
 # LOCALIZATION NOTE (CrashReporterProductErrorText2): %s is replaced with another string containing detailed information.
-CrashReporterProductErrorText2=Firefox has crashed. Unfortunately the crash reporter is unable to submit a crash report.\n\nDetails: %s
-CrashReporterDescriptionText2=Firefox has crashed. Your tabs will be listed on the Firefox Start page when you restart.\n\nPlease help us fix the problem!
+CrashReporterProductErrorText2=B2G has crashed. Unfortunately the crash reporter is unable to submit a crash report.\n\nDetails: %s
+CrashReporterDescriptionText2=B2G has crashed. Your tabs will be listed on the B2G Start page when you restart.\n\nPlease help us fix the problem!
 # LOCALIZATION NOTE (CheckSendReport): The %s is replaced with the vendor name.
 CheckSendReport=Send %s a crash report
 CheckIncludeURL=Include the page address
-Quit2=Quit Firefox
-Restart=Restart Firefox
+Quit2=Quit B2G
+Restart=Restart B2G
copy from mobile/xul/locales/en-US/defines.inc
copy to b2g/locales/en-US/defines.inc
copy from mobile/xul/locales/en-US/installer/setup.ini
copy to b2g/locales/en-US/installer/setup.ini
copy from mobile/xul/locales/en-US/updater/updater.ini
copy to b2g/locales/en-US/updater/updater.ini
copy from mobile/xul/locales/filter.py
copy to b2g/locales/filter.py
--- a/mobile/xul/locales/filter.py
+++ b/b2g/locales/filter.py
@@ -33,28 +33,32 @@
 # 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 *****
 
 
 def test(mod, path, entity = None):
   import re
-  # ignore anything but mobile, which is our local repo checkout name
+  # ignore anything but b2g, which is our local repo checkout name
   if mod not in ("netwerk", "dom", "toolkit", "security/manager",
                  "services/sync", "embedding/android",
-                 "mobile/xul"):
+                 "b2g"):
     return False
 
-  if mod != "mobile/xul":
-    # we only have exceptions for mobile
+  # Ignore Lorentz strings, at least temporarily
+  if mod == "toolkit" and path == "chrome/mozapps/plugins/plugins.dtd":
+    if entity.startswith('reloadPlugin.'): return False
+    if entity.startswith('report.'): return False
+
+  if mod != "b2g":
+    # we only have exceptions for b2g
     return True
   if not entity:
-    return not (re.match(r"searchplugins\/.+\.xml", path) or
-                re.match(r"mobile-l10n.js", path) or
+    return not (re.match(r"b2g-l10n.js", path) or
                 re.match(r"defines.inc", path))
   if path == "defines.inc":
     return entity != "MOZ_LANGPACK_CONTRIBUTORS"
 
   if path != "chrome/region.properties":
     # only region.properties exceptions remain, compare all others
     return True
   
copy from mobile/xul/locales/generic/install.rdf
copy to b2g/locales/generic/install.rdf
--- a/mobile/xul/locales/generic/install.rdf
+++ b/b2g/locales/generic/install.rdf
@@ -48,15 +48,15 @@
                em:type="8"
                em:creator="@MOZ_LANGPACK_CREATOR@">
 #ifdef MOZ_LANGPACK_CONTRIBUTORS
     @MOZ_LANGPACK_CONTRIBUTORS@
 #endif
 
     <em:targetApplication>
       <Description>
-        <em:id>{a23983c0-fd0e-11dc-95ff-0800200c9a66}</em:id>
+        <em:id>{3c2e2abc-06d4-11e1-ac3b-374f68613e61}</em:id>
         <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
         <em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
       </Description>
     </em:targetApplication>
   </Description>
 </RDF>
copy from mobile/xul/locales/jar.mn
copy to b2g/locales/jar.mn
--- a/mobile/xul/locales/jar.mn
+++ b/b2g/locales/jar.mn
@@ -1,31 +1,12 @@
 #filter substitution
 
 @AB_CD@.jar:
 % locale browser @AB_CD@ %locale/@AB_CD@/browser/
   locale/@AB_CD@/browser/about.dtd                (%chrome/about.dtd)
   locale/@AB_CD@/browser/aboutCertError.dtd       (%chrome/aboutCertError.dtd)
-  locale/@AB_CD@/browser/aboutHome.dtd            (%chrome/aboutHome.dtd)
-  locale/@AB_CD@/browser/browser.dtd              (%chrome/browser.dtd)
-  locale/@AB_CD@/browser/browser.properties       (%chrome/browser.properties)
-  locale/@AB_CD@/browser/config.dtd               (%chrome/config.dtd)
-  locale/@AB_CD@/browser/localepicker.properties  (%chrome/localepicker.properties)
-  locale/@AB_CD@/browser/region.properties        (%chrome/region.properties)
-  locale/@AB_CD@/browser/preferences.dtd          (%chrome/preferences.dtd)
-  locale/@AB_CD@/browser/checkbox.dtd             (%chrome/checkbox.dtd)
   locale/@AB_CD@/browser/notification.dtd         (%chrome/notification.dtd)
-  locale/@AB_CD@/browser/sync.dtd                 (%chrome/sync.dtd)
-  locale/@AB_CD@/browser/sync.properties          (%chrome/sync.properties)
-  locale/@AB_CD@/browser/prompt.dtd               (%chrome/prompt.dtd)
   locale/@AB_CD@/browser/webapps.dtd              (%chrome/webapps.dtd)
-  locale/@AB_CD@/browser/feedback.dtd             (%chrome/feedback.dtd)
   locale/@AB_CD@/browser/phishing.dtd             (%chrome/phishing.dtd)
-  locale/@AB_CD@/browser/bookmarks.json           (bookmarks.json)
-  locale/@AB_CD@/browser/searchplugins/list.txt   (%searchplugins/list.txt)
 
-# Fennec-specific overrides of generic strings
 * locale/@AB_CD@/browser/netError.dtd             (%chrome/overrides/netError.dtd)
 % override chrome://global/locale/netError.dtd    chrome://browser/locale/netError.dtd
-* locale/@AB_CD@/browser/appstrings.properties    (%chrome/overrides/appstrings.properties)
-% override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
-* locale/@AB_CD@/browser/passwordmgr.properties    (%chrome/overrides/passwordmgr.properties)
-% override chrome://passwordmgr/locale/passwordmgr.properties chrome://browser/locale/passwordmgr.properties
copy from mobile/xul/locales/l10n.ini
copy to b2g/locales/l10n.ini
--- a/mobile/xul/locales/l10n.ini
+++ b/b2g/locales/l10n.ini
@@ -1,11 +1,10 @@
 [general]
-depth = ../../..
-all = mobile/xul/locales/all-locales
+depth = ../..
+all = b2g/locales/all-locales
 
 [compare]
-dirs = mobile/xul
+dirs = b2g
 
 [includes]
 toolkit = toolkit/locales/l10n.ini
 services_sync = services/sync/locales/l10n.ini
-embedding_android = embedding/android/locales/l10n.ini
copy from mobile/xul/makefiles.sh
copy to b2g/makefiles.sh
--- a/mobile/xul/makefiles.sh
+++ b/b2g/makefiles.sh
@@ -10,49 +10,44 @@
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
 # The Original Code is Mozilla.
 #
 # The Initial Developer of the Original Code is
 # the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2007
+# Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Mark Finkle <mfinkle@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 add_makefiles "
-mobile/xul/app/Makefile
-mobile/xul/app/profile/extensions/Makefile
+netwerk/locales/Makefile
+dom/locales/Makefile
+toolkit/locales/Makefile
+security/manager/locales/Makefile
+b2g/app/Makefile
 $MOZ_BRANDING_DIRECTORY/Makefile
-$MOZ_BRANDING_DIRECTORY/content/Makefile
-$MOZ_BRANDING_DIRECTORY/locales/Makefile
-mobile/xul/chrome/Makefile
-mobile/xul/components/Makefile
-mobile/xul/components/build/Makefile
-mobile/xul/modules/Makefile
-mobile/xul/installer/Makefile
-mobile/xul/locales/Makefile
-mobile/xul/Makefile
-mobile/xul/themes/core/Makefile
-"
+b2g/chrome/Makefile
+b2g/installer/Makefile
+b2g/locales/Makefile
+b2g/Makefile"
 
-if [ "$ENABLE_TESTS" ]; then
-  add_makefiles "
-    mobile/xul/chrome/tests/Makefile
-  "
+if test -n "$MOZ_UPDATE_PACKAGING"; then
+   add_makefiles "
+     tools/update-packaging/Makefile
+   "
 fi
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -133,17 +133,17 @@
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
-@BINPATH@/components/dom_telephony_worker.xpt
+@BINPATH@/components/dom_system_b2g.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_notification.xpt
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -65,17 +65,17 @@ components/nsExtensionManager.js
 components/nsInterfaceInfoToIDL.js
 components/nsScriptableIO.js
 components/nsUrlClassifierTable.js
 components/nsXmlRpcClient.js
 components/pluginGlue.js
 components/sidebar.xpt
 #ifdef MOZ_B2G_RIL
 components/dom_telephony.xpt
-components/dom_telephony_worker.xpt
+components/dom_system_b2g.xpt
 #endif
 components/WeaveCrypto.js
 components/WeaveCrypto.manifest
 components/xmlextras.xpt
 components/xpcom.xpt
 components/xpti.dat
 components/xptitemp.dat
 components/nsMicrosummaryService.js
@@ -1137,17 +1137,17 @@ xpicleanup@BIN_SUFFIX@
   components/cookie.xpt
   components/crashreporter.xpt
   components/directory.xpt
   components/docshell.xpt
   components/dom.xpt
   components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
   components/dom_telephony.xpt
-  components/dom_telephony_worker.xpt
+  components/dom_system_b2g.xpt
 #endif
   components/dom_canvas.xpt
   components/dom_core.xpt
   components/dom_css.xpt
   components/dom_events.xpt
   components/dom_geolocation.xpt
   components/dom_html.xpt
   components/dom_json.xpt
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -129,16 +129,25 @@ public:
    */
   void UpdateState(bool aNotify);
   
   /**
    * Method to update mState with link state information.  This does not notify.
    */
   void UpdateLinkState(nsEventStates aState);
 
+  /**
+   * Returns true if this element is either a full-screen element or an
+   * ancestor of the full-screen element.
+   */
+  bool IsFullScreenAncestor() const {
+    return mState.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
+                                        NS_EVENT_STATE_FULL_SCREEN);
+  }
+
 protected:
   /**
    * Method to get the _intrinsic_ content state of this element.  This is the
    * state that is independent of the element's presentation.  To get the full
    * content state, use State().  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   virtual nsEventStates IntrinsicState() const;
deleted file mode 100644
--- a/content/base/public/nsIDOMGCParticipant.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsIDOMGCParticipant_h_
-#define nsIDOMGCParticipant_h_
-
-#include "nsISupports.h"
-
-template<class E> class nsCOMArray;
-
-// 0e2a5a8d-28fd-4a5c-8bf1-5b0067ff3286
-#define NS_IDOMGCPARTICIPANT_IID \
-{ 0x0e2a5a8d, 0x28fd, 0x4a5c, \
-  {0x8b, 0xf1, 0x5b, 0x00, 0x67, 0xff, 0x32, 0x86} }
-
-/**
- * DOM GC Participants are objects that expose information about
- * reachability in the native object graphs to help prevent script ->
- * native -> script cyclical reference from causing leaks due to the
- * creation of garbage collection roots and native/script boundaries.
- *
- * Some implementations of nsIDOMGCParticipant may be responsible for
- * enforcing the requirement that callers of
- * |nsDOMClassInfo::PreserveWrapper| must call
- * |nsDOMClassInfo::ReleaseWrapper| before the nsIDOMGCParticipant
- * argument to the former is destroyed.
- */
-class nsIDOMGCParticipant : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMGCPARTICIPANT_IID)
-
-  /**
-   * Get a reference node for what is known to be a strongly connected
-   * component of nsIDOMGCParticipants.  For example, DOM trees are
-   * strongly connected, so can return the root node to greatly reduce
-   * the number of nodes on which we need to run graph algorithms.
-   *
-   * Note that it's acceptable for nodes in a single strongly connected
-   * component to return different values for GetSCCIndex, as long as
-   * those two values claim that they're reachable from each other in
-   * AppendReachableList.
-   */
-  virtual nsIDOMGCParticipant* GetSCCIndex() = 0;
-
-  /**
-   * Append the list of nsIDOMGCPartipants reachable from this one via
-   * C++ getters exposed to script that return a different result from
-   * |GetSCCIndex|.  The caller is responsible for taking the transitive
-   * closure of |AppendReachableList|.
-   *
-   * This will only be called on objects that are returned by GetSCCIndex.
-   *
-   * null pointers may be appended; they will be ignored by the caller.
-   */
-  virtual void AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMGCParticipant, NS_IDOMGCPARTICIPANT_IID)
-
-#endif // !defined(nsIDOMGCParticipant_h_)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -119,18 +119,19 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0x3b78f6, 0x6dc5, 0x44c6, \
-  { 0xbc, 0x28, 0x60, 0x2a, 0xb2, 0x4f, 0xfb, 0x7b } }
+{ 0x283ec27d, 0x5b23, 0x49b2, \
+  { 0x94, 0xd9, 0x9, 0xb5, 0xdb, 0x45, 0x30, 0x73 } }
+
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -747,31 +748,41 @@ public:
    * contains the element which requested DOM full-screen mode if the
    * requestee is in a subdocument. Note this element must be *in*
    * this document.
    */
   virtual Element* GetFullScreenElement() = 0;
 
   /**
    * Asynchronously requests that the document make aElement the full-screen
-   * element, and move into full-screen mode.
+   * element, and move into full-screen mode. The current full-screen element
+   * (if any) is pushed onto the full-screen element stack, and it can be
+   * returned to full-screen status by calling RestorePreviousFullScreenState().
    */
   virtual void AsyncRequestFullScreen(Element* aElement) = 0;
 
   /**
-   * Requests that the document, and all documents in its hierarchy exit
-   * from DOM full-screen mode.
+   * Restores the previous full-screen element to full-screen status. If there
+   * is no former full-screen element, this exits full-screen, moving the
+   * top-level browser window out of full-screen mode.
    */
-  virtual void CancelFullScreen() = 0;
+  virtual void RestorePreviousFullScreenState() = 0;
 
   /**
    * Returns true if this document is in full-screen mode.
    */
   virtual bool IsFullScreenDoc() = 0;
 
+  /**
+   * Exits all documents from DOM full-screen mode, and moves the top-level
+   * browser window out of full-screen mode. If aRunAsync is true, this runs
+   * asynchronously.
+   */
+  static void ExitFullScreen(bool aRunAsync);
+
   //----------------------------------------------------------------------
 
   // Document notification API's
 
   /**
    * Add a new observer of document change notifications. Whenever
    * content is changed, appended, inserted or removed the observers are
    * informed.  An observer that is already observing the document must
--- a/content/base/public/nsIEventSource.idl
+++ b/content/base/public/nsIEventSource.idl
@@ -46,27 +46,32 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
 interface nsPIDOMWindow;
 
-[scriptable, uuid(755e2d2d-a836-4539-83f4-16b51156341f)]
+[scriptable, uuid(a3d3181e-47c1-4f2e-b2c7-94775a86f5c5)]
 interface nsIEventSource : nsISupports
 {
   readonly attribute DOMString url;
 
   // ready state
   const unsigned short CONNECTING = 0;
   const unsigned short OPEN = 1;
   const unsigned short CLOSED = 2;
   readonly attribute long readyState;
 
+  // if true then cross-site Access-Control requests are made using credentials
+  // such as cookies and authorization headers. Never affects same-site
+  // requests.
+  readonly attribute boolean withCredentials;
+
   // event handler attributes
   attribute nsIDOMEventListener onopen;
   attribute nsIDOMEventListener onmessage;
   attribute nsIDOMEventListener onerror;
 
   /**
    * Close the connection, if any, and set the readyState attribute to CLOSED.
    * If the connection is already closed, the method does nothing.
@@ -78,14 +83,19 @@ interface nsIEventSource : nsISupports
    * context, and owner window that should be used.
    *
    * @param principal The principal to use for the request. This must not be
    *                  null.
    * @param scriptContext The script context to use for the request. May be
    *                      null.
    * @param ownerWindow The associated window for the request. May be null.
    * @param url The EventSource's url. This must not be empty.
+   * @param withCredentials When set to true attempts to make cross-site
+   *                        Access-Control requests with credentials such as
+   *                        cookies and authorization headers. Never affects
+   *                        same-site requests.
    */
   [noscript] void init(in nsIPrincipal principal,
                        in nsIScriptContext scriptContext,
                        in nsPIDOMWindow ownerWindow,
-                       in DOMString url);
+                       in DOMString url,
+                       in boolean withCredentials);
 };
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1533,17 +1533,16 @@ nsDOMImplementation::CreateHTMLDocument(
 // ==================================================================
 
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(true)
-  , mIsFullScreen(false)
   , mVisibilityState(eHidden)
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
   
 #ifdef PR_LOGGING
   if (!gDocumentLeakPRLog)
     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
 
@@ -1868,17 +1867,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLayoutHistoryState)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnloadBlocker)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mImageMaps,
                                                        nsIDOMNodeList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFullScreenElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
 
   // Traverse all our nsCOMArrays.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
 
   for (PRUint32 i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
@@ -1923,17 +1921,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXPathEvaluatorTearoff)
   tmp->mCachedRootElement = nsnull; // Avoid a dangling pointer
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFullScreenElement)
 
   tmp->mParentDocument = nsnull;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
 
   
   if (tmp->mBoxObjectTable) {
    tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
@@ -7299,31 +7296,16 @@ nsDocument::OnPageShow(bool aPersisted,
 static bool
 NotifyPageHide(nsIDocument* aDocument, void* aData)
 {
   const bool* aPersistedPtr = static_cast<const bool*>(aData);
   aDocument->OnPageHide(*aPersistedPtr, nsnull);
   return true;
 }
 
-static bool
-SetFullScreenState(nsIDocument* aDoc, Element* aElement, bool aIsFullScreen);
-
-static void
-SetWindowFullScreen(nsIDocument* aDoc, bool aValue);
-
-static bool
-ResetFullScreen(nsIDocument* aDocument, void* aData) {
-  if (aDocument->IsFullScreenDoc()) {
-    ::SetFullScreenState(aDocument, nsnull, false);
-    aDocument->EnumerateSubDocuments(ResetFullScreen, nsnull);
-  }
-  return true;
-}
-
 void
 nsDocument::OnPageHide(bool aPersisted,
                        nsIDOMEventTarget* aDispatchStartTarget)
 {
   // Send out notifications that our <link> elements are detached,
   // but only if this is not a full unload.
   Element* root = GetRootElement();
   if (aPersisted && root) {
@@ -7368,33 +7350,25 @@ nsDocument::OnPageHide(bool aPersisted,
   
   EnumerateExternalResources(NotifyPageHide, &aPersisted);
   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
 
   if (IsFullScreenDoc()) {
     // A full-screen doc has been hidden. We need to ensure we exit
     // full-screen, i.e. remove full-screen state from all full-screen
     // documents, and exit the top-level window from full-screen mode.
-    // Unfortunately by the time a doc is hidden, it has been removed
-    // from the doc tree, so we can't just call CancelFullScreen()...
-
-    // So firstly reset full-screen state in *this* document. OnPageHide()
-    // is called in every hidden document, so doing this ensures all hidden
-    // documents have their state reset.
-    ::SetFullScreenState(this, nsnull, false);
-
-    // Next walk the document tree of still visible documents, and reset
-    // their full-screen state. We then move the top-level window out
-    // of full-screen mode.
-    nsCOMPtr<nsIDocument> fullScreenRoot(do_QueryReferent(sFullScreenRootDoc));
-    if (fullScreenRoot) {
-      fullScreenRoot->EnumerateSubDocuments(ResetFullScreen, nsnull);
-      SetWindowFullScreen(fullScreenRoot, false);
-      sFullScreenRootDoc = nsnull;
-    }
+    // By the time a doc is hidden, it has been removed from the doc tree,
+    // so nsIDocument::ExitFullScreen() won't be able to traverse to this
+    // document to reset its state, so reset full-screen state in *this*
+    // document. OnPageHide() is called in every hidden document, so doing
+    // this ensures all hidden documents have their full-screen state reset.
+    ClearFullScreenStack();
+
+    // Next reset full-screen state in all visible documents in the doctree.
+    nsIDocument::ExitFullScreen(false);
   }
 }
 
 void
 nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
 {
   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
                mSubtreeModifiedTargets.Count() == 0,
@@ -8440,53 +8414,23 @@ DispatchFullScreenChange(nsIDocument* aT
   nsRefPtr<nsPLDOMEvent> e =
     new nsPLDOMEvent(aTarget,
                      NS_LITERAL_STRING("mozfullscreenchange"),
                      true,
                      false);
   e->PostDOMEvent();
 }
 
-bool
-nsDocument::SetFullScreenState(Element* aElement, bool aIsFullScreen)
-{
-  if (mFullScreenElement) {
-    // Reset the ancestor and full-screen styles on the outgoing full-screen
-    // element in the current document.
-    nsEventStateManager::SetFullScreenState(mFullScreenElement, false);
-    mFullScreenElement = nsnull;
-  }
-  if (aElement) {
-    nsEventStateManager::SetFullScreenState(aElement, aIsFullScreen);
-  }
-  mFullScreenElement = aElement;
-
-  if (mIsFullScreen == aIsFullScreen) {
-    return false;
-  }
-  mIsFullScreen = aIsFullScreen;
-  return true;
-}
-
-// Wrapper for the nsIDocument -> nsDocument cast required to call
-// nsDocument::SetFullScreenState().
-static bool
-SetFullScreenState(nsIDocument* aDoc, Element* aElement, bool aIsFullScreen)
-{
-  return static_cast<nsDocument*>(aDoc)->
-    SetFullScreenState(aElement, aIsFullScreen);
-}
-
 NS_IMETHODIMP
 nsDocument::MozCancelFullScreen()
 {
   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
     return NS_OK;
   }
-  CancelFullScreen();
+  RestorePreviousFullScreenState();
   return NS_OK;
 }
 
 // Runnable to set window full-screen mode. Used as a script runner
 // to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to 
 // run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
 // (handled in chome code) which is unsafe to run if this is called in
 // nsGenericElement::UnbindFromTree().
@@ -8509,52 +8453,149 @@ private:
 };
 
 static void
 SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
 {
   nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
 }
 
-void
-nsDocument::CancelFullScreen()
+class nsCallExitFullScreen : public nsRunnable {
+public:
+  NS_IMETHOD Run()
+  {
+    nsDocument::ExitFullScreen();
+    return NS_OK;
+  }
+};
+
+/* static */
+void
+nsIDocument::ExitFullScreen(bool aRunAsync)
+{
+  if (aRunAsync) {
+    NS_DispatchToCurrentThread(new nsCallExitFullScreen());
+    return;
+  }
+  nsDocument::ExitFullScreen();
+}
+
+static bool
+ResetFullScreen(nsIDocument* aDocument, void* aData) {
+  if (aDocument->IsFullScreenDoc()) {
+    static_cast<nsDocument*>(aDocument)->ClearFullScreenStack();
+    NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
+    nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
+    changed->AppendElement(aDocument);
+    aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
+  }
+  return true;
+}
+
+/* static */
+void
+nsDocument::ExitFullScreen()
+{
+  // Clear full-screen stacks in all descendant documents.
+  nsCOMPtr<nsIDocument> root(do_QueryReferent(sFullScreenRootDoc));
+  if (!root) {
+    // Not in full-screen mode.
+    return;
+  }
+  NS_ASSERTION(root->IsFullScreenDoc(),
+    "Full-screen root should be a full-screen doc...");
+
+  // Stores a list of documents to which we must dispatch "mozfullscreenchange".
+  // We're required by the spec to dispatch the events in leaf-to-root
+  // order when exiting full-screen, but we traverse the doctree in a
+  // root-to-leaf order, so we save references to the documents we must
+  // dispatch to so that we dispatch in the specified order.
+  nsAutoTArray<nsIDocument*, 8> changed;
+
+  // Walk the tree of full-screen documents, and reset their full-screen state.
+  ResetFullScreen(root, static_cast<void*>(&changed));
+
+  // Dispatch "mozfullscreenchange" events. Note this loop is in reverse
+  // order so that the events for the leaf document arrives before the root
+  // document, as required by the spec.
+  for (PRUint32 i = 0; i < changed.Length(); ++i) {
+    DispatchFullScreenChange(changed[changed.Length() - i - 1]);
+  }
+
+  // Reset global state. Do this before we move the window out of full-screen
+  // mode, as that calls nsGlobalWindow::SetFullScreen() which calls back into
+  // nsIDocument::ExitFullScreen().
+  sFullScreenRootDoc = nsnull;
+  sFullScreenDoc = nsnull;
+
+  // Move the top-level window out of full-screen mode.
+  SetWindowFullScreen(root, false);
+}
+
+void
+nsDocument::RestorePreviousFullScreenState()
 {
   NS_ASSERTION(!IsFullScreenDoc() || sFullScreenDoc != nsnull,
                "Should have a full-screen doc when full-screen!");
 
   if (!IsFullScreenDoc() || !GetWindow() || !sFullScreenDoc) {
     return;
   }
 
-  // Reset full-screen state in all full-screen documents.
-  nsCOMPtr<nsIDocument> doc(do_QueryReferent(sFullScreenDoc));
-  while (doc != nsnull) {
-    if (::SetFullScreenState(doc, nsnull, false)) {
-      DispatchFullScreenChange(doc);
-    }
+  // Clear full-screen stacks in all descendant documents, bottom up.
+  nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
+  nsIDocument* doc = fullScreenDoc;
+  while (doc != this) {
+    NS_ASSERTION(doc->IsFullScreenDoc(), "Should be full-screen doc");
+    static_cast<nsDocument*>(doc)->ClearFullScreenStack();
+    DispatchFullScreenChange(doc);
     doc = doc->GetParentDocument();
   }
-  sFullScreenDoc = nsnull;
-  sFullScreenRootDoc = nsnull;
-
-  // Move the window out of full-screen mode.
-  SetWindowFullScreen(this, false);
-
-  return;
+
+  // Roll-back full-screen state to previous full-screen element.
+  NS_ASSERTION(doc == this, "Must have reached this doc.");
+  while (doc != nsnull) {
+    static_cast<nsDocument*>(doc)->FullScreenStackPop();
+    DispatchFullScreenChange(doc);
+    if (static_cast<nsDocument*>(doc)->mFullScreenStack.IsEmpty()) {
+      // Full-screen stack in document is empty. Go back up to the parent
+      // document. We'll pop the containing element off its stack, and use
+      // its next full-screen element as the full-screen element.
+      doc = doc->GetParentDocument();
+    } else {
+      // Else we popped the top of the stack, and there's still another
+      // element in there, so that will become the full-screen element.
+      sFullScreenDoc = do_GetWeakReference(doc);
+      break;
+    }
+  }
+
+  if (doc == nsnull) {
+    // We moved all documents out of full-screen mode, reset global full-screen
+    // state and move the top-level window out of full-screen mode.
+    DebugOnly< nsCOMPtr<nsIDocument> > root(do_QueryReferent(sFullScreenRootDoc));
+    NS_ASSERTION(!root->IsFullScreenDoc(), "Should have cleared all docs' stacks");
+    sFullScreenDoc = nsnull;
+    sFullScreenRootDoc = nsnull;
+    SetWindowFullScreen(this, false);
+  }
 }
 
 bool
 nsDocument::IsFullScreenDoc()
 {
-  return mIsFullScreen;
+  return GetFullScreenElement() != nsnull;
 }
 
 static nsIDocument*
 GetCommonAncestor(nsIDocument* aDoc1, nsIDocument* aDoc2)
 {
+  if (!aDoc1 || !aDoc2) {
+    return nsnull;
+  }
   nsIDocument* doc1 = aDoc1;
   nsIDocument* doc2 = aDoc2;
 
   nsAutoTArray<nsIDocument*, 30> parents1, parents2;
   do {
     parents1.AppendElement(doc1);
     doc1 = doc1->GetParentDocument();
   } while (doc1);
@@ -8629,21 +8670,108 @@ LogFullScreenDenied(bool aLogFailure, co
                                   aMessage,
                                   nsnull, 0, nsnull,
                                   EmptyString(), 0, 0,
                                   nsIScriptError::warningFlag,
                                   "DOM", aDoc);
 }
 
 void
+nsDocument::ClearFullScreenStack()
+{
+  if (mFullScreenStack.IsEmpty()) {
+    return;
+  }
+  // The top element in the full-screen stack will have full-screen
+  // style bits set on it and its ancestors. Remove the style bits.
+  // Note the non-top elements won't have the style bits set.
+  Element* top = FullScreenStackTop();
+  NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty");
+  if (top) {
+    nsEventStateManager::SetFullScreenState(top, false);
+  }
+  mFullScreenStack.Clear();
+}
+
+bool
+nsDocument::FullScreenStackPush(Element* aElement)
+{
+  NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
+  Element* top = FullScreenStackTop();
+  if (top == aElement || !aElement) {
+    return false;
+  }
+  if (top) {
+    // We're pushing a new element onto the full-screen stack, so we must
+    // remove the ancestor and full-screen styles from the former top of the
+    // stack.
+    nsEventStateManager::SetFullScreenState(top, false);
+  }
+  nsEventStateManager::SetFullScreenState(aElement, true);
+  mFullScreenStack.AppendElement(do_GetWeakReference(aElement));
+  NS_ASSERTION(GetFullScreenElement() == aElement, "Should match");
+  return true;
+}
+
+void
+nsDocument::FullScreenStackPop()
+{
+  if (mFullScreenStack.IsEmpty()) {
+    return;
+  }
+
+  // Remove styles from existing top element.
+  Element* top = FullScreenStackTop();
+  nsEventStateManager::SetFullScreenState(top, false);
+
+  // Remove top element. Note the remaining top element in the stack
+  // will not have full-screen style bits set, so we will need to restore
+  // them on the new top element before returning.
+  PRUint32 last = mFullScreenStack.Length() - 1;
+  mFullScreenStack.RemoveElementAt(last);
+
+  // Pop from the stack null elements (references to elements which have
+  // been GC'd since they were added to the stack) and elements which are
+  // no longer in this document.
+  while (!mFullScreenStack.IsEmpty()) {
+    Element* element = FullScreenStackTop();
+    if (!element || !element->IsInDoc() || element->OwnerDoc() != this) {
+      NS_ASSERTION(!element->IsFullScreenAncestor(),
+                   "Should have already removed full-screen styles");
+      PRUint32 last = mFullScreenStack.Length() - 1;
+      mFullScreenStack.RemoveElementAt(last);
+    } else {
+      // The top element of the stack is now an in-doc element. Apply the
+      // full-screen styles and return.
+      nsEventStateManager::SetFullScreenState(element, true);
+      break;
+    }
+  }
+}
+
+Element*
+nsDocument::FullScreenStackTop()
+{
+  if (mFullScreenStack.IsEmpty()) {
+    return nsnull;
+  }
+  PRUint32 last = mFullScreenStack.Length() - 1;
+  nsCOMPtr<Element> element(do_QueryReferent(mFullScreenStack[last]));
+  NS_ASSERTION(element, "Should have full-screen element!");
+  NS_ASSERTION(element->IsInDoc(), "Full-screen element should be in doc");
+  NS_ASSERTION(element->OwnerDoc() == this, "Full-screen element should be in this doc");
+  return element;
+}
+
+void
 nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
 {
   NS_ASSERTION(aElement,
     "Must pass non-null element to nsDocument::RequestFullScreen");
-  if (!aElement) {
+  if (!aElement || aElement == GetFullScreenElement()) {
     return;
   }
   if (!aElement->IsInDoc()) {
     LogFullScreenDenied(true, "FullScreenDeniedNotInDocument", this);
     return;
   }
   if (aElement->OwnerDoc() != this) {
     LogFullScreenDenied(true, "FullScreenDeniedMovedDocument", this);
@@ -8652,75 +8780,104 @@ nsDocument::RequestFullScreen(Element* a
   if (!GetWindow()) {
     LogFullScreenDenied(true, "FullScreenDeniedLostWindow", this);
     return;
   }
   if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
     // IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
     return;
   }
-
-  // Turn off full-screen state in all documents which were previously
-  // full-screen but which shouldn't be after this request is granted.
-  // Note commonAncestor will be null when in a separate browser window
-  // to the requesting document.
-  nsIDocument* commonAncestor = nsnull;
+  if (GetFullScreenElement() &&
+      !nsContentUtils::ContentIsDescendantOf(aElement, GetFullScreenElement())) {
+    // If this document is full-screen, only grant full-screen requests from 
+    // a descendent of the current full-screen element.
+    LogFullScreenDenied(true, "FullScreenDeniedNotDescendant", this);
+    return;
+  }
+
+  // Stores a list of documents which we must dispatch "mozfullscreenchange"
+  // too. We're required by the spec to dispatch the events in root-to-leaf
+  // order, but we traverse the doctree in a leaf-to-root order, so we save
+  // references to the documents we must dispatch to so that we get the order
+  // as specified.
+  nsAutoTArray<nsIDocument*, 8> changed;
+
+  // If another top-level window is full-screen. Exit it from full-screen.
   nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
-  if (fullScreenDoc) {
-    commonAncestor = GetCommonAncestor(fullScreenDoc, this);
-  }
-  nsIDocument* doc = fullScreenDoc;
-  while (doc != commonAncestor) {
-    if (::SetFullScreenState(doc, nsnull, false)) {
-      DispatchFullScreenChange(doc);
-    }
-    doc = doc->GetParentDocument();
-  }
-  if (!commonAncestor && fullScreenDoc) {
-    // Other doc is in another browser window. Move it out of full-screen.
-    // Note that nsGlobalWindow::SetFullScreen() proxies to the root window
-    // in its hierarchy, and does not operate on the a per-nsIDOMWindow basis.
-    SetWindowFullScreen(fullScreenDoc, false);
+  nsIDocument* commonAncestor = GetCommonAncestor(fullScreenDoc, this);
+  if (fullScreenDoc && !commonAncestor) {
+    // A document which doesn't have a common ancestor is full-screen, this
+    // must be in a separate browser window. Fully exit full-screen, to move
+    // the other browser window/doctree out of full-screen.
+    nsIDocument::ExitFullScreen(false);
   }
 
   // Remember the root document, so that if a full-screen document is hidden
   // we can reset full-screen state in the remaining visible full-screen documents.
   sFullScreenRootDoc = do_GetWeakReference(nsContentUtils::GetRootDocument(this));
 
   // Set the full-screen element. This sets the full-screen style on the
   // element, and the full-screen-ancestor styles on ancestors of the element
   // in this document.
-  if (SetFullScreenState(aElement, true)) {
-    DispatchFullScreenChange(aElement->OwnerDoc());
-  }
-
+  DebugOnly<bool> x = FullScreenStackPush(aElement);
+  NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
+  changed.AppendElement(this);
+  
   // Propagate up the document hierarchy, setting the full-screen element as
   // the element's container in ancestor documents. This also sets the
   // appropriate css styles as well. Note we don't propagate down the
   // document hierarchy, the full-screen element (or its container) is not
   // visible there.  
   nsIDocument* child = this;
   nsIDocument* parent;
   while ((parent = child->GetParentDocument())) {
     Element* element = parent->FindContentForSubDocument(child)->AsElement();
-    if (::SetFullScreenState(parent, element, true)) {
-      DispatchFullScreenChange(element->OwnerDoc());
-    }
-    child = parent;
-  }
+    if (static_cast<nsDocument*>(parent)->FullScreenStackPush(element)) {
+      changed.AppendElement(parent);
+      child = parent;
+    } else {
+      NS_ASSERTION(!commonAncestor || child == commonAncestor,
+                   "Should finish loop at common ancestor (or null)");
+      // We've reached either the root, or a point in the doctree where the
+      // new full-screen element container is the same as the previous
+      // full-screen element's container. No more changes need to be made
+      // to the full-screen stacks of documents further up the tree.
+      break;
+    }
+  }
+
+  // Dispatch "mozfullscreenchange" events. Note this loop is in reverse
+  // order so that the events for the root document arrives before the leaf
+  // document, as required by the spec.
+  for (PRUint32 i = 0; i < changed.Length(); ++i) {
+    DispatchFullScreenChange(changed[changed.Length() - i - 1]);
+  }
+
+  // Remember this is the requesting full-screen document.
+  sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
 
   // Make the window full-screen. Note we must make the state changes above
   // before making the window full-screen, as then the document reports as
   // being in full-screen mode when the chrome "fullscreen" event fires,
   // enabling chrome to distinguish between browser and dom full-screen
-  // modes.
+  // modes. Also note that nsGlobalWindow::SetFullScreen() (which
+  // SetWindowFullScreen() calls) proxies to the root window in its hierarchy,
+  // and does not operate on the a per-nsIDOMWindow basis.
   SetWindowFullScreen(this, true);
 
-  // Remember this is the requesting full-screen document.
-  sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
+#ifdef DEBUG
+  NS_ASSERTION(GetFullScreenElement() == aElement,
+               "Full-screen element should be the requested element!");
+  NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
+  nsCOMPtr<nsIDOMHTMLElement> fse;
+  GetMozFullScreenElement(getter_AddRefs(fse));
+  nsCOMPtr<nsIContent> c(do_QueryInterface(fse));
+  NS_ASSERTION(c->AsElement() == aElement,
+    "GetMozFullScreenElement should match GetFullScreenElement()");
+#endif
 }
 
 NS_IMETHODIMP
 nsDocument::GetMozFullScreenElement(nsIDOMHTMLElement **aFullScreenElement)
 {
   NS_ENSURE_ARG_POINTER(aFullScreenElement);
   *aFullScreenElement = nsnull;
   if (IsFullScreenDoc()) {
@@ -8729,17 +8886,20 @@ nsDocument::GetMozFullScreenElement(nsID
     CallQueryInterface(GetFullScreenElement(), aFullScreenElement);
   }
   return NS_OK;
 }
 
 Element*
 nsDocument::GetFullScreenElement()
 {
-  return mFullScreenElement;
+  Element* element = FullScreenStackTop();
+  NS_ASSERTION(!element || element->IsFullScreenAncestor(),
+    "Should have full-screen styles applied!");
+  return element;
 }
 
 NS_IMETHODIMP
 nsDocument::GetMozFullScreen(bool *aFullScreen)
 {
   NS_ENSURE_ARG_POINTER(aFullScreen);
   *aFullScreen = IsFullScreenDoc();
   return NS_OK;
@@ -8748,16 +8908,36 @@ nsDocument::GetMozFullScreen(bool *aFull
 NS_IMETHODIMP
 nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
 {
   NS_ENSURE_ARG_POINTER(aFullScreen);
   *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
   return NS_OK;
 }
 
+static bool
+HasFullScreenSubDocument(nsIDocument* aDoc, void* aData)
+{
+  if (aDoc->IsFullScreenDoc()) {
+    // This subdocument is full-screen. Set result and return false to
+    // stop iteration.
+    *static_cast<bool*>(aData) = true;
+    return false;
+  }
+  return true;
+}
+
+static bool
+HasFullScreenSubDocument(nsIDocument* aDoc)
+{
+  bool result = false;
+  aDoc->EnumerateSubDocuments(&HasFullScreenSubDocument, static_cast<void*>(&result));
+  return result;
+}
+
 bool
 nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
 {
   if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
     // Chrome code can always use the full-screen API, provided it's not
     // explicitly disabled. Note IsCallerChrome() returns true when running
     // in an nsRunnable, so don't use GetMozFullScreenEnabled() from an
     // nsRunnable!
@@ -8771,16 +8951,20 @@ nsDocument::IsFullScreenEnabled(bool aCa
   if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
     LogFullScreenDenied(aLogFailure, "FullScreenDeniedPlugins", this);
     return false;
   }
   if (!IsVisible()) {
     LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
     return false;
   }
+  if (HasFullScreenSubDocument(this)) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedSubDocFullScreen", this);
+    return false;
+  }
 
   // Ensure that all ancestor <iframe> elements have the mozallowfullscreen
   // boolean attribute set.
   nsINode* node = static_cast<nsINode*>(this);
   do {
     nsIContent* content = static_cast<nsIContent*>(node);
     if (content->IsHTML(nsGkAtoms::iframe) &&
         !content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -953,29 +953,43 @@ public:
 
   bool HasAudioAvailableListeners()
   {
     return mHasAudioAvailableListener;
   }
 
   virtual Element* GetFullScreenElement();
   virtual void AsyncRequestFullScreen(Element* aElement);
-  virtual void CancelFullScreen();
+  virtual void RestorePreviousFullScreenState();
   virtual bool IsFullScreenDoc();
+  static void ExitFullScreen();
 
   // This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
   // to move document into full-screen mode if allowed. aWasCallerChrome
   // should be true when nsIDocument::AsyncRequestFullScreen() was called
   // by chrome code.
   void RequestFullScreen(Element* aElement, bool aWasCallerChrome);
 
-  // Returns true if making this change results in a change in the full-screen
-  // state of this document.
-  bool SetFullScreenState(Element* aElement, bool aIsFullScreen);
- 
+  // Removes all elements from the full-screen stack, removing full-scren
+  // styles from the top element in the stack.
+  void ClearFullScreenStack();
+
+  // Pushes aElement onto the full-screen stack, and removes full-screen styles
+  // from the former full-screen stack top, and its ancestors, and applies the
+  // styles to aElement. aElement becomes the new "full-screen element".
+  bool FullScreenStackPush(Element* aElement);
+
+  // Remove the top element from the full-screen stack. Removes the full-screen
+  // styles from the former top element, and applies them to the new top
+  // element, if there is one.
+  void FullScreenStackPop();
+
+  // Returns the top element from the full-screen stack.
+  Element* FullScreenStackTop();
+
   // This method may fire a DOM event; if it does so it will happen
   // synchronously.
   void UpdateVisibilityState();
   // Posts an event to call UpdateVisibilityState
   virtual void PostVisibilityUpdateEvent();
 
 protected:
   friend class nsNodeUtils;
@@ -1105,16 +1119,21 @@ protected:
 
   // The root document of the doctree containing the document which requested
   // full-screen. This root document will also be in full-screen state, as will
   // all the descendents down to the document which requested full-screen. This
   // reference allows us to reset full-screen state on all documents when a
   // document is hidden/navigation occurs.
   static nsWeakPtr sFullScreenRootDoc;
 
+  // Stack of full-screen elements. When we request full-screen we push the
+  // full-screen element onto this stack, and when we cancel full-screen we
+  // pop one off this stack, restoring the previous full-screen state
+  nsTArray<nsWeakPtr> mFullScreenStack;
+
   nsRefPtr<nsEventListenerManager> mListenerManager;
   nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
   nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
   nsRefPtr<nsScriptLoader> mScriptLoader;
   nsDocHeaderData* mHeaderData;
   /* mIdentifierMap works as follows for IDs:
    * 1) Attribute changes affect the table immediately (removing and adding
    *    entries as needed).
@@ -1124,19 +1143,16 @@ protected:
    */
   nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;
 
   nsClassHashtable<nsStringHashKey, nsRadioGroupStruct> mRadioGroups;
 
   // Recorded time of change to 'loading' state.
   mozilla::TimeStamp mLoadingTimeStamp;
 
-  // The current full-screen element of this document.
-  nsCOMPtr<Element> mFullScreenElement;
-
   // True if the document has been detached from its content viewer.
   bool mIsGoingAway:1;
   // True if the document is being destroyed.
   bool mInDestructor:1;
 
   // True if this document has ever had an HTML or SVG <title> element
   // bound to it
   bool mMayHaveTitleElement:1;
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -57,16 +57,17 @@
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIScriptError.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
+#include "nsCrossSiteListenerProxy.h"
 
 using namespace mozilla;
 
 #define REPLACEMENT_CHAR     (PRUnichar)0xFFFD
 #define BOM_CHAR             (PRUnichar)0xFEFF
 #define SPACE_CHAR           (PRUnichar)0x0020
 #define CR_CHAR              (PRUnichar)0x000D
 #define LF_CHAR              (PRUnichar)0x000A
@@ -80,16 +81,17 @@ using namespace mozilla;
 #define DEFAULT_RECONNECTION_TIME_VALUE   5000
 #define MAX_RECONNECTION_TIME_VALUE       PR_IntervalToMilliseconds(DELAY_INTERVAL_LIMIT)
 
 nsEventSource::nsEventSource() :
   mStatus(PARSE_STATE_OFF),
   mFrozen(false),
   mErrorLoadOnRedirect(false),
   mGoingToDispatchAllMessages(false),
+  mWithCredentials(false),
   mLastConvertionResult(NS_OK),
   mReadyState(nsIEventSource::CONNECTING),
   mScriptLine(0),
   mInnerWindowID(0)
 {
 }
 
 nsEventSource::~nsEventSource()
@@ -160,16 +162,24 @@ nsEventSource::GetUrl(nsAString& aURL)
 NS_IMETHODIMP
 nsEventSource::GetReadyState(PRInt32 *aReadyState)
 {
   NS_ENSURE_ARG_POINTER(aReadyState);
   *aReadyState = mReadyState;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsEventSource::GetWithCredentials(bool *aWithCredentials)
+{
+  NS_ENSURE_ARG_POINTER(aWithCredentials);
+  *aWithCredentials = mWithCredentials;
+  return NS_OK;
+}
+
 #define NS_EVENTSRC_IMPL_DOMEVENTLISTENER(_eventlistenername, _eventlistener)  \
   NS_IMETHODIMP                                                                \
   nsEventSource::GetOn##_eventlistenername(nsIDOMEventListener * *aListener)   \
   {                                                                            \
     return GetInnerEventListener(_eventlistener, aListener);                   \
   }                                                                            \
                                                                                \
   NS_IMETHODIMP                                                                \
@@ -225,26 +235,28 @@ nsEventSource::Close()
 
 /**
  * This Init method should only be called by C++ consumers.
  */
 NS_IMETHODIMP
 nsEventSource::Init(nsIPrincipal* aPrincipal,
                     nsIScriptContext* aScriptContext,
                     nsPIDOMWindow* aOwnerWindow,
-                    const nsAString& aURL)
+                    const nsAString& aURL,
+                    bool aWithCredentials)
 {
   NS_ENSURE_ARG(aPrincipal);
 
   if (mReadyState != nsIEventSource::CONNECTING || !PrefEnabled()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   mPrincipal = aPrincipal;
   mScriptContext = aScriptContext;
+  mWithCredentials = aWithCredentials;
   if (aOwnerWindow) {
     mOwner = aOwnerWindow->IsOuterWindow() ?
       aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow;
   } else {
     mOwner = nsnull;
   }
 
   nsCOMPtr<nsIJSContextStack> stack =
@@ -285,18 +297,18 @@ nsEventSource::Init(nsIPrincipal* aPrinc
 
   rv = os->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(this, DOM_WINDOW_THAWED_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsXPIDLCString origin;
-  rv = mPrincipal->GetOrigin(getter_Copies(origin));
+  nsAutoString origin;
+  rv = nsContentUtils::GetUTFOrigin(srcURI, origin);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString spec;
   rv = srcURI->GetSpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mOriginalURL = NS_ConvertUTF8toUTF16(spec);
   mSrc = srcURI;
@@ -371,17 +383,41 @@ nsEventSource::Initialize(nsISupports* a
   NS_ENSURE_STATE(scriptContext);
 
   nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
     do_QueryInterface(aOwner);
   NS_ENSURE_STATE(scriptPrincipal);
   nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
   NS_ENSURE_STATE(principal);
 
-  return Init(principal, scriptContext, ownerWindow, urlParam);
+  bool withCredentialsParam = false;
+  if (aArgc >= 2) {
+    NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aArgv[1]), NS_ERROR_INVALID_ARG);
+
+    JSObject *obj = JSVAL_TO_OBJECT(aArgv[1]);
+    NS_ASSERTION(obj, "obj shouldn't be null!!");
+
+    JSBool hasProperty = JS_FALSE;
+    NS_ENSURE_TRUE(JS_HasProperty(aContext, obj, "withCredentials",
+                                  &hasProperty), NS_ERROR_FAILURE);
+
+    if (hasProperty) {
+      jsval withCredentialsVal;
+      NS_ENSURE_TRUE(JS_GetProperty(aContext, obj, "withCredentials",
+                                    &withCredentialsVal), NS_ERROR_FAILURE);
+
+      JSBool withCredentials = JS_FALSE;
+      NS_ENSURE_TRUE(JS_ValueToBoolean(aContext, withCredentialsVal,
+                                       &withCredentials), NS_ERROR_FAILURE);
+      withCredentialsParam = !!withCredentials;
+    }
+  }
+
+  return Init(principal, scriptContext, ownerWindow,
+              urlParam, withCredentialsParam);
 }
 
 //-----------------------------------------------------------------------------
 // nsEventSource::nsIObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsEventSource::Observe(nsISupports* aSubject,
@@ -881,18 +917,23 @@ nsEventSource::InitChannelAndRequestEven
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHttpChannel = do_QueryInterface(channel);
   NS_ENSURE_TRUE(mHttpChannel, NS_ERROR_NO_INTERFACE);
 
   rv = SetupHttpChannel();
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCOMPtr<nsIStreamListener> listener =
+    new nsCORSListenerProxy(this, mPrincipal, mHttpChannel,
+                            mWithCredentials, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Start reading from the channel
-  return mHttpChannel->AsyncOpen(this, nsnull);
+  return mHttpChannel->AsyncOpen(listener, nsnull);
 }
 
 void
 nsEventSource::AnnounceConnection()
 {
   if (mReadyState == nsIEventSource::CLOSED) {
     return;
   }
@@ -1168,26 +1209,23 @@ nsEventSource::FailConnection()
 
 bool
 nsEventSource::CheckCanRequestSrc(nsIURI* aSrc)
 {
   if (mReadyState == nsIEventSource::CLOSED) {
     return false;
   }
 
-  bool isSameOrigin = false;
   bool isValidURI = false;
   bool isValidContentLoadPolicy = false;
   bool isValidProtocol = false;
 
   nsCOMPtr<nsIURI> srcToTest = aSrc ? aSrc : mSrc.get();
   NS_ENSURE_TRUE(srcToTest, false);
 
-  isSameOrigin = NS_SUCCEEDED(mPrincipal->CheckMayLoad(srcToTest, false));
-
   PRUint32 aCheckURIFlags =
     nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL |
     nsIScriptSecurityManager::DISALLOW_SCRIPT;
 
   nsresult rv = nsContentUtils::GetSecurityManager()->
     CheckLoadURIWithPrincipal(mPrincipal,
                               srcToTest,
                               aCheckURIFlags);
@@ -1217,18 +1255,17 @@ nsEventSource::CheckCanRequestSrc(nsIURI
   nsCAutoString targetURIScheme;
   rv = srcToTest->GetScheme(targetURIScheme);
   if (NS_SUCCEEDED(rv)) {
     // We only have the http support for now
     isValidProtocol = targetURIScheme.EqualsLiteral("http") ||
                       targetURIScheme.EqualsLiteral("https");
   }
 
-  return isSameOrigin && isValidURI && isValidContentLoadPolicy &&
-         isValidProtocol;
+  return isValidURI && isValidContentLoadPolicy && isValidProtocol;
 }
 
 // static
 void
 nsEventSource::TimerCallback(nsITimer* aTimer, void* aClosure)
 {
   nsRefPtr<nsEventSource> thisObject = static_cast<nsEventSource*>(aClosure);
 
@@ -1382,17 +1419,17 @@ nsEventSource::DispatchAllMessageEvents(
       NS_WARNING("Failed to create the message event!!!");
       return;
     }
 
     nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event);
     rv = messageEvent->InitMessageEvent(message->mEventName,
                                         false, false,
                                         jsData,
-                                        NS_ConvertUTF8toUTF16(mOrigin),
+                                        mOrigin,
                                         message->mLastEventID, nsnull);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to init the message event!!!");
       return;
     }
 
     nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
     privateEvent->SetTrusted(true);
--- a/content/base/src/nsEventSource.h
+++ b/content/base/src/nsEventSource.h
@@ -210,16 +210,17 @@ protected:
     PARSE_STATE_FIELD_VALUE,
     PARSE_STATE_BEGIN_OF_LINE
   };
   ParserStatus mStatus;
 
   bool mFrozen;
   bool mErrorLoadOnRedirect;
   bool mGoingToDispatchAllMessages;
+  bool mWithCredentials;
 
   // used while reading the input streams
   nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
   nsresult mLastConvertionResult;
   nsString mLastFieldName;
   nsString mLastFieldValue;
 
   nsRefPtr<nsDOMEventListenerWrapper> mOnOpenListener;
@@ -238,17 +239,17 @@ protected:
   nsCOMPtr<nsIHttpChannel> mHttpChannel;
 
   nsCOMPtr<nsITimer> mTimer;
 
   PRInt32 mReadyState;
   nsString mOriginalURL;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
-  nsCString mOrigin;
+  nsString mOrigin;
 
   PRUint32 mRedirectFlags;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   nsCOMPtr<nsIChannel> mNewRedirectChannel;
 
   // Event Source owner information:
   // - the script file name
   // - source code line number where the Event Source object was constructed.
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3062,45 +3062,38 @@ nsGenericElement::BindToTree(nsIDocument
   NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
                    "Bound to wrong binding parent");
 
   return NS_OK;
 }
 
-static bool
-IsFullScreenAncestor(Element* aElement)
-{
-  nsEventStates state = aElement->State();
-  return state.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
-                                     NS_EVENT_STATE_FULL_SCREEN);
-}
-
 void
 nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
                   "Shallow unbind won't clear document and binding parent on "
                   "kids!");
   // Make sure to unbind this node before doing the kids
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
 
   if (aNullParent) {
-    if (IsFullScreenAncestor(this)) {
+    if (IsFullScreenAncestor()) {
       // The element being removed is an ancestor of the full-screen element,
       // exit full-screen state.
       nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
                                       "RemovedFullScreenElement",
                                       nsnull, 0, nsnull,
                                       EmptyString(), 0, 0,
                                       nsIScriptError::warningFlag,
-                                      "DOM", OwnerDoc());      
-      OwnerDoc()->CancelFullScreen();
+                                      "DOM", OwnerDoc());
+      // Fully exit full-screen.
+      nsIDocument::ExitFullScreen(false);
     }
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nsnull;
     }
     SetParentIsContent(false);
   }
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -489,16 +489,17 @@ include $(topsrcdir)/config/rules.mk
 		badContentType.eventsource \
 		badContentType.eventsource^headers^ \
 		badEventFieldName.eventsource \
 		badEventFieldName.eventsource^headers^ \
 		badHTTPResponseCode.eventsource \
 		badHTTPResponseCode.eventsource^headers^ \
 		badMessageEvent.eventsource \
 		badMessageEvent.eventsource^headers^ \
+		file_restrictedEventSource.sjs \
 		forRemoval.resource \
 		forRemoval.resource^headers^ \
 		accesscontrol.resource \
 		accesscontrol.resource^headers^ \
 		invalid_accesscontrol.resource \
 		invalid_accesscontrol.resource^headers^ \
 		test_xhr_progressevents.html \
 		progressserver.sjs \
--- a/content/base/test/accesscontrol.resource^headers^
+++ b/content/base/test/accesscontrol.resource^headers^
@@ -1,4 +1,5 @@
-Access-Control-Allow-Origin: http://localhost:8888
+Access-Control-Allow-Origin: http://mochi.test:8888
+Access-Control-Allow-Credentials: true
 Content-Type: text/event-stream
 Cache-Control: no-cache, must-revalidate
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_restrictedEventSource.sjs
@@ -0,0 +1,50 @@
+function handleRequest(request, response)
+{
+  if ((request.queryString == "test=user1_xhr" &&
+       request.hasHeader("Authorization") &&
+       request.getHeader("Authorization") == "Basic dXNlciAxOnBhc3N3b3JkIDE=") ||
+      (request.queryString == "test=user1_evtsrc" &&
+       request.hasHeader("Authorization") &&
+       request.getHeader("Authorization") == "Basic dXNlciAxOnBhc3N3b3JkIDE=" &&
+       request.hasHeader("Cookie") &&
+       request.getHeader("Cookie") == "test=5c")) {
+    response.setStatusLine(null, 200, "OK");
+    response.setHeader("Content-Type", "text/event-stream", false);
+    response.setHeader("Access-Control-Allow-Origin", "http://mochi.test:8888", false);
+    response.setHeader("Access-Control-Allow-Credentials", "true", false);
+    response.setHeader("Cache-Control", "no-cache, must-revalidate", false);
+    if (request.queryString == "test=user1_xhr") {
+      response.setHeader("Set-Cookie", "test=5c", false);
+    }
+    response.write("event: message\ndata: 1\n\n");
+  } else if ((request.queryString == "test=user2_xhr" &&
+              request.hasHeader("Authorization") &&
+              request.getHeader("Authorization") == "Basic dXNlciAyOnBhc3N3b3JkIDI=") ||
+             (request.queryString == "test=user2_evtsrc" &&
+              request.hasHeader("Authorization") &&
+              request.getHeader("Authorization") == "Basic dXNlciAyOnBhc3N3b3JkIDI=" &&
+              request.hasHeader("Cookie") &&
+              request.getHeader("Cookie") == "test=5d")) {
+    response.setStatusLine(null, 200, "OK");
+    response.setHeader("Content-Type", "text/event-stream", false);
+    response.setHeader("Access-Control-Allow-Origin", "http://mochi.test:8888", false);
+    response.setHeader("Access-Control-Allow-Credentials", "true", false);
+    response.setHeader("Cache-Control", "no-cache, must-revalidate", false);
+    if (request.queryString == "test=user2_xhr") {
+      response.setHeader("Set-Cookie", "test=5d", false);
+    }
+    response.write("event: message\ndata: 1\n\n");
+  } else if (request.queryString == "test=user1_xhr" ||
+             request.queryString == "test=user2_xhr") {
+    response.setStatusLine(null, 401, "Unauthorized");
+    response.setHeader("WWW-Authenticate", "basic realm=\"restricted\"", false);
+    response.setHeader("Access-Control-Allow-Origin", "http://mochi.test:8888", false);
+    response.setHeader("Access-Control-Allow-Credentials", "true", false);
+    response.write("Unauthorized");
+  } else {
+    response.setStatusLine(null, 403, "Forbidden");
+    response.setHeader("Access-Control-Allow-Origin", "http://mochi.test:8888", false);
+    response.setHeader("Access-Control-Allow-Credentials", "true", false);
+    response.write("Forbidden");
+  }
+}
\ No newline at end of file
--- a/content/base/test/test_bug338583.html
+++ b/content/base/test/test_bug338583.html
@@ -27,34 +27,56 @@ https://bugzilla.mozilla.org/show_bug.cg
 //   3) possible invalid eventsources
 //   4) the close method when the object is just been used
 //   5) access-control
 //   6) the data parameter
 //   7) delayed server responses
 
 // --
 
+  var gTestsHaveFinished = [];
+
+  function setTestHasFinished(test_id)
+  {
+    if (gTestsHaveFinished[test_id]) {
+      return;
+    }
+
+    gTestsHaveFinished[test_id] = true;
+    for (var i=0; i < gTestsHaveFinished.length; ++i) {
+      if (!gTestsHaveFinished[i]) {
+        return;
+      }
+    }
+
+    SimpleTest.finish();
+  }
+
   function runAllTests() {
-    // these tests run asynchronously
-    doTest1();    // this will take 8000 ms
-    doTest2();    // this will take 5000 ms
-    doTest3();    // this will take 1500 ms
-    doTest3_b();  // this will take 1500 ms
-    doTest3_c();  // this will take 1500 ms
-    doTest3_d();  // this will take 1500 ms
-    doTest3_e();  // this will take 1500 ms
-    doTest3_f();  // this will take 1500 ms
-    doTest3_g();  // this will take 1500 ms
-    doTest3_h();  // this will take 1500 ms
-    doTest4();    // this will take 3000 ms
-    doTest4_b();  // this will take 3000 ms
-    doTest5();    // this will take 3000 ms
-    doTest5_b();  // this will take 3000 ms
-    doTest6();    // this will take 2500 ms
-    doTest7();    // this will take 8000 ms
+    // these tests run asynchronously, and they will take 8000 ms
+    var all_tests = [
+      doTest1, doTest1_e, doTest2, doTest3, doTest3_b, doTest3_c, doTest3_d,
+      doTest3_e, doTest3_f, doTest3_g, doTest3_h, doTest4, doTest4_b,
+      doTest5, doTest5_b, doTest5_c, doTest5_e, doTest6, doTest7
+    ];
+
+    for (var test_id=0; test_id < all_tests.length; ++test_id) {
+      gTestsHaveFinished[test_id] = false;
+      var fn = all_tests[test_id];
+      fn(test_id);
+    }
+
+    setTimeout(function() {
+      for (var test_id=0; test_id < all_tests.length; ++test_id) {
+        if (!gTestsHaveFinished[test_id]) {
+          ok(false, "Test " + test_id + " took too long");
+          setTestHasFinished(test_id);
+        }
+      }
+    }, 60000 * stress_factor); // all tests together are supposed to take less than 1 minute
   }
 
   function fn_onmessage(e) {
     if (e.currentTarget == e.target && e.target.hits != null)
       e.target.hits['fn_onmessage']++;
   }
 
   function fn_event_listener_message(e) {
@@ -65,24 +87,26 @@ https://bugzilla.mozilla.org/show_bug.cg
   function fn_other_event_name(e) {
     if (e.currentTarget == e.target && e.target.hits != null)
       e.target.hits['fn_other_event_name']++;
   }
 
   var domBranch;
   var oldPrefVal;
 
-  var gEventSourceObj1 = null;
+  var gEventSourceObj1 = null, gEventSourceObj1_e;
   var gEventSourceObj2 = null;
   var gEventSourceObj3_a = null, gEventSourceObj3_b = null,
       gEventSourceObj3_c = null, gEventSourceObj3_d = null,
       gEventSourceObj3_e = null, gEventSourceObj3_f = null,
       gEventSourceObj3_g = null, gEventSourceObj3_h = null;
   var gEventSourceObj4_a = null, gEventSourceObj4_b = null;
-  var gEventSourceObj5_a = null, gEventSourceObj5_b = null;
+  var gEventSourceObj5_a = null, gEventSourceObj5_b = null,
+      gEventSourceObj5_c = null, gEventSourceObj5_d = null,
+      gEventSourceObj5_e = null, gEventSourceObj5_f = null;
   var gEventSourceObj6 = null;
   var gEventSourceObj7 = null;
   var stress_factor;  // used in the setTimeouts in order to help
                       // the test when running in slow machines
 
   function hasBeenHitFor1And2(obj, min) {
     if (obj.hits['fn_onmessage'] < min ||
         obj.hits['fn_event_listener_message'] < min ||
@@ -91,205 +115,227 @@ https://bugzilla.mozilla.org/show_bug.cg
     return true;
   }
 
 // in order to test (1):
 //   a) if the EventSource constructor parameter is equal to its url attribute
 //   b) let its fn_onmessage, fn_event_listener_message, and fn_other_event_name functions listeners be hit four times each
 //   c) the close method (we expect readyState == CLOSED)
 //   d) the close method (we expect no message events anymore)
+//   e) if the ctor throws an exception when the second parameter is null
 
-  function doTest1() {
+  function doTest1(test_id) {
     gEventSourceObj1 = new EventSource("eventsource.resource");
     ok(gEventSourceObj1.url == "http://mochi.test:8888/tests/content/base/test/eventsource.resource", "Test 1.a failed.");
     ok(gEventSourceObj1.readyState == 0 || gEventSourceObj1.readyState == 1, "Test 1.a failed.");
 
-    doTest1_b();
+    doTest1_b(test_id);
   }
 
-  function doTest1_b() {
+  function doTest1_b(test_id) {
     gEventSourceObj1.hits = [];
     gEventSourceObj1.hits['fn_onmessage'] = 0;
     gEventSourceObj1.onmessage = fn_onmessage;
     gEventSourceObj1.hits['fn_event_listener_message'] = 0;
     gEventSourceObj1.addEventListener('message', fn_event_listener_message, true);
     gEventSourceObj1.hits['fn_other_event_name'] = 0;
     gEventSourceObj1.addEventListener('other_event_name', fn_other_event_name, true);
 
     // the eventsources.res always use a retry of 0.5 second, so for four hits a timeout of 6 seconds is enough
     setTimeout(function(){
       bhits = hasBeenHitFor1And2(gEventSourceObj1, 4);
       ok(bhits, "Test 1.b failed.");
 
-      doTest1_c();
+      doTest1_c(test_id);
     }, parseInt(6000*stress_factor));
   }
 
-  function doTest1_c() {
+  function doTest1_c(test_id) {
     gEventSourceObj1.close();
     ok(gEventSourceObj1.readyState == 2, "Test 1.c failed.");
 
-    doTest1_d();
+    doTest1_d(test_id);
   }
 
-  function doTest1_d() {
+  function doTest1_d(test_id) {
     gEventSourceObj1.hits['fn_onmessage'] = 0;
     gEventSourceObj1.hits['fn_event_listener_message'] = 0;
     gEventSourceObj1.hits['fn_other_event_name'] = 0;
 
     setTimeout(function(){
       bhits = hasBeenHitFor1And2(gEventSourceObj1, 1);
       ok(!bhits, "Test 1.d failed.");
       gEventSourceObj1.close();
+      setTestHasFinished(test_id);
     }, parseInt(2000*stress_factor));
   }
 
+  function doTest1_e(test_id) {
+    try {
+      gEventSourceObj1_e = new EventSource("eventsource.resource", null);
+      ok(false, "Test 1.e failed");
+      gEventSourceObj1_e.close();
+    } catch (e) {
+      ok(true, "Test 1.e failed");
+    }
+    setTestHasFinished(test_id);
+  }
+
 // in order to test (2)
 //   a) set a eventsource that give the dom events messages
 //   b) expect trusted events
 
-  function doTest2() {
+  function doTest2(test_id) {
     var func = function(e) {
       ok(e.isTrusted, "Test 2 failed");
       gEventSourceObj2.close();
     };
 
     gEventSourceObj2 = new EventSource("eventsource.resource");
     gEventSourceObj2.onmessage = func;
 
-    setTimeout(function(){  // just to clean...
+    setTimeout(function() {  // just to clean...
       gEventSourceObj2.close();
+      setTestHasFinished(test_id);
     }, parseInt(5000*stress_factor));
   }
 
 // in order to test (3)
 //   a) XSite domain error test
 //   b) protocol file:// test
 //   c) protocol javascript: test
 //   d) wrong Content-Type test
 //   e) bad http response code test
 //   f) message eventsource without a data test
 //   g) eventsource with invalid NCName char in the event field test
 //   h) DNS error
 
-  function doTest3() {
+  function doTest3(test_id) {
     gEventSourceObj3_a = new EventSource("http://example.org/tests/content/base/test/eventsource.resource");
 
     gEventSourceObj3_a.onmessage = fn_onmessage;
     gEventSourceObj3_a.hits = [];
     gEventSourceObj3_a.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_a.hits['fn_onmessage'] == 0, "Test 3.a failed");
       gEventSourceObj3_a.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
-  function doTest3_b() {
+  function doTest3_b(test_id) {
     var xhr = new XMLHttpRequest;
     xhr.open("GET", "/dynamic/getMyDirectory.sjs", false);
     xhr.send();
     var basePath = xhr.responseText;
 
     gEventSourceObj3_b = new EventSource("file://" + basePath + "eventsource.resource");
 
     gEventSourceObj3_b.onmessage = fn_onmessage;
     gEventSourceObj3_b.hits = [];
     gEventSourceObj3_b.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_b.hits['fn_onmessage'] == 0, "Test 3.b failed");
       gEventSourceObj3_b.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
   function jsEvtSource()
   {
     return "event: message\n" +
            "data: 1\n\n";
   }
 
-  function doTest3_c() {
+  function doTest3_c(test_id) {
     gEventSourceObj3_c = new EventSource("javascript: return jsEvtSource()");
 
     gEventSourceObj3_c.onmessage = fn_onmessage;
     gEventSourceObj3_c.hits = [];
     gEventSourceObj3_c.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_c.hits['fn_onmessage'] == 0, "Test 3.c failed");
       gEventSourceObj3_c.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
-  function doTest3_d() {
+  function doTest3_d(test_id) {
     gEventSourceObj3_d = new EventSource("badContentType.eventsource");
 
     gEventSourceObj3_d.onmessage = fn_onmessage;
     gEventSourceObj3_d.hits = [];
     gEventSourceObj3_d.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_d.hits['fn_onmessage'] == 0, "Test 3.d failed");
       gEventSourceObj3_d.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
-  function doTest3_e() {
+  function doTest3_e(test_id) {
     gEventSourceObj3_e = new EventSource("badHTTPResponseCode.eventsource");
 
     gEventSourceObj3_e.onmessage = fn_onmessage;
     gEventSourceObj3_e.hits = [];
     gEventSourceObj3_e.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_e.hits['fn_onmessage'] == 0, "Test 3.e failed");
       gEventSourceObj3_e.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
-  function doTest3_f() {
+  function doTest3_f(test_id) {
     gEventSourceObj3_f = new EventSource("badMessageEvent.eventsource");
 
     gEventSourceObj3_f.onmessage = fn_onmessage;
     gEventSourceObj3_f.hits = [];
     gEventSourceObj3_f.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_f.hits['fn_onmessage'] == 0, "Test 3.f failed");
       gEventSourceObj3_f.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
   function fnInvalidNCName() {
     fnInvalidNCName.hits++;
   }
 
-  function doTest3_g() {
+  function doTest3_g(test_id) {
     gEventSourceObj3_g = new EventSource("badEventFieldName.eventsource");
 
     fnInvalidNCName.hits = 0;
     gEventSourceObj3_g.addEventListener('message event', fnInvalidNCName, true);
 
     setTimeout(function() {
       ok(fnInvalidNCName.hits != 0, "Test 3.g failed");
       gEventSourceObj3_g.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
-  function doTest3_h() {
+  function doTest3_h(test_id) {
     gEventSourceObj3_h = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com");
 
     gEventSourceObj3_h.onmessage = fn_onmessage;
     gEventSourceObj3_h.hits = [];
     gEventSourceObj3_h.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj3_h.hits['fn_onmessage'] == 0, "Test 3.h failed");
       gEventSourceObj3_h.close();
+      setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
 // in order to test (4)
 //   a) close the object when it is in use, which is being processed and that is expected
 //      to dispatch more eventlisteners
 //   b) remove an eventlistener in use
 
@@ -304,72 +350,186 @@ https://bugzilla.mozilla.org/show_bug.cg
   function fn_onmessage4_b(e)
   {
     if (e.data > gEventSourceObj4_b.lastData)
       gEventSourceObj4_b.lastData = e.data;
     if (e.data == 2)
       gEventSourceObj4_b.removeEventListener('message', fn_onmessage4_b, true);
   }
 
-  function doTest4() {
+  function doTest4(test_id) {
     gEventSourceObj4_a = new EventSource("forRemoval.resource");
     gEventSourceObj4_a.lastData = 0;
     gEventSourceObj4_a.onmessage = fn_onmessage4_a;
 
     setTimeout(function() {
       ok(gEventSourceObj4_a.lastData == 2, "Test 4.a failed");
       gEventSourceObj4_a.close();
+      setTestHasFinished(test_id);
     }, parseInt(3000*stress_factor));
   }
 
-  function doTest4_b()
+  function doTest4_b(test_id)
   {
     gEventSourceObj4_b = new EventSource("forRemoval.resource");
     gEventSourceObj4_b.lastData = 0;
     gEventSourceObj4_b.addEventListener('message', fn_onmessage4_b, true);
 
     setTimeout(function() {
       ok(gEventSourceObj4_b.lastData == 2, "Test 4.b failed");
       gEventSourceObj4_b.close();
+      setTestHasFinished(test_id);
     }, parseInt(3000*stress_factor));
   }
 
 // in order to test (5)
-//   a) valid access-control xsite request (but must fail)
+//   a) valid access-control xsite request
 //   b) invalid access-control xsite request
+//   c) valid access-control xsite request on a restricted page with credentials
+//   d) valid access-control xsite request on a restricted page without credentials
+//   e) valid access-control xsite request on a restricted page when the parameter withCredentials is a getter 
+//   f) valid access-control xsite request on a restricted page when the parameter withCredentials is missing 
 
-  function doTest5()
+  function doTest5(test_id)
   {
     gEventSourceObj5_a = new EventSource("http://example.org/tests/content/base/test/accesscontrol.resource");
 
     gEventSourceObj5_a.onmessage = fn_onmessage;
     gEventSourceObj5_a.hits = [];
     gEventSourceObj5_a.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
-      ok(gEventSourceObj5_a.hits['fn_onmessage'] == 0, "Test 5.a failed");
+      ok(gEventSourceObj5_a.hits['fn_onmessage'] != 0, "Test 5.a failed");
       gEventSourceObj5_a.close();
+      setTestHasFinished(test_id);
     }, parseInt(3000*stress_factor));
   }
 
-  function doTest5_b()
+  function doTest5_b(test_id)
   {
     gEventSourceObj5_b = new EventSource("http://example.org/tests/content/base/test/invalid_accesscontrol.resource");
 
     gEventSourceObj5_b.onmessage = fn_onmessage;
     gEventSourceObj5_b.hits = [];
     gEventSourceObj5_b.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
       ok(gEventSourceObj5_b.hits['fn_onmessage'] == 0, "Test 5.b failed");
       gEventSourceObj5_b.close();
+      setTestHasFinished(test_id);
+    }, parseInt(3000*stress_factor));
+  }
+
+  function doTest5_c(test_id)
+  {
+    // credentials using the auth cache and cookies
+    var xhr = SpecialPowers.createSystemXHR();
+    xhr.withCredentials = true;
+    // also, test mixed mode UI
+    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
+    xhr.send();
+    ok(xhr.status == 200, "Failed to set credentials in test 5.c");
+
+    gEventSourceObj5_c = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
+                                         { withCredentials: true } );
+    ok(gEventSourceObj5_c.withCredentials, "Wrong withCredentials in test 5.c");
+
+    gEventSourceObj5_c.onmessage = function(e) {
+      ok(e.origin == "https://example.com", "Wrong Origin in test 5.c");
+      fn_onmessage(e);
+    };
+    gEventSourceObj5_c.hits = [];
+    gEventSourceObj5_c.hits['fn_onmessage'] = 0;
+
+    setTimeout(function() {
+      ok(gEventSourceObj5_c.hits['fn_onmessage'] > 0, "Test 5.c failed");
+      gEventSourceObj5_c.close();
+      doTest5_d(test_id);
     }, parseInt(3000*stress_factor));
   }
 
-  function doTest6()
+  function doTest5_d(test_id)
+  {
+    var xhr = SpecialPowers.createSystemXHR();
+    xhr.withCredentials = true;
+    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
+    xhr.send();
+    ok(xhr.status == 200, "Failed to set credentials in test 5.d");
+
+    gEventSourceObj5_d = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc");
+    ok(!gEventSourceObj5_d.withCredentials, "Wrong withCredentials in test 5.d");
+
+    gEventSourceObj5_d.onmessage = function(e) {
+      ok(e.origin == "https://example.com", "Wrong Origin in test 5.d");
+      fn_onmessage(e);
+    };
+    gEventSourceObj5_d.hits = [];
+    gEventSourceObj5_d.hits['fn_onmessage'] = 0;
+
+    setTimeout(function() {
+      ok(gEventSourceObj5_d.hits['fn_onmessage'] == 0, "Test 5.d failed");
+      gEventSourceObj5_d.close();
+      setTestHasFinished(test_id);
+    }, parseInt(3000*stress_factor));
+  }
+
+  function doTest5_e(test_id)
+  {
+    // credentials using the auth cache and cookies
+    var xhr = SpecialPowers.createSystemXHR();
+    xhr.withCredentials = true;
+    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
+    xhr.send();
+    ok(xhr.status == 200, "Failed to set credentials in test 5.e");
+
+    gEventSourceObj5_e = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
+                                         { get withCredentials() { return true; } } );
+    ok(gEventSourceObj5_e.withCredentials, "Wrong withCredentials in test 5.e");
+
+    gEventSourceObj5_e.onmessage = function(e) {
+      ok(e.origin == "http://example.org", "Wrong Origin in test 5.e");
+      fn_onmessage(e);
+    };
+    gEventSourceObj5_e.hits = [];
+    gEventSourceObj5_e.hits['fn_onmessage'] = 0;
+
+    setTimeout(function() {
+      ok(gEventSourceObj5_e.hits['fn_onmessage'] > 0, "Test 5.e failed");
+      gEventSourceObj5_e.close();
+      doTest5_f(test_id);
+    }, parseInt(5000*stress_factor));
+  }
+
+  function doTest5_f(test_id)
+  {
+    var xhr = SpecialPowers.createSystemXHR();
+    xhr.withCredentials = true;
+    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
+    xhr.send();
+    ok(xhr.status == 200, "Failed to set credentials in test 5.f");
+
+    gEventSourceObj5_f = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc",
+                                         { });
+    ok(!gEventSourceObj5_f.withCredentials, "Wrong withCredentials in test 5.f");
+
+    gEventSourceObj5_f.onmessage = function(e) {
+      ok(e.origin == "http://example.org", "Wrong Origin in test 5.f");
+      fn_onmessage(e);
+    };
+    gEventSourceObj5_f.hits = [];
+    gEventSourceObj5_f.hits['fn_onmessage'] = 0;
+
+    setTimeout(function() {
+      ok(gEventSourceObj5_f.hits['fn_onmessage'] == 0, "Test 5.f failed");
+      gEventSourceObj5_f.close();
+      setTestHasFinished(test_id);
+    }, parseInt(3000*stress_factor));
+  }
+
+  function doTest6(test_id)
   {
     gEventSourceObj6 = new EventSource("somedatas.resource");
     var fn_somedata = function(e) {
       if (fn_somedata.expected == 0) {
         ok(e.data == "123456789\n123456789123456789\n123456789123456789123456789123456789\n 123456789123456789123456789123456789123456789123456789123456789123456789\nçãá\"\'@`~Ý Ḿyyyy",
           "Test 6.a failed");
       } else if (fn_somedata.expected == 1) {
         ok(e.data == " :xxabcdefghij\nçãá\"\'@`~Ý Ḿyyyy : zz",
@@ -382,20 +542,21 @@ https://bugzilla.mozilla.org/show_bug.cg
       }
       fn_somedata.expected++;
     }
     fn_somedata.expected = 0;
     gEventSourceObj6.onmessage = fn_somedata;
 
     setTimeout(function() {
       gEventSourceObj6.close();
+      setTestHasFinished(test_id);
     }, parseInt(2500*stress_factor));
   }
 
-  function doTest7()
+  function doTest7(test_id)
   {
     gEventSourceObj7 = new EventSource("delayedServerEvents.sjs");
     gEventSourceObj7.msg_received = [];
     gEventSourceObj7.onmessage = function(e)
     {
       e.target.msg_received.push(e.data);
     }
     
@@ -403,21 +564,21 @@ https://bugzilla.mozilla.org/show_bug.cg
       gEventSourceObj7.close();
       
       ok(gEventSourceObj7.msg_received[0] == "" &&
          gEventSourceObj7.msg_received[1] == "delayed1" &&
          gEventSourceObj7.msg_received[2] == "delayed2", "Test 7 failed");
 
       SpecialPowers.setBoolPref("dom.server-events.enabled", oldPrefVal);
       document.getElementById('waitSpan').innerHTML = '';
-      SimpleTest.finish();
+      setTestHasFinished(test_id);
     }, parseInt(8000*stress_factor));
   }
 
-  function doTest()
+  function doTest(test_id)
   {
     oldPrefVal = SpecialPowers.getBoolPref("dom.server-events.enabled");
     SpecialPowers.setBoolPref("dom.server-events.enabled", true);
 
     // we get a good stress_factor by testing 10 setTimeouts and some float
     // arithmetic taking my machine as stress_factor==1 (time=589)
 
     var begin_time = (new Date()).getTime();
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -292,18 +292,17 @@ nsHTMLSharedObjectElement::BindToTree(ns
 
 #ifndef XP_MACOSX
   if (aDocument &&
       aDocument->IsFullScreenDoc() &&
       nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
     // This content contains a windowed plugin for which we don't control
     // event dispatch, and we're in full-screen mode. Exit full-screen mode
     // to prevent phishing attacks.
-    NS_DispatchToCurrentThread(
-      NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
+    nsIDocument::ExitFullScreen(true);
     nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
                                     "AddedWindowedPluginWhileFullScreen",
                                     nsnull, 0, nsnull,
                                     EmptyString(), 0, 0,
                                     nsIScriptError::warningFlag,
                                     "DOM", aDocument);           
   }
 #endif
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -287,16 +287,17 @@ include $(topsrcdir)/config/rules.mk
 		test_fullscreen-api.html \
 		file_fullscreen-plugins.html \
 		file_fullscreen-denied.html \
 		file_fullscreen-denied-inner.html \
 		file_fullscreen-hidden.html \
 		file_fullscreen-navigation.html \
 		file_fullscreen-esc-exit.html \
 		file_fullscreen-esc-exit-inner.html \
+		file_fullscreen-rollback.html \
 		test_li_attributes_reflection.html \
 		test_ol_attributes_reflection.html \
 		test_bug651956.html \
 		test_bug694503.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/content/html/content/test/file_fullscreen-api-keys.html
+++ b/content/html/content/test/file_fullscreen-api-keys.html
@@ -23,21 +23,21 @@ Test that restricted key pressed drop do
 
 // List of key codes which should exit full-screen mode.
 var keyList = [
   { code: "VK_ESCAPE", suppressed: true},
   { code: "VK_F11",    suppressed: false},
 ];
 
 function ok(condition, msg) {
-  opener.ok(condition, msg);
+  opener.ok(condition, "[keys] " + msg);
 }
 
 function is(a, b, msg) {
-  opener.is(a, b, msg);
+  opener.is(a, b, "[keys] " + msg);
 }
 
 var gKeyTestIndex = 0;
 var gKeyName;
 var gKeyCode;
 var gKeySuppressed;
 var gKeyReceived = false;
 
--- a/content/html/content/test/file_fullscreen-api.html
+++ b/content/html/content/test/file_fullscreen-api.html
@@ -17,21 +17,21 @@ Test DOM full-screen API.
   </style>
 </head>
 <body onload="start();">
 <script type="application/javascript">
 
 /** Test for Bug 545812 **/
 
 function ok(condition, msg) {
-  opener.ok(condition, msg);
+  opener.ok(condition, "[fullscreen] " + msg);
 }
 
 function is(a, b, msg) {
-  opener.is(a, b, msg);
+  opener.is(a, b, "[fullscreen] " + msg);
 }
 
 /*
 <html>
   <body onload='document.body.mozRequestFullScreen();'>
   <iframe id='inner-frame'></iframe>
   </body>
 </html>
@@ -59,151 +59,151 @@ function setRequireTrustedContext(value)
 
 function fullScreenElement() {
   return document.getElementById('full-screen-element');
 }
 
 function fullScreenChange(event) {
   switch (fullScreenChangeCount) {
     case 0: {
-      ok(document.mozFullScreen, "Should be in full-screen mode (first time)");
-      is(event.target, document, "Event target should be full-screen document #1");
-      is(document.mozFullScreenElement, fullScreenElement(),
-         "Full-screen element should be div element.");
-      ok(document.mozFullScreenElement.mozMatchesSelector(":-moz-full-screen"),
-         "FSE should match :-moz-full-screen");
+      ok(document.mozFullScreen, "1. Should be in full-screen mode (first time)");
+      is(event.target, document, "2. Event target should be full-screen document #1");
+      is(document.mozFullScreenElement, fullScreenElement(), "3. Full-screen element should be div element.");
+      ok(document.mozFullScreenElement.mozMatchesSelector(":-moz-full-screen"), "4. FSE should match :-moz-full-screen");
       var fse = fullScreenElement();
       fse.parentNode.removeChild(fse);
-      is(document.mozFullScreenElement, null,
-         "Full-screen element should be null after removing.");
-      ok(!document.mozFullScreen, "Should have left full-screen mode when we remove full-screen element");
+      is(document.mozFullScreenElement, null, "5. Full-screen element should be null after removing.");
+      ok(!document.mozFullScreen, "6. Should have left full-screen mode when we remove full-screen element");
       document.body.appendChild(fse);
-      ok(!document.mozFullScreen, "Should not return to full-screen mode when re-adding former FSE");
-      is(document.mozFullScreenElement, null,
-         "Full-screen element should still be null after re-adding former FSE.");
+      ok(!document.mozFullScreen, "7. Should not return to full-screen mode when re-adding former FSE");
+      is(document.mozFullScreenElement, null, "8. Full-screen element should still be null after re-adding former FSE.");
       break;
     }
     case 1: {
-      ok(!document.mozFullScreen, "Should have left full-screen mode (first time)");
-      is(event.target, document, "Event target should be full-screen document #2");
-      is(document.mozFullScreenElement, null, "Full-screen element should be null.");
+      ok(!document.mozFullScreen, "9. Should have left full-screen mode (first time)");
+      is(event.target, document, "10. Event target should be full-screen document #2");
+      is(document.mozFullScreenElement, null, "11. Full-screen element should be null.");
       iframe = document.createElement("iframe");
       iframe.mozAllowFullScreen = true;
       document.body.appendChild(iframe);
       iframe.src = iframeContents;
       break;
     }
     case 2: {
-      ok(document.mozFullScreen, "Should be back in full-screen mode (second time)");
-      is(event.target, document, "Event target should be full-screen document #3");
-      is(document.mozFullScreenElement, iframe,
-        "Full-screen element should be iframe element.");
- 
-      SimpleTest.waitForFocus(function() {
-        ok(document.mozFullScreen, "Should still be full-screen mode before focus.");
-        SpecialPowers.focus(window);
-        ok(document.mozFullScreen, "Should still be full-screen mode after focus.");
-        
-        var fse = fullScreenElement();
-        fse.mozRequestFullScreen();
-
-        // RequestFullScreen() is async, continue after it completes.
-        setTimeout(function() {
-          ok(document.mozFullScreen, "Should still be full-screen mode after re-requesting.");
-          is(document.mozFullScreenElement, fse, "Full-screen element should have switched to requestee.");
-          var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
-          _innerFrame.contentDocument.body.appendChild(fse);
-          ok(!document.mozFullScreen, "Should exit full-screen after transplanting FSE");
-          is(document.mozFullScreenElement, null, "Full-screen element transplanted, should be null.");
-          is(iframe.contentDocument.mozFullScreenElement, null, "Full-screen element in outer frame should be null.");
-          is(_innerFrame.contentDocument.mozFullScreenElement, null, "Full-screen element in inner frame should be null.");
-          ok(!iframe.contentDocument.mozFullScreen, "Outer frame should not acquire full-screen status.");
-          ok(!_innerFrame.contentDocument.mozFullScreen, "Inner frame should not acquire full-screen status.");
-          
-          document.body.appendChild(fse);
-        }, 0);
-      }, 0);
+      ok(document.mozFullScreen, "12. Should be back in full-screen mode (second time)");
+      is(event.target, document, "13. Event target should be full-screen document #3");
+      is(document.mozFullScreenElement, iframe, "14. Full-screen element should be iframe element.");
+      is(iframe.contentDocument.mozFullScreenElement, iframe.contentDocument.body, "15. Full-screen element in subframe should be body");
+      
+      // The iframe's body is full-screen. Cancel full-screen in the subdocument to return
+      // the full-screen element to the previous full-screen element. This causes
+      // a fullscreenchange event.
+      document.mozCancelFullScreen();
       break;
     }
     case 3: {
-      ok(!document.mozFullScreen, "Should be back in non-full-screen mode (second time)");
-      is(event.target, document, "Event target should be full-screen document #4");
-      is(document.mozFullScreenElement, null, "Full-screen element should be null.");
+      ok(!document.mozFullScreen, "16. Should have left full-screen when removing FSE ancestor.");
+      is(document.mozFullScreenElement, null, "17. Full-screen element should have rolled back.");
+      is(iframe.contentDocument.mozFullScreenElement, null, "18. Full-screen element in subframe should be null");
+      
+      fullScreenElement().mozRequestFullScreen();
+      break;
+    }
+    case 4: {
+      ok(document.mozFullScreen, "19. Should be back in full-screen mode (second time)");
+      is(event.target, document, "20. Event target should be full-screen document #3");
+      is(document.mozFullScreenElement, fullScreenElement(), "21. Full-screen element should be div.");
+      
+      // Transplant the FSE into subdoc. Should exit full-screen.
+      var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
+      var fse = fullScreenElement();
+      _innerFrame.contentDocument.body.appendChild(fse);
+      ok(!document.mozFullScreen, "22. Should exit full-screen after transplanting FSE");
+      is(document.mozFullScreenElement, null, "23. Full-screen element transplanted, should be null.");
+      is(iframe.contentDocument.mozFullScreenElement, null, "24. Full-screen element in outer frame should be null.");
+      is(_innerFrame.contentDocument.mozFullScreenElement, null, "25. Full-screen element in inner frame should be null.");
+      ok(!iframe.contentDocument.mozFullScreen, "26. Outer frame should not acquire full-screen status.");
+      ok(!_innerFrame.contentDocument.mozFullScreen, "27. Inner frame should not acquire full-screen status.");
+      
+      document.body.appendChild(fse);
+      break;
+    }
+    case 5: {
+      ok(!document.mozFullScreen, "28. Should be back in non-full-screen mode (second time)");
+      is(event.target, document, "29. Event target should be full-screen document #4");
+      is(document.mozFullScreenElement, null, "30. Full-screen element should be null.");
       document.body.removeChild(iframe);
       iframe = null;
 
       // Do a request out of document. It should be denied.
       // Continue test in the following mozfullscreenerror handler.
       outOfDocElement = document.createElement("div");
       var f =
       function(e) {
         document.removeEventListener("mozfullscreenerror", f, false);
-        ok(!document.mozFullScreen, "Requests for full-screen from not-in-doc elements should fail.");
+        ok(!document.mozFullScreen, "31. Requests for full-screen from not-in-doc elements should fail.");
         fullScreenErrorRun = true;
 
         container = document.createElement("div");
         inDocElement = document.createElement("div");
         container.appendChild(inDocElement);
         fullScreenElement().appendChild(container);
         
         inDocElement.mozRequestFullScreen();
       };
       document.addEventListener("mozfullscreenerror", f, false);
       outOfDocElement.mozRequestFullScreen();
 
       break;
     }
-    case 4: {
-      ok(document.mozFullScreen, "Should still be in full-screen mode (third time)");
-      is(event.target, document, "Event target should be full-screen document #5");
-      ok(fullScreenErrorRun, "Should have run fullscreenerror handler from previous case.");
-      is(document.mozFullScreenElement, inDocElement,
-        "FSE should be inDocElement.");
+    case 6: {
+      ok(document.mozFullScreen, "32. Should still be in full-screen mode (third time)");
+      is(event.target, document, "33. Event target should be full-screen document #5");
+      ok(fullScreenErrorRun, "34. Should have run fullscreenerror handler from previous case.");
+      is(document.mozFullScreenElement, inDocElement, "35. FSE should be inDocElement.");
 
       var n = container;
       do {
         ok(n.mozMatchesSelector(":-moz-full-screen-ancestor"), "Ancestor " + n + " should match :-moz-full-screen-ancestor")
         n = n.parentNode;
       } while (n && n.mozMatchesSelector);
         
       // Remove full-screen ancestor element from document, verify it stops being reported as current FSE.
       container.parentNode.removeChild(container);
-      ok(!document.mozFullScreen,
-         "Should exit full-screen mode after removing full-screen element ancestor from document");
-      is(document.mozFullScreenElement, null,
-        "Should not have a full-screen element again.");
+      ok(!document.mozFullScreen, "36. Should exit full-screen mode after removing full-screen element ancestor from document");
+      is(document.mozFullScreenElement, null, "37. Should not have a full-screen element again.");
       break;
     }
-    case 5: {
-      ok(!document.mozFullScreen, "Should be back in non-full-screen mode (third time)");
+    case 7: {
+      ok(!document.mozFullScreen, "38. Should be back in non-full-screen mode (third time)");
       setRequireTrustedContext(true);
       fullscreendenied = false;
       fullScreenElement().mozRequestFullScreen();
 
       setTimeout(
         function() {
           ok(fullscreendenied, "Request for fullscreen should have been denied because calling context isn't trusted");
           ok(!document.mozFullScreen, "Should still be in normal mode, because calling context isn't trusted.");
           button = document.createElement("button");
           button.onclick = function(){fullScreenElement().mozRequestFullScreen();}
           fullScreenElement().appendChild(button);
           sendMouseClick(button);
         }, 0);
       break;
     }
-    case 6: {
+    case 8: {
       ok(document.mozFullScreen, "Moved to full-screen after mouse click");
       document.mozCancelFullScreen();
       ok(document.mozFullScreen, "Should still be in full-screen mode, because calling context isn't trusted.");
       setRequireTrustedContext(false);
       document.mozCancelFullScreen();
       ok(!document.mozFullScreen, "Should have left full-screen mode.");
       break;
     }
-    case 7: {
+    case 9: {
       ok(!document.mozFullScreen, "Should have left full-screen mode (last time).");
 
       SpecialPowers.setBoolPref("full-screen-api.enabled", false);
       is(document.mozFullScreenEnabled, false, "document.mozFullScreenEnabled should be false if full-screen-api.enabled is false");
       fullscreendenied = false;
       fullScreenElement().mozRequestFullScreen();
       setTimeout(
         function() {
--- a/content/html/content/test/file_fullscreen-denied.html
+++ b/content/html/content/test/file_fullscreen-denied.html
@@ -17,21 +17,21 @@ Test DOM full-screen API.
 </head>
 <body onload="run();">
 
 <script type="application/javascript">
 
 /** Test for Bug 545812 **/
 
 function ok(condition, msg) {
-  opener.ok(condition, msg);
+  opener.ok(condition, "[denied] " + msg);
 }
 
 function is(a, b, msg) {
-  opener.is(a, b, msg);
+  opener.is(a, b, "[denied] " + msg);
 }
 
 var fullscreendenied = false;
 
 document.addEventListener("mozfullscreenerror", function(){fullscreendenied=true;}, false);
 
 var gotFullScreenChange = false;
 
--- a/content/html/content/test/file_fullscreen-esc-exit.html
+++ b/content/html/content/test/file_fullscreen-esc-exit.html
@@ -16,29 +16,30 @@ exit DOM full-screen mode.
   }
   </style>
 </head>
 <body onload="startTest();">
 
 <script type="application/javascript">
 
 function ok(condition, msg) {
-  opener.ok(condition, msg);
+  opener.ok(condition, "[esc-exit] " + msg);
 }
 
 function is(a, b, msg) {
-  opener.is(a, b, msg);
+  opener.is(a, b, "[esc-exit] " + msg);
 }
 
 function finish() {
   opener.nextTest();
 }
 
 function fullscreenchange1(event) {
   ok(document.mozFullScreen, "Should have entered full-screen mode");
+  is(document.mozFullScreenElement, document.body, "FSE should be doc");
   document.removeEventListener("mozfullscreenchange", fullscreenchange1, false);
   document.addEventListener("mozfullscreenchange", fullscreenchange2, false);
   ok(!document.getElementById("subdoc").contentWindow.escKeySent, "Should not yet have sent ESC key press.");
   document.getElementById("subdoc").contentWindow.startTest();
 }
 
 function fullscreenchange2(event) {
   document.removeEventListener("mozfullscreenchange", fullscreenchange2, false);
--- a/content/html/content/test/file_fullscreen-hidden.html
+++ b/content/html/content/test/file_fullscreen-hidden.html
@@ -29,22 +29,23 @@ function boom()
 {
   frameWin = document.getElementById("f").contentWindow;
   e1 = frameWin.document.documentElement;
   frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
 }
 
 function b2()
 {
-  try { e1.mozRequestFullScreen(); } catch(e) { opener.ok(false, "Should not enter full-screen"); }
+  try { e1.mozRequestFullScreen(); } catch(e) { opener.ok(false, "[hidden] Should not enter full-screen"); }
   setTimeout(done, 0);
 }
 
 function done() {
-  opener.ok(!document.mozFullScreen, "Should not have entered full-screen mode in hidden document.");
-  opener.ok(!e1.ownerDocument.mozFullScreen, "Requesting owner should not have entered full-screen mode.");
+  opener.ok(!document.mozFullScreen, "[hidden] Should not have entered full-screen mode in hidden document.");
+  opener.ok(!e1.ownerDocument.mozFullScreen, "[hidden] Requesting owner should not have entered full-screen mode.");
   opener.nextTest();
 }
 
 </script>
 </pre>
 </body>
+
 </html>
--- a/content/html/content/test/file_fullscreen-navigation.html
+++ b/content/html/content/test/file_fullscreen-navigation.html
@@ -29,23 +29,23 @@ var prevTrusted;
 
 function boom()
 {
   frameWin = document.getElementById("f").contentWindow;
   e1 = frameWin.document.body;
   e1.mozRequestFullScreen();
   setTimeout(
     function() {
-      opener.ok(document.mozFullScreen, "Request should be granted");
+      opener.ok(document.mozFullScreen, "[navigation] Request should be granted");
       frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
     }, 0);
 }
 
 function b2()
 {
-  opener.ok(!document.mozFullScreen, "Should have left full-screen due to navigation.");
+  opener.ok(!document.mozFullScreen, "[navigation] Should have left full-screen due to navigation.");
   opener.nextTest();
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/html/content/test/file_fullscreen-plugins.html
+++ b/content/html/content/test/file_fullscreen-plugins.html
@@ -38,21 +38,21 @@ Test plugins with DOM full-screen API:
 
 <iframe id="subdoc-plugin" src="data:text/html;charset=utf-8,<html><body><embed id%3D'windowed-plugin' type%3D'application%2Fx-test' style%3D'width%3A200px%3Bheight%3A100px%3B' wmode%3D'window'><%2Fembed><%2Fbody><%2Fhtml>%0D%0A"></iframe>
 
 <script type="application/javascript">
 
 /** Test for Bug 545812 **/
 
 function ok(condition, msg) {
-  opener.ok(condition, msg);
+  opener.ok(condition, "[plugins] " + msg);
 }
 
 function is(a, b, msg) {
-  opener.is(a, b, msg);
+  opener.is(a, b, "[plugins] " + msg);
 }
 
 const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
 
 document.addEventListener("mozfullscreenchange", isMacOs ? macFullScreenChange : fullScreenChange, false);
 
 var windowedPlugin = null;
 
@@ -139,16 +139,17 @@ function macFullScreenChange(event) {
   }
   fullScreenChangeCount++;
 }
 
 function fullScreenChange(event) {
   switch (fullScreenChangeCount) {
     case 0: {
       ok(document.mozFullScreen, "Request for full-screen with document containing windowless plugin should be granted");
+      is(document.mozFullScreenElement, document.body, "FSE should be body.");
       // Add windowed plugin to document, should cause full-screen mode to exit.
       document.body.appendChild(windowedPlugin);
       break;
     }
     case 1: {
       ok(!document.mozFullScreen, "Should have left full-screen mode after re-adding windowed plugin to document");
       windowedPlugin.parentNode.removeChild(windowedPlugin);
       document.body.mozRequestFullScreen();
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/file_fullscreen-rollback.html
@@ -0,0 +1,130 @@
+ <!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=700764
+
+Verifies that cancelFullScreen() rolls back to have the previous full-screen
+element full-screen.
+
+Tests:
+* Request full-screen in doc.
+* Request full-screen in doc on element not descended from full-screen element. Request should be denied.
+* Request full-screen in subdoc.
+* Cancel full-screen in subdoc, doc should be full-screen.
+* Request full-screen in subdoc.
+* Removing FSE should fully-exit full-screen.
+
+
+-->
+<head>
+  <title>Test for Bug 700764</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body onload="start();">
+
+<div id="fse">
+  <div id="fse-inner">
+    <iframe id="subdoc" mozallowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe>
+  </div>
+</div>
+
+<div id="non-fse"></div>
+
+<script type="application/javascript">
+
+/** Test for Bug 700764 **/
+
+function ok(condition, msg) {
+  opener.ok(condition, "[rollback] " + msg);
+}
+
+function is(a, b, msg) {
+  opener.is(a, b, "[rollback] " + msg);
+}
+
+function addListener(type, f) {
+  document.addEventListener("mozfullscreen" + type, f, false);
+}
+
+function removeListener(type, f) {
+  document.removeEventListener("mozfullscreen" + type, f, false);
+}
+
+function e(id) {
+  return document.getElementById(id);
+}
+
+function start() {
+  SimpleTest.waitForFocus(
+    function() {
+      addListener("change", change1);
+      e("fse").mozRequestFullScreen();
+    }
+  );
+}
+
+function change1() {
+  removeListener("change", change1);
+  addListener("error", error1);
+  is(document.mozFullScreenElement, e("fse"), "Body should be FSE");
+  
+  // Request full-screen from element not descendent from current FSE.
+  e("non-fse").mozRequestFullScreen();
+}
+
+function error1() {
+  removeListener("error", error1);
+  addListener("change", change2);
+  is(document.mozFullScreenElement, e("fse"), "FSE should not change");
+  var iframe = e("subdoc");
+  iframe.contentDocument.body.mozRequestFullScreen();
+}
+
+function change2() {
+  removeListener("change", change2);
+  var iframe = e("subdoc");
+  is(document.mozFullScreenElement, iframe, "Subdoc container should be FSE.");
+  is(iframe.contentDocument.mozFullScreenElement, iframe.contentDocument.body, "Subdoc body should be FSE in subdoc");
+  addListener("change", change3);
+  iframe.contentDocument.mozCancelFullScreen();  
+}
+
+function change3() {
+  removeListener("change", change3);
+  is(document.mozFullScreenElement, e("fse"), "FSE should rollback to FSE.");
+  addListener("change", change4);
+  document.mozCancelFullScreen();
+}
+
+function change4() {
+  removeListener("change", change4);
+  is(document.mozFullScreenElement, null, "Should have left full-screen entirely");
+  addListener("change", change5);
+  e("fse").mozRequestFullScreen();
+}
+
+function change5() {
+  removeListener("change", change5);
+  addListener("change", change6);
+  is(document.mozFullScreenElement, e("fse"), "FSE should be e('fse')");
+  e("fse-inner").mozRequestFullScreen();
+}
+
+function change6() {
+  removeListener("change", change6);
+  addListener("change", change7);
+  var element = e('fse-inner');
+  is(document.mozFullScreenElement, element, "FSE should be e('fse-inner')");
+  element.parentNode.removeChild(element);
+}
+
+function change7() {
+  removeListener("change", change7);
+  is(document.mozFullScreenElement, null, "Should have fully exited full-screen mode when removed FSE from doc");
+  opener.nextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/content/test/test_fullscreen-api.html
+++ b/content/html/content/test/test_fullscreen-api.html
@@ -31,16 +31,17 @@ SpecialPowers.setBoolPref("full-screen-a
 // to write.
 var prevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
 SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
 
 // Run the tests which go full-screen in new windows, as mochitests normally
 // run in an iframe, which by default will not have the mozallowfullscreen
 // attribute set, so full-screen won't work.
 var gTestWindows = [
+  "file_fullscreen-rollback.html",
   "file_fullscreen-esc-exit.html",
   "file_fullscreen-denied.html",
   "file_fullscreen-api.html",
   "file_fullscreen-api-keys.html",
   "file_fullscreen-plugins.html",
   "file_fullscreen-hidden.html",
   "file_fullscreen-navigation.html"
 ];
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4419,22 +4419,22 @@ nsGlobalWindow::SetFullScreen(bool aFull
   // Set this before so if widget sends an event indicating its
   // gone full screen, the state trap above works.
   mFullScreen = aFullScreen;
 
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   if (widget)
     widget->MakeFullScreen(aFullScreen);
 
-  if (!mFullScreen && mDocument) {
-    // Notify the document that we've left full-screen mode. This is so that
-    // if we're in full-screen mode and the user exits full-screen mode with
-    // the browser full-screen mode toggle keyboard-shortcut, we detect that
-    // and leave DOM API full-screen mode too.
-    mDocument->MozCancelFullScreen();
+  if (!mFullScreen) {
+    // Force exit from DOM full-screen mode. This is so that if we're in
+    // DOM full-screen mode and the user exits full-screen mode with
+    // the browser full-screen mode toggle keyboard-shortcut, we'll detect
+    // that and leave DOM API full-screen mode too.
+    nsIDocument::ExitFullScreen(false);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetFullScreen(bool* aFullScreen)
 {
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1104,18 +1104,18 @@ IDBObjectStore::AddOrPut(const jsval& aV
   PRUint64 offset;
 
   nsresult rv =
     GetAddInfo(aCx, aValue, keyval, cloneBuffer, key, updateInfo, &offset);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  // Put requires a key.
-  if (aOverwrite && key.IsUnset()) {
+  // Put requires a key, unless this is an autoIncrementing objectStore.
+  if (aOverwrite && !mAutoIncrement && key.IsUnset()) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<AddHelper> helper =
     new AddHelper(mTransaction, request, this, cloneBuffer, key, aOverwrite,
@@ -1788,17 +1788,17 @@ AddHelper::DoDatabaseWork(mozIStorageCon
     }
 
     if (NS_FAILED(rv)) {
       return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
     }
   }
 
   // If we are supposed to generate a key, get the new id.
-  if (autoIncrement && !mOverwrite) {
+  if (autoIncrement && !mayOverwrite) {
 #ifdef DEBUG
     PRInt64 oldKey = unsetKey ? 0 : mKey.ToInteger();
 #endif
 
     PRInt64 newIntKey;
     rv = aConnection->GetLastInsertRowID(&newIntKey);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
--- a/dom/indexedDB/test/test_key_requirements.html
+++ b/dom/indexedDB/test/test_key_requirements.html
@@ -56,28 +56,28 @@
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result, key2, "put gave the same key back");
 
       try {
         objectStore.put({});
-        ok(false, "put with no key should throw!");
+        ok(true, "put with no key should not throw with autoIncrement!");
       }
       catch (e) {
-        ok(true, "put with no key threw");
+        ok(false, "put with no key threw with autoIncrement");
       }
 
       try {
         objectStore.put({});
-        ok(false, "put with no key should throw!");
+        ok(true, "put with no key should not throw with autoIncrement!");
       }
       catch (e) {
-        ok(true, "put with no key threw");
+        ok(false, "put with no key threw with autoIncrement");
       }
 
       try {
         objectStore.delete();
         ok(false, "remove with no key should throw!");
       }
       catch (e) {
         ok(true, "remove with no key threw");
@@ -242,28 +242,28 @@
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result, key2, "put gave the same key back");
 
       try {
         objectStore.put({});
-        ok(false, "put with no key should throw!");
+        ok(true, "put with no key should not throw with autoIncrement!");
       }
       catch (e) {
-        ok(true, "put with no key threw");
+        ok(false, "put with no key threw with autoIncrement");
       }
 
       try {
         objectStore.put({});
-        ok(false, "put with no key should throw!");
+        ok(true, "put with no key should not throw with autoIncrement!");
       }
       catch (e) {
-        ok(true, "put with no key threw");
+        ok(false, "put with no key threw with autoIncrement");
       }
 
       try {
         objectStore.delete();
         ok(false, "remove with no key should throw!");
       }
       catch (e) {
         ok(true, "remove with no key threw");
--- a/dom/indexedDB/test/test_put_get_values_autoIncrement.html
+++ b/dom/indexedDB/test/test_put_get_values_autoIncrement.html
@@ -24,28 +24,28 @@
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore(objectStoreName,
                                              { autoIncrement: 1 });
 
-      request = objectStore.add(testString.value);
+      request = objectStore.put(testString.value);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
         testString.key = event.target.result;
         request = objectStore.get(testString.key);
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           is(event.target.result, testString.value, "Got the right value");
         };
       };
 
-      request = objectStore.add(testInt.value);
+      request = objectStore.put(testInt.value);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
         testInt.key = event.target.result;
         request = objectStore.get(testInt.key);
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           is(event.target.result, testInt.value, "Got the right value");
           finishTest();
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -118,13 +118,15 @@ GlobalStorageWarning=Use of globalStorag
 FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
 FullScreenDeniedPlugins=Request for full-screen was denied because a document on this page contains a windowed plugin.
 FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
 FullScreenDeniedIframeDisallowed=Request for full-screen was denied because at least one of the document's containing iframes does not have a "mozallowfullscreen" attribute.
 FullScreenDeniedNotInputDriven=Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler.
 FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
 FullScreenDeniedMovedDocument=Request for full-screen was denied because requesting element has moved document.
 FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
+FullScreenDeniedSubDocFullScreen=Request for full-screen was denied because a subdocument of the document requesting full-screen is already full-screen.
+FullScreenDeniedNotDescendant=Request for full-screen was denied because requesting element is not a descendant of the current full-screen element.
 RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
 AddedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was added to document.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
 InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3308,18 +3308,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
 
   if (mObjectFrame) {
     if (!mWidget) {
       bool windowless = false;
       mInstance->IsWindowless(&windowless);
       nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
 #ifndef XP_MACOSX
       if (!windowless && doc && doc->IsFullScreenDoc()) {
-        NS_DispatchToCurrentThread(
-          NS_NewRunnableMethod(doc, &nsIDocument::CancelFullScreen));
+        nsIDocument::ExitFullScreen(true);
       }
 #endif
       // always create widgets in Twips, not pixels
       nsPresContext* context = mObjectFrame->PresContext();
       rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
                                       context->DevPixelsToAppUnits(mPluginWindow->height),
                                       windowless);
       if (NS_OK == rv) {
--- a/dom/system/Makefile.in
+++ b/dom/system/Makefile.in
@@ -56,16 +56,20 @@ endif
 ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
 DIRS = cocoa
 endif
 
 ifneq (,$(filter android,$(MOZ_WIDGET_TOOLKIT)))
 DIRS = android
 endif
 
+ifdef MOZ_B2G_RIL #{
+DIRS += b2g
+endif #}
+
 CPPSRCS     = \
   nsDeviceMotion.cpp \
   $(NULL)
 
 # We fire the nsDOMDeviceAcceleration
 LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
 
 # On Systems that have build in geolocation providers,
rename from dom/telephony/worker-component/Makefile.in
rename to dom/system/b2g/Makefile.in
--- a/dom/telephony/worker-component/Makefile.in
+++ b/dom/system/b2g/Makefile.in
@@ -1,62 +1,65 @@
-#
 # ***** BEGIN LICENSE BLOCK *****
 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
 #
 # The contents of this file are subject to the Mozilla Public License Version
 # 1.1 (the "License"); you may not use this file except in compliance with
 # the License. You may obtain a copy of the License at
 # http://www.mozilla.org/MPL/
 #
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
-# The Original Code is mozilla.org Code.
+# The Original Code is Telephony.
 #
 # The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
+#   The Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
+#   Ben Turner <bent.mozilla@gmail.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@
+DEPTH            = ../../..
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-EXTRA_COMPONENTS = \
-  nsTelephonyWorker.manifest \
-  nsTelephonyWorker.js \
+MODULE           = dom
+LIBRARY_NAME     = domsystemb2g_s
+XPIDL_MODULE     = dom_system_b2g
+LIBXUL_LIBRARY   = 1
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/dom/dom-config.mk
+
+CPPSRCS = \
+  RadioManager.cpp \
   $(NULL)
 
-EXTRA_JS_MODULES = \
-  ril_consts.js \
-  ril_worker.js \
-  $(NULL)
+XPIDLSRCS = nsIRadioWorker.idl
 
-XPIDL_MODULE = dom_telephony_worker
-XPIDLSRCS = \
-  nsITelephonyWorker.idl \
-  nsIRadioInterface.idl \
+LOCAL_INCLUDES = \
+  -I$(topsrcdir)/dom/base \
+  -I$(topsrcdir)/dom/telephony \
+  -I$(topsrcdir)/content/events/src \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
-
rename from dom/telephony/Radio.cpp
rename to dom/system/b2g/RadioManager.cpp
--- a/dom/telephony/Radio.cpp
+++ b/dom/system/b2g/RadioManager.cpp
@@ -32,24 +32,25 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "Radio.h"
-#include "nsITelephonyWorker.h"
+#include "RadioManager.h"
+#include "nsIRadioWorker.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsIJSContextStack.h"
 #include "nsIObserverService.h"
 #include "mozilla/dom/workers/Workers.h"
 #include "jstypedarray.h"
+#include "nsTelephonyWorker.h"
 
 #include "nsThreadUtils.h"
 
 #if defined(MOZ_WIDGET_GONK)
 #include <android/log.h>
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
 #else
 #define LOG(args...)  printf(args);
@@ -63,17 +64,17 @@ static NS_DEFINE_CID(kTelephonyWorkerCID
 // Topic we listen to for shutdown.
 #define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
 
 USING_TELEPHONY_NAMESPACE
 
 namespace {
 
 // Doesn't carry a reference, we're owned by services.
-Radio* gInstance = nsnull;
+RadioManager* gInstance = nsnull;
 
 class ConnectWorkerToRIL : public WorkerTask {
 public:
   virtual bool RunTask(JSContext *aCx);
 };
 
 JSBool
 PostToRIL(JSContext *cx, uintN argc, jsval *vp)
@@ -189,52 +190,50 @@ RILReceiver::DispatchRILEvent::RunTask(J
   memcpy(JS_GetTypedArrayData(array), mMessage->mData, mMessage->mSize);
   jsval argv[] = { OBJECT_TO_JSVAL(array) };
   return JS_CallFunctionName(aCx, obj, "onRILMessage", NS_ARRAY_LENGTH(argv),
                              argv, argv);
 }
 
 } // anonymous namespace
 
-Radio::Radio()
+RadioManager::RadioManager()
   : mShutdown(false)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!gInstance, "There should only be one instance!");
 }
 
-Radio::~Radio()
+RadioManager::~RadioManager()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!gInstance || gInstance == this,
                "There should only be one instance!");
   gInstance = nsnull;
 }
 
 nsresult
-Radio::Init()
+RadioManager::Init()
 {
   NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
 
   nsCOMPtr<nsIObserverService> obs =
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   if (!obs) {
     NS_WARNING("Failed to get observer service!");
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = obs->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The telephony worker component is a hack that gives us a global object for
   // our own functions and makes creating the worker possible.
-  nsCOMPtr<nsITelephonyWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
-  if (!worker) {
-    return NS_ERROR_FAILURE;
-  }
+  nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
+  NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
 
   jsval workerval;
   rv = worker->GetWorker(&workerval);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
 
   JSContext *cx;
   rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
@@ -261,73 +260,73 @@ Radio::Init()
   if (!wctd->PostTask(connection)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // Now that we're set up, connect ourselves to the RIL thread.
   mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
   StartRil(receiver);
 
-  mRadioInterface = do_QueryInterface(worker);
-  NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
+  mTelephone = do_QueryInterface(worker);
+  NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 void
-Radio::Shutdown()
+RadioManager::Shutdown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   StopRil();
-  mRadioInterface = nsnull;
+  mTelephone = nsnull;
 
   mShutdown = true;
 }
 
 // static
-already_AddRefed<Radio>
-Radio::FactoryCreate()
+already_AddRefed<RadioManager>
+RadioManager::FactoryCreate()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  nsRefPtr<Radio> instance(gInstance);
+  nsRefPtr<RadioManager> instance(gInstance);
 
   if (!instance) {
-    instance = new Radio();
+    instance = new RadioManager();
     if (NS_FAILED(instance->Init())) {
       return nsnull;
     }
 
     gInstance = instance;
   }
 
   return instance.forget();
 }
 
 // static
-already_AddRefed<nsIRadioInterface>
-Radio::GetRadioInterface()
+already_AddRefed<nsITelephone>
+RadioManager::GetTelephone()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (gInstance) {
-    nsCOMPtr<nsIRadioInterface> retval = gInstance->mRadioInterface;
+    nsCOMPtr<nsITelephone> retval = gInstance->mTelephone;
     return retval.forget();
   }
 
   return nsnull;
 }
 
 
-NS_IMPL_ISUPPORTS1(Radio, nsIObserver)
+NS_IMPL_ISUPPORTS1(RadioManager, nsIObserver)
 
 NS_IMETHODIMP
-Radio::Observe(nsISupports* aSubject, const char* aTopic,
-               const PRUnichar* aData)
+RadioManager::Observe(nsISupports* aSubject, const char* aTopic,
+                      const PRUnichar* aData)
 {
   if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC)) {
     Shutdown();
 
     nsCOMPtr<nsIObserverService> obs =
       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     if (obs) {
       if (NS_FAILED(obs->RemoveObserver(this, aTopic))) {
rename from dom/telephony/Radio.h
rename to dom/system/b2g/RadioManager.h
--- a/dom/telephony/Radio.h
+++ b/dom/system/b2g/RadioManager.h
@@ -43,17 +43,17 @@
 #include "jsapi.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsServiceManagerUtils.h"
 
 #include "nsIObserver.h"
 #include "mozilla/ipc/Ril.h"
-#include "nsIRadioInterface.h"
+#include "nsITelephone.h"
 
 #define TELEPHONYRADIO_CONTRACTID "@mozilla.org/telephony/radio;1"
 #define TELEPHONYRADIOINTERFACE_CONTRACTID "@mozilla.org/telephony/radio-interface;1"
 
 #define BEGIN_TELEPHONY_NAMESPACE \
   namespace mozilla { namespace dom { namespace telephony {
 #define END_TELEPHONY_NAMESPACE \
   } /* namespace telephony */ } /* namespace dom */ } /* namespace mozilla */
@@ -68,34 +68,34 @@
 #define TELEPHONYRADIOINTERFACE_CID \
   {0xd66e7ece, 0x41b1, 0x4608, {0x82, 0x80, 0x72, 0x50, 0xa6, 0x44, 0xe6, 0x6f}}
 
 
 class nsIXPConnectJSObjectHolder;
 
 BEGIN_TELEPHONY_NAMESPACE
 
-class Radio : public nsIObserver
+class RadioManager : public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsresult Init();
   void Shutdown();
 
-  static already_AddRefed<Radio>
+  static already_AddRefed<RadioManager>
   FactoryCreate();
 
-  static already_AddRefed<nsIRadioInterface>
-  GetRadioInterface();
+  static already_AddRefed<nsITelephone>
+  GetTelephone();
 
 protected:
-  Radio();
-  ~Radio();
+  RadioManager();
+  ~RadioManager();
 
-  nsCOMPtr<nsIRadioInterface> mRadioInterface;
+  nsCOMPtr<nsITelephone> mTelephone;
   bool mShutdown;
 };
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_radio_h__
new file mode 100644
--- /dev/null
+++ b/dom/system/b2g/nsIRadioWorker.idl
@@ -0,0 +1,43 @@
+/* ***** 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 Telephony.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.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 ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(8f031451-ac25-4816-a09e-a075bb704e63)]
+interface nsIRadioWorker : nsISupports {
+    readonly attribute jsval worker;
+};
--- a/dom/telephony/Makefile.in
+++ b/dom/telephony/Makefile.in
@@ -37,36 +37,35 @@
 
 DEPTH            = ../..
 topsrcdir        = @top_srcdir@
 srcdir           = @srcdir@
 VPATH            = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+MODULE           = dom
 LIBRARY_NAME     = domtelephony_s
 XPIDL_MODULE     = dom_telephony
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/dom/dom-config.mk
 
-CPPSRCS = \
-  Radio.cpp \
-  $(NULL)
-
-LOCAL_INCLUDES = \
-  -I$(topsrcdir)/dom/base \
-  -I$(topsrcdir)/content/events/src \
-  $(NULL)
-
 XPIDLSRCS = \
   mozIDOMTelephony.idl \
+  nsITelephone.idl \
   $(NULL)
 
 EXTRA_COMPONENTS = \
   Telephony.manifest \
   Telephony.js \
+  nsTelephonyWorker.manifest \
+  nsTelephonyWorker.js \
   $(NULL)
 
-DIRS += worker-component
+EXTRA_JS_MODULES = \
+  ril_consts.js \
+  ril_worker.js \
+  $(NULL)
 
 include $(topsrcdir)/config/rules.mk
+
--- a/dom/telephony/Telephony.js
+++ b/dom/telephony/Telephony.js
@@ -147,28 +147,28 @@ const DOM_CARDSTATE_UNAVAILABLE    = "un
 const DOM_CARDSTATE_ABSENT         = "absent";
 const DOM_CARDSTATE_PIN_REQUIRED   = "pin_required";
 const DOM_CARDSTATE_PUK_REQUIRED   = "puk_required";
 const DOM_CARDSTATE_NETWORK_LOCKED = "network_locked";
 const DOM_CARDSTATE_NOT_READY      = "not_ready";
 const DOM_CARDSTATE_READY          = "ready";
 
 /**
- * Callback object that Telephony registers with nsIRadioInterface.
+ * Callback object that Telephony registers with nsITelephone.
  * Telephony can't use itself because that might overload event handler
  * attributes ('onfoobar').
  */
 function TelephonyRadioCallback(telephony) {
   this.telephony = telephony;
 }
 TelephonyRadioCallback.prototype = {
 
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioCallback]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephoneCallback]),
 
-  // nsIRadioCallback
+  // nsITelephoneCallback
 
   onsignalstrengthchange: function onsignalstrengthchange(signalStrength) {
     this.telephony.signalStrength = signalStrength;
     this.telephony._dispatchEventByType("signalstrengthchange");
   },
 
   onoperatorchange: function onoperatorchange(operator) {
     this.telephony.operator = operator;
@@ -210,17 +210,17 @@ Telephony.prototype = {
                                          Ci.nsIDOMEventTarget,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   // nsIDOMGlobalPropertyInitializer
 
   init: function init(window) {
     this.window = window;
     this.radioInterface = Cc["@mozilla.org/telephony/radio-interface;1"]
-                            .createInstance(Ci.nsIRadioInterface);
+                            .createInstance(Ci.nsITelephone);
     this.radioCallback = new TelephonyRadioCallback(this);
     window.addEventListener("unload", function onunload(event) {
       this.radioInterface.unregisterCallback(this.radioCallback);
       this.radioCallback = null;
       this.window = null;
     }.bind(this));
     this.radioInterface.registerCallback(this.radioCallback);
     this.liveCalls = [];
rename from dom/telephony/worker-component/nsIRadioInterface.idl
rename to dom/telephony/nsITelephone.idl
--- a/dom/telephony/worker-component/nsIRadioInterface.idl
+++ b/dom/telephony/nsITelephone.idl
@@ -33,29 +33,29 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 [scriptable, uuid(e21cdf40-c511-442b-8c7d-aa75471b0423)]
-interface nsIRadioCallback : nsISupports {
+interface nsITelephoneCallback : nsISupports {
   void oncallstatechange(in jsval callState);
 
   //XXX philikon's additions
   void onoperatorchange(in jsval operatorInfo);
   void onradiostatechange(in jsval radioState);
   void oncardstatechange(in jsval cardState);
   void onsignalstrengthchange(in jsval signalStrength);
 };
 
 [scriptable, uuid(dda49485-5887-49bb-ba0b-10c5d116eb64)]
-interface nsIRadioInterface : nsISupports {
+interface nsITelephone : nsISupports {
 
   readonly attribute jsval initialState;
 
   void dial(in DOMString number);
   void hangup(in long callIndex);
 
-  void registerCallback(in nsIRadioCallback callback);
-  void unregisterCallback(in nsIRadioCallback callback);
+  void registerCallback(in nsITelephoneCallback callback);
+  void unregisterCallback(in nsITelephoneCallback callback);
 };
new file mode 100644
--- /dev/null
+++ b/dom/telephony/nsTelephonyWorker.h
@@ -0,0 +1,40 @@
+/* ***** 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 Telephony.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.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 ***** */
+
+#define NS_TELEPHONYWORKER_CID \
+    { 0x2d831c8d, 0x6017, 0x435b, \
+      { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
rename from dom/telephony/worker-component/nsTelephonyWorker.js
rename to dom/telephony/nsTelephonyWorker.js
--- a/dom/telephony/worker-component/nsTelephonyWorker.js
+++ b/dom/telephony/nsTelephonyWorker.js
@@ -55,21 +55,21 @@ function nsTelephonyWorker() {
   this.initialState = {};
 }
 nsTelephonyWorker.prototype = {
 
   classID:   TELEPHONYWORKER_CID,
   classInfo: XPCOMUtils.generateCI({classID: TELEPHONYWORKER_CID,
                                     contractID: TELEPHONYWORKER_CONTRACTID,
                                     classDescription: "TelephonyWorker",
-                                    interfaces: [Ci.nsITelephonyWorker,
-                                                 Ci.nsIRadioInterface]}),
+                                    interfaces: [Ci.nsIRadioWorker,
+                                                 Ci.nsITelephone]}),
 
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyWorker,
-                                         Ci.nsIRadioInterface]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioWorker,
+                                         Ci.nsITelephone]),
 
   onerror: function onerror(event) {
     // It is very important to call preventDefault on the event here.
     // If an exception is thrown on the worker, it bubbles out to the
     // component that created it. If that component doesn't have an
     // onerror handler, the worker will try to call the error reporter
     // on the context it was created on. However, That doesn't work
     // for component contexts and can result in crashes. This onerror
@@ -113,21 +113,21 @@ nsTelephonyWorker.prototype = {
       let method = callback[methodname];
       if (typeof method != "function") {
         return;
       }
       method.call(callback, value);
     });
   },
 
-  // nsITelephonWorker
+  // nsIRadioWorker
 
   worker: null,
 
-  // nsIRadioInterface
+  // nsITelephone
 
   initialState: null,
 
   dial: function dial(number) {
     debug("Dialing " + number);
     this.worker.postMessage({type: "dial", number: number});
   },
 
rename from dom/telephony/worker-component/nsTelephonyWorker.manifest
rename to dom/telephony/nsTelephonyWorker.manifest
rename from dom/telephony/worker-component/ril_consts.js
rename to dom/telephony/ril_consts.js
rename from dom/telephony/worker-component/ril_worker.js
rename to dom/telephony/ril_worker.js
deleted file mode 100644
--- a/dom/telephony/worker-component/nsITelephonyWorker.idl
+++ /dev/null
@@ -1,51 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Telephony.
- *
- * The Initial Developer of the Original Code is
- *   The Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ben Turner <bent.mozilla@gmail.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 ***** */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(8f031451-ac25-4816-a09e-a075bb704e63)]
-interface nsITelephonyWorker : nsISupports {
-    readonly attribute jsval worker;
-};
-
-%{ C++
-
-#define NS_TELEPHONYWORKER_CID \
-    { 0x2d831c8d, 0x6017, 0x435b, \
-      { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
-
-%}
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -279,16 +279,17 @@ GLContextCGL::ResizeOffscreen(const gfxI
                                    textureMaxMipMapLevel:0
                                    pixelsWide:aNewSize.width
                                    pixelsHigh:aNewSize.height];
         if (!pb) {
             return false;
         }
 
         if (!ResizeOffscreenFBO(aNewSize, false)) {
+            [pb release];
             return false;
         }
 
         [mPBuffer release];
         mPBuffer = pb;
 
         mOffscreenSize = aNewSize;
         mOffscreenActualSize = aNewSize;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5764,96 +5764,59 @@ static inline bool
 EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
     JS_ASSERT(pn->pn_left->isKind(PNK_FORIN) || pn->pn_left->isKind(PNK_FORHEAD));
     return pn->pn_left->isKind(PNK_FORIN)
            ? EmitForIn(cx, bce, pn, top)
            : EmitNormalFor(cx, bce, pn, top);
 }
 
-JSBool
-frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
-{
-    JSBool useful, wantval;
-    StmtInfo stmtInfo;
-    StmtInfo *stmt;
-    ptrdiff_t top, off, tmp, beq, jmp;
-    ParseNode *pn2, *pn3;
-    JSAtom *atom;
-    jsatomid atomIndex;
-    uintN index;
-    ptrdiff_t noteIndex, noteIndex2;
-    SrcNoteType noteType;
-    jsbytecode *pc;
-    JSOp op;
-    uint32 argc;
-    EmitLevelManager elm(bce);
-    jsint sharpnum = -1;
-
-    JS_CHECK_RECURSION(cx, return JS_FALSE);
-
-    JSBool ok = true;
-    pn->pn_offset = top = bce->offset();
-
-    /* Emit notes to tell the current bytecode's source line number. */
-    UPDATE_LINE_NUMBER_NOTES(cx, bce, pn->pn_pos.begin.lineno);
-
-    switch (pn->getKind()) {
-      case PNK_FUNCTION:
-      {
-        JSFunction *fun;
-        uintN slot;
-
+static bool
+EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
 #if JS_HAS_XML_SUPPORT
-        if (pn->isArity(PN_NULLARY)) {
-            if (Emit1(cx, bce, JSOP_GETFUNNS) < 0)
-                return JS_FALSE;
-            break;
-        }
+    if (pn->isArity(PN_NULLARY))
+        return Emit1(cx, bce, JSOP_GETFUNNS) >= 0;
 #endif
 
-        fun = pn->pn_funbox->function();
-        JS_ASSERT(fun->isInterpreted());
-        if (fun->script()) {
-            /*
-             * This second pass is needed to emit JSOP_NOP with a source note
-             * for the already-emitted function definition prolog opcode. See
-             * comments in the PNK_STATEMENTLIST case.
-             */
-            JS_ASSERT(pn->isOp(JSOP_NOP));
-            JS_ASSERT(bce->inFunction());
-            if (!EmitFunctionDefNop(cx, bce, pn->pn_index))
-                return JS_FALSE;
-            break;
-        }
-
-        JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
-                     fun->kind() == JSFUN_INTERPRETED);
-
+    JSFunction *fun = pn->pn_funbox->function();
+    JS_ASSERT(fun->isInterpreted());
+    if (fun->script()) {
+        /*
+         * This second pass is needed to emit JSOP_NOP with a source note
+         * for the already-emitted function definition prolog opcode. See
+         * comments in the PNK_STATEMENTLIST case.
+         */
+        JS_ASSERT(pn->isOp(JSOP_NOP));
+        JS_ASSERT(bce->inFunction());
+        return EmitFunctionDefNop(cx, bce, pn->pn_index);
+    }
+
+    JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
+                 fun->kind() == JSFUN_INTERPRETED);
+
+    {
         /*
          * Generate code for the function's body.  bce2 is not allocated on the
          * stack because doing so significantly reduces the maximum depth of
          * nested functions we can handle.  See bug 696284.
          */
-        BytecodeEmitter *bce2 = cx->new_<BytecodeEmitter>(bce->parser, pn->pn_pos.begin.lineno);
-        if (!bce2) {
-            js_ReportOutOfMemory(cx);
-            return JS_FALSE;
-        }
-        if (!bce2->init(cx))
-            return JS_FALSE;
+        AutoPtr<BytecodeEmitter> bce2(cx);
+        bce2 = cx->new_<BytecodeEmitter>(bce->parser, pn->pn_pos.begin.lineno);
+        if (!bce2 || !bce2->init(cx))
+            return false;
 
         bce2->flags = pn->pn_funbox->tcflags | TCF_COMPILING | TCF_IN_FUNCTION |
                      (bce->flags & TCF_FUN_MIGHT_ALIAS_LOCALS);
         bce2->bindings.transfer(cx, &pn->pn_funbox->bindings);
 #if JS_HAS_SHARP_VARS
         if (bce2->flags & TCF_HAS_SHARPS) {
             bce2->sharpSlotBase = bce2->bindings.sharpSlotBase(cx);
             if (bce2->sharpSlotBase < 0)
-                return JS_FALSE;
+                return false;
         }
 #endif
         bce2->setFunction(fun);
         bce2->funbox = pn->pn_funbox;
         bce2->parent = bce;
         bce2->globalScope = bce->globalScope;
 
         /*
@@ -5861,90 +5824,1129 @@ frontend::EmitTree(JSContext *cx, Byteco
          * 16 bits and to reserve the all-ones value, thereby reserving the
          * magic FREE_UPVAR_COOKIE value. Note the bce2->staticLevel assignment
          * below.
          */
         JS_ASSERT(bce->staticLevel < JS_BITMASK(16) - 1);
         bce2->staticLevel = bce->staticLevel + 1;
 
         /* We measured the max scope depth when we parsed the function. */
-        if (!EmitFunctionScript(cx, bce2, pn->pn_body))
-            pn = NULL;
-
-        cx->delete_(bce2);
-        bce2 = NULL;
-        if (!pn)
-            return JS_FALSE;
-
-        /* Make the function object a literal in the outer script's pool. */
-        index = bce->objectList.index(pn->pn_funbox);
-
-        /* Emit a bytecode pointing to the closure object in its immediate. */
-        op = pn->getOp();
-        if (op != JSOP_NOP) {
-            if ((pn->pn_funbox->tcflags & TCF_GENEXP_LAMBDA) &&
-                NewSrcNote(cx, bce, SRC_GENEXP) < 0)
-            {
-                return JS_FALSE;
-            }
+        if (!EmitFunctionScript(cx, bce2.get(), pn->pn_body))
+            return false;
+    }
+
+    /* Make the function object a literal in the outer script's pool. */
+    uintN index = bce->objectList.index(pn->pn_funbox);
+
+    /* Emit a bytecode pointing to the closure object in its immediate. */
+    if (pn->getOp() != JSOP_NOP) {
+        if ((pn->pn_funbox->tcflags & TCF_GENEXP_LAMBDA) &&
+            NewSrcNote(cx, bce, SRC_GENEXP) < 0)
+        {
+            return false;
+        }
+        EMIT_INDEX_OP(pn->getOp(), index);
+
+        /* Make blockChain determination quicker. */
+        return EmitBlockChain(cx, bce) >= 0;
+    }
+
+    /*
+     * For a script we emit the code as we parse. Thus the bytecode for
+     * top-level functions should go in the prolog to predefine their
+     * names in the variable object before the already-generated main code
+     * is executed. This extra work for top-level scripts is not necessary
+     * when we emit the code for a function. It is fully parsed prior to
+     * invocation of the emitter and calls to EmitTree for function
+     * definitions can be scheduled before generating the rest of code.
+     */
+    if (!bce->inFunction()) {
+        JS_ASSERT(!bce->topStmt);
+        if (!BindGlobal(cx, bce, pn, fun->atom))
+            return false;
+        if (pn->pn_cookie.isFree()) {
+            bce->switchToProlog();
+            JSOp op = fun->isFlatClosure() ? JSOP_DEFFUN_FC : JSOP_DEFFUN;
             EMIT_INDEX_OP(op, index);
 
             /* Make blockChain determination quicker. */
             if (EmitBlockChain(cx, bce) < 0)
-                return JS_FALSE;
-            break;
+                return false;
+            bce->switchToMain();
+        }
+
+        /* Emit NOP for the decompiler. */
+        if (!EmitFunctionDefNop(cx, bce, index))
+            return false;
+    } else {
+        uintN slot;
+        DebugOnly<BindingKind> kind = bce->bindings.lookup(cx, fun->atom, &slot);
+        JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
+        JS_ASSERT(index < JS_BIT(20));
+        pn->pn_index = index;
+        JSOp op = fun->isFlatClosure() ? JSOP_DEFLOCALFUN_FC : JSOP_DEFLOCALFUN;
+        if (pn->isClosed() &&
+            !bce->callsEval() &&
+            !bce->closedVars.append(pn->pn_cookie.slot()))
+        {
+            return false;
         }
+        if (!EmitSlotIndexOp(cx, op, slot, index, bce))
+            return false;
+
+        /* Make blockChain determination quicker. */
+        return EmitBlockChain(cx, bce) >= 0;
+    }
+
+    return true;
+}
+
+static bool
+EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /* Emit an annotated nop so we know to decompile a 'do' keyword. */
+    ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
+    if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
+        return false;
+
+    ptrdiff_t noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
+    if (noteIndex2 < 0)
+        return false;
+
+    /* Compile the loop body. */
+    ptrdiff_t top = EmitTraceOp(cx, bce, pn->pn_left);
+    if (top < 0)
+        return false;
+
+    StmtInfo stmtInfo;
+    PushStatement(bce, &stmtInfo, STMT_DO_LOOP, top);
+    if (!EmitTree(cx, bce, pn->pn_left))
+        return false;
+
+    /* Set loop and enclosing label update offsets, for continue. */
+    ptrdiff_t off = bce->offset();
+    StmtInfo *stmt = &stmtInfo;
+    do {
+        stmt->update = off;
+    } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+    /* Compile the loop condition, now that continues know where to go. */
+    if (!EmitTree(cx, bce, pn->pn_right))
+        return false;
+
+    /*
+     * Since we use JSOP_IFNE for other purposes as well as for do-while
+     * loops, we must store 1 + (beq - top) in the SRC_WHILE note offset,
+     * and the decompiler must get that delta and decompile recursively.
+     */
+    ptrdiff_t beq = EmitJump(cx, bce, JSOP_IFNE, top - bce->offset());
+    if (beq < 0)
+        return false;
+
+    /*
+     * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
+     * note gets bigger.
+     */
+    if (!SetSrcNoteOffset(cx, bce, noteIndex2, 0, beq - top))
+        return false;
+    if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, 1 + (off - top)))
+        return false;
+
+    return PopStatementBCE(cx, bce);
+}
+
+static bool
+EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
+{
+    /*
+     * Minimize bytecodes issued for one or more iterations by jumping to
+     * the condition below the body and closing the loop if the condition
+     * is true with a backward branch. For iteration count i:
+     *
+     *  i    test at the top                 test at the bottom
+     *  =    ===============                 ==================
+     *  0    ifeq-pass                       goto; ifne-fail
+     *  1    ifeq-fail; goto; ifne-pass      goto; ifne-pass; ifne-fail
+     *  2    2*(ifeq-fail; goto); ifeq-pass  goto; 2*ifne-pass; ifne-fail
+     *  . . .
+     *  N    N*(ifeq-fail; goto); ifeq-pass  goto; N*ifne-pass; ifne-fail
+     */
+    StmtInfo stmtInfo;
+    PushStatement(bce, &stmtInfo, STMT_WHILE_LOOP, top);
+
+    ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
+    if (noteIndex < 0)
+        return false;
+
+    ptrdiff_t jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
+    if (jmp < 0)
+        return false;
+
+    ptrdiff_t noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
+    if (noteIndex2 < 0)
+        return false;
+
+    top = EmitTraceOp(cx, bce, pn->pn_right);
+    if (top < 0)
+        return false;
+
+    if (!EmitTree(cx, bce, pn->pn_right))
+        return false;
+
+    CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, jmp);
+    if (!EmitTree(cx, bce, pn->pn_left))
+        return false;
+
+    ptrdiff_t beq = EmitJump(cx, bce, JSOP_IFNE, top - bce->offset());
+    if (beq < 0)
+        return false;
+
+    /*
+     * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
+     * note gets bigger.
+     */
+    if (!SetSrcNoteOffset(cx, bce, noteIndex2, 0, beq - top))
+        return false;
+    if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, beq - jmp))
+        return false;
+
+    return PopStatementBCE(cx, bce);
+}
+
+static bool
+EmitBreak(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    StmtInfo *stmt = bce->topStmt;
+    JSAtom *atom = pn->pn_atom;
+
+    SrcNoteType noteType;
+    jsatomid labelIndex;
+    if (atom) {
+        if (!bce->makeAtomIndex(atom, &labelIndex))
+            return false;
+
+        while (stmt->type != STMT_LABEL || stmt->label != atom)
+            stmt = stmt->down;
+        noteType = SRC_BREAK2LABEL;
+    } else {
+        labelIndex = INVALID_ATOMID;
+        while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)
+            stmt = stmt->down;
+        noteType = (stmt->type == STMT_SWITCH) ? SRC_SWITCHBREAK : SRC_BREAK;
+    }
+
+    return EmitGoto(cx, bce, stmt, &stmt->breaks, labelIndex, noteType) >= 0;
+}
+
+static bool
+EmitContinue(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    StmtInfo *stmt = bce->topStmt;
+    JSAtom *atom = pn->pn_atom;
+
+    SrcNoteType noteType;
+    jsatomid labelIndex;
+    if (atom) {
+        if (!bce->makeAtomIndex(atom, &labelIndex))
+            return false;
+
+        /* Find the loop statement enclosed by the matching label. */
+        StmtInfo *loop = NULL;
+        while (stmt->type != STMT_LABEL || stmt->label != atom) {
+            if (STMT_IS_LOOP(stmt))
+                loop = stmt;
+            stmt = stmt->down;
+        }
+        stmt = loop;
+        noteType = SRC_CONT2LABEL;
+    } else {
+        labelIndex = INVALID_ATOMID;
+        while (!STMT_IS_LOOP(stmt))
+            stmt = stmt->down;
+        noteType = SRC_CONTINUE;
+    }
+
+    return EmitGoto(cx, bce, stmt, &stmt->continues, labelIndex, noteType) >= 0;
+}
+
+static bool
+EmitReturn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /* Push a return value */
+    if (ParseNode *pn2 = pn->pn_kid) {
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+    } else {
+        if (Emit1(cx, bce, JSOP_PUSH) < 0)
+            return false;
+    }
+
+    /*
+     * EmitNonLocalJumpFixup may add fixup bytecode to close open try
+     * blocks having finally clauses and to exit intermingled let blocks.
+     * We can't simply transfer control flow to our caller in that case,
+     * because we must gosub to those finally clauses from inner to outer,
+     * with the correct stack pointer (i.e., after popping any with,
+     * for/in, etc., slots nested inside the finally's try).
+     *
+     * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
+     * extra JSOP_RETRVAL after the fixups.
+     */
+    ptrdiff_t top = bce->offset();
+
+    if (Emit1(cx, bce, JSOP_RETURN) < 0)
+        return false;
+    if (!EmitNonLocalJumpFixup(cx, bce, NULL))
+        return false;
+    if (top + JSOP_RETURN_LENGTH != bce->offset()) {
+        bce->base()[top] = JSOP_SETRVAL;
+        if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
+            return false;
+        if (EmitBlockChain(cx, bce) < 0)
+            return false;
+    }
+
+    return true;
+}
+
+static bool
+EmitStatementList(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
+{
+    JS_ASSERT(pn->isArity(PN_LIST));
+
+    ptrdiff_t noteIndex = -1;
+    ptrdiff_t tmp = bce->offset();
+    if (pn->pn_xflags & PNX_NEEDBRACES) {
+        noteIndex = NewSrcNote2(cx, bce, SRC_BRACE, 0);
+        if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
+            return false;
+    }
+
+    StmtInfo stmtInfo;
+    PushStatement(bce, &stmtInfo, STMT_BLOCK, top);
+
+    ParseNode *pnchild = pn->pn_head;
+    if (pn->pn_xflags & PNX_FUNCDEFS) {
+        /*
+         * This block contains top-level function definitions. To ensure
+         * that we emit the bytecode defining them before the rest of code
+         * in the block we use a separate pass over functions. During the
+         * main pass later the emitter will add JSOP_NOP with source notes
+         * for the function to preserve the original functions position
+         * when decompiling.
+         *
+         * Currently this is used only for functions, as compile-as-we go
+         * mode for scripts does not allow separate emitter passes.
+         */
+        JS_ASSERT(bce->inFunction());
+        if (pn->pn_xflags & PNX_DESTRUCT) {
+            /*
+             * Assign the destructuring arguments before defining any
+             * functions, see bug 419662.
+             */
+            JS_ASSERT(pnchild->isKind(PNK_SEMI));
+            JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_CONST));
+            if (!EmitTree(cx, bce, pnchild))
+                return false;
+            pnchild = pnchild->pn_next;
+        }
+
+        for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
+            if (pn2->isKind(PNK_FUNCTION)) {
+                if (pn2->isOp(JSOP_NOP)) {
+                    if (!EmitTree(cx, bce, pn2))
+                        return false;
+                } else {
+                    /*
+                     * JSOP_DEFFUN in a top-level block with function
+                     * definitions appears, for example, when "if (true)"
+                     * is optimized away from "if (true) function x() {}".
+                     * See bug 428424.
+                     */
+                    JS_ASSERT(pn2->isOp(JSOP_DEFFUN));
+                }
+            }
+        }
+    }
+
+    for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+    }
+
+    if (noteIndex >= 0 && !SetSrcNoteOffset(cx, bce, (uintN)noteIndex, 0, bce->offset() - tmp))
+        return false;
+
+    return PopStatementBCE(cx, bce);
+}
+
+static bool
+EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    JS_ASSERT(pn->isKind(PNK_SEMI));
+
+    ParseNode *pn2 = pn->pn_kid;
+    if (!pn2)
+        return true;
+
+    /*
+     * Top-level or called-from-a-native JS_Execute/EvaluateScript,
+     * debugger, and eval frames may need the value of the ultimate
+     * expression statement as the script's result, despite the fact
+     * that it appears useless to the compiler.
+     *
+     * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
+     * calling JS_Compile* to suppress JSOP_POPV.
+     */
+    bool wantval;
+    JSBool useful = wantval = !(bce->flags & (TCF_IN_FUNCTION | TCF_NO_SCRIPT_RVAL));
+
+    /* Don't eliminate expressions with side effects. */
+    if (!useful) {
+        if (!CheckSideEffects(cx, bce, pn2, &useful))
+            return false;
 
         /*
-         * For a script we emit the code as we parse. Thus the bytecode for
-         * top-level functions should go in the prolog to predefine their
-         * names in the variable object before the already-generated main code
-         * is executed. This extra work for top-level scripts is not necessary
-         * when we emit the code for a function. It is fully parsed prior to
-         * invocation of the emitter and calls to EmitTree for function
-         * definitions can be scheduled before generating the rest of code.
+         * Don't eliminate apparently useless expressions if they are
+         * labeled expression statements.  The tc->topStmt->update test
+         * catches the case where we are nesting in EmitTree for a labeled
+         * compound statement.
          */
-        if (!bce->inFunction()) {
-            JS_ASSERT(!bce->topStmt);
-            if (!BindGlobal(cx, bce, pn, fun->atom))
-                return false;
-            if (pn->pn_cookie.isFree()) {
-                bce->switchToProlog();
-                op = fun->isFlatClosure() ? JSOP_DEFFUN_FC : JSOP_DEFFUN;
-                EMIT_INDEX_OP(op, index);
-
-                /* Make blockChain determination quicker. */
-                if (EmitBlockChain(cx, bce) < 0)
-                    return JS_FALSE;
-                bce->switchToMain();
+        if (bce->topStmt &&
+            bce->topStmt->type == STMT_LABEL &&
+            bce->topStmt->update >= bce->offset())
+        {
+            useful = true;
+        }
+    }
+
+    if (useful) {
+        JSOp op = wantval ? JSOP_POPV : JSOP_POP;
+        JS_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
+#if JS_HAS_DESTRUCTURING
+        if (!wantval &&
+            pn2->isKind(PNK_ASSIGN) &&
+            !MaybeEmitGroupAssignment(cx, bce, op, pn2, &op))
+        {
+            return false;
+        }
+#endif
+        if (op != JSOP_NOP) {
+            /*
+             * Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or
+             * avoid null closure cloning. Do this only for assignment
+             * statements that are not completion values wanted by a
+             * script evaluator, to ensure that the joined function
+             * can't escape directly.
+             */
+            if (!wantval &&
+                pn2->isKind(PNK_ASSIGN) &&
+                pn2->pn_left->isOp(JSOP_SETPROP) &&
+                pn2->pn_right->isOp(JSOP_LAMBDA) &&
+                pn2->pn_right->pn_funbox->joinable())
+            {
+                if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
+                    return false;
+                pn2->pn_left->setOp(JSOP_SETMETHOD);
             }
-
-            /* Emit NOP for the decompiler. */
-            if (!EmitFunctionDefNop(cx, bce, index))
-                return JS_FALSE;
+            if (!EmitTree(cx, bce, pn2))
+                return false;
+            if (Emit1(cx, bce, op) < 0)
+                return false;
+        }
+    } else if (!pn->isDirectivePrologueMember()) {
+        /* Don't complain about directive prologue members; just don't emit their code. */
+        bce->current->currentLine = pn2->pn_pos.begin.lineno;
+        if (!ReportCompileErrorNumber(cx, bce->tokenStream(), pn2,
+                                      JSREPORT_WARNING | JSREPORT_STRICT, JSMSG_USELESS_EXPR))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool
+EmitDelete(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /*
+     * Under ECMA 3, deleting a non-reference returns true -- but alas we
+     * must evaluate the operand if it appears it might have side effects.
+     */
+    ParseNode *pn2 = pn->pn_kid;
+    switch (pn2->getKind()) {
+      case PNK_NAME:
+      {
+        if (!BindNameToSlot(cx, bce, pn2))
+            return false;
+        JSOp op = pn2->getOp();
+        if (op == JSOP_FALSE) {
+            if (Emit1(cx, bce, op) < 0)
+                return false;
         } else {
-            DebugOnly<BindingKind> kind = bce->bindings.lookup(cx, fun->atom, &slot);
-            JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
-            JS_ASSERT(index < JS_BIT(20));
-            pn->pn_index = index;
-            op = fun->isFlatClosure() ? JSOP_DEFLOCALFUN_FC : JSOP_DEFLOCALFUN;
-            if (pn->isClosed() &&
-                !bce->callsEval() &&
-                !bce->closedVars.append(pn->pn_cookie.slot())) {
-                return JS_FALSE;
-            }
-            if (!EmitSlotIndexOp(cx, op, slot, index, bce))
-                return JS_FALSE;
-
-            /* Make blockChain determination quicker. */
-            if (EmitBlockChain(cx, bce) < 0)
-                return JS_FALSE;
+            if (!EmitAtomOp(cx, pn2, op, bce))
+                return false;
         }
         break;
       }
+      case PNK_DOT:
+        if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce, false))
+            return false;
+        break;
+#if JS_HAS_XML_SUPPORT
+      case PNK_DBLDOT:
+        JS_ASSERT(!bce->inStrictMode());
+        if (!EmitElemOp(cx, pn2, JSOP_DELDESC, bce))
+            return false;
+        break;
+#endif
+      case PNK_LB:
+        if (!EmitElemOp(cx, pn2, JSOP_DELELEM, bce))
+            return false;
+        break;
+      default:
+      {
+        /*
+         * If useless, just emit JSOP_TRUE; otherwise convert delete foo()
+         * to foo(), true (a comma expression, requiring SRC_PCDELTA).
+         */
+        JSBool useful = false;
+        if (!CheckSideEffects(cx, bce, pn2, &useful))
+            return false;
+
+        ptrdiff_t off, noteIndex;
+        if (useful) {
+            JS_ASSERT_IF(pn2->isKind(PNK_LP), !(pn2->pn_xflags & PNX_SETCALL));
+            if (!EmitTree(cx, bce, pn2))
+                return false;
+            off = bce->offset();
+            noteIndex = NewSrcNote2(cx, bce, SRC_PCDELTA, 0);
+            if (noteIndex < 0 || Emit1(cx, bce, JSOP_POP) < 0)
+                return false;
+        } else {
+            off = noteIndex = -1;
+        }
+
+        if (Emit1(cx, bce, JSOP_TRUE) < 0)
+            return false;
+        if (noteIndex >= 0) {
+            ptrdiff_t tmp = bce->offset();
+            if (!SetSrcNoteOffset(cx, bce, uintN(noteIndex), 0, tmp - off))
+                return false;
+        }
+      }
+    }
+
+    return true;
+}
+
+static bool
+EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
+{
+    bool callop = pn->isKind(PNK_LP);
+
+    /*
+     * Emit callable invocation or operator new (constructor call) code.
+     * First, emit code for the left operand to evaluate the callable or
+     * constructable object expression.
+     *
+     * For operator new applied to other expressions than E4X ones, we emit
+     * JSOP_GETPROP instead of JSOP_CALLPROP, etc. This is necessary to
+     * interpose the lambda-initialized method read barrier -- see the code
+     * in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP.
+     *
+     * Then (or in a call case that has no explicit reference-base
+     * object) we emit JSOP_PUSH to produce the |this| slot required
+     * for calls (which non-strict mode functions will box into the
+     * global object).
+     */
+    ParseNode *pn2 = pn->pn_head;
+    switch (pn2->getKind()) {
+      case PNK_NAME:
+        if (!EmitNameOp(cx, bce, pn2, callop))
+            return false;
+        break;
+      case PNK_DOT:
+        if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
+            return false;
+        break;
+      case PNK_LB:
+        JS_ASSERT(pn2->isOp(JSOP_GETELEM));
+        if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce))
+            return false;
+        break;
+#if JS_HAS_XML_SUPPORT
+      case PNK_XMLUNARY:
+        JS_ASSERT(pn2->isOp(JSOP_XMLNAME));
+        if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, bce))
+            return false;
+        callop = true;          /* suppress JSOP_PUSH after */
+        break;
+#endif
+      default:
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+        callop = false;             /* trigger JSOP_PUSH after */
+        break;
+    }
+    if (!callop && Emit1(cx, bce, JSOP_PUSH) < 0)
+        return false;
+
+    /* Remember start of callable-object bytecode for decompilation hint. */
+    ptrdiff_t off = top;
+
+    /*
+     * Emit code for each argument in order, then emit the JSOP_*CALL or
+     * JSOP_NEW bytecode with a two-byte immediate telling how many args
+     * were pushed on the operand stack.
+     */
+    uintN oldflags = bce->flags;
+    bce->flags &= ~TCF_IN_FOR_INIT;
+    for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
+        if (!EmitTree(cx, bce, pn3))
+            return false;
+    }
+    bce->flags |= oldflags & TCF_IN_FOR_INIT;
+    if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
+        return false;
+
+    uint32 argc = pn->pn_count - 1;
+    if (Emit3(cx, bce, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0)
+        return false;
+    CheckTypeSet(cx, bce, pn->getOp());
+    if (pn->isOp(JSOP_EVAL)) {
+        EMIT_UINT16_IMM_OP(JSOP_LINENO, pn->pn_pos.begin.lineno);
+        if (EmitBlockChain(cx, bce) < 0)
+            return false;
+    }
+    if (pn->pn_xflags & PNX_SETCALL) {
+        if (Emit1(cx, bce, JSOP_SETCALL) < 0)
+            return false;
+    }
+    return true;
+}
+
+static bool
+EmitLogical(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /*
+     * JSOP_OR converts the operand on the stack to boolean, leaves the original
+     * value on the stack and jumps if true; otherwise it falls into the next
+     * bytecode, which pops the left operand and then evaluates the right operand.
+     * The jump goes around the right operand evaluation.
+     *
+     * JSOP_AND converts the operand on the stack to boolean and jumps if false;
+     * otherwise it falls into the right operand's bytecode.
+     */
+
+    if (pn->isArity(PN_BINARY)) {
+        if (!EmitTree(cx, bce, pn->pn_left))
+            return false;
+        ptrdiff_t top = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
+        if (top < 0)
+            return false;
+        if (Emit1(cx, bce, JSOP_POP) < 0)
+            return false;
+        if (!EmitTree(cx, bce, pn->pn_right))
+            return false;
+        ptrdiff_t off = bce->offset();
+        jsbytecode *pc = bce->code(top);
+        CHECK_AND_SET_JUMP_OFFSET(cx, bce, pc, off - top);
+        *pc = pn->getOp();
+        return true;
+    }
+
+    JS_ASSERT(pn->isArity(PN_LIST));
+    JS_ASSERT(pn->pn_head->pn_next->pn_next);
+
+    /* Left-associative operator chain: avoid too much recursion. */
+    ParseNode *pn2 = pn->pn_head;
+    if (!EmitTree(cx, bce, pn2))
+        return false;
+    ptrdiff_t top = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
+    if (top < 0)
+        return false;
+    if (Emit1(cx, bce, JSOP_POP) < 0)
+        return false;
+
+    /* Emit nodes between the head and the tail. */
+    ptrdiff_t jmp = top;
+    while ((pn2 = pn2->pn_next)->pn_next) {
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+        ptrdiff_t off = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
+        if (off < 0)
+            return false;
+        if (Emit1(cx, bce, JSOP_POP) < 0)
+            return false;
+        if (!SetBackPatchDelta(cx, bce, bce->code(jmp), off - jmp))
+            return false;
+        jmp = off;
+    }
+    if (!EmitTree(cx, bce, pn2))
+        return false;
+
+    pn2 = pn->pn_head;
+    ptrdiff_t off = bce->offset();
+    do {
+        jsbytecode *pc = bce->code(top);
+        ptrdiff_t tmp = GetJumpOffset(bce, pc);
+        CHECK_AND_SET_JUMP_OFFSET(cx, bce, pc, off - top);
+        *pc = pn->getOp();
+        top += tmp;
+    } while ((pn2 = pn2->pn_next)->pn_next);
+
+    return true;
+}
+
+static bool
+EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /* Emit lvalue-specialized code for ++/-- operators. */
+    ParseNode *pn2 = pn->pn_kid;
+    JS_ASSERT(!pn2->isKind(PNK_RP));
+    JSOp op = pn->getOp();
+    switch (pn2->getKind()) {
+      case PNK_DOT:
+        if (!EmitPropIncDec(cx, pn2, op, bce))
+            return false;
+        break;
+      case PNK_LB:
+        if (!EmitElemIncDec(cx, pn2, op, bce))
+            return false;
+        break;
+      case PNK_LP:
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+        if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
+            return false;
+        if (Emit1(cx, bce, op) < 0)
+            return false;
+        /*
+         * This is dead code for the decompiler, don't generate
+         * a decomposed version of the opcode. We do need to balance
+         * the stacks in the decomposed version.
+         */
+        JS_ASSERT(js_CodeSpec[op].format & JOF_DECOMPOSE);
+        JS_ASSERT(js_CodeSpec[op].format & JOF_ELEM);
+        if (Emit1(cx, bce, (JSOp)1) < 0)
+            return false;
+        if (Emit1(cx, bce, JSOP_POP) < 0)
+            return false;
+        break;
+#if JS_HAS_XML_SUPPORT
+      case PNK_XMLUNARY:
+        JS_ASSERT(!bce->inStrictMode());
+        JS_ASSERT(pn2->isOp(JSOP_SETXMLNAME));
+        if (!EmitTree(cx, bce, pn2->pn_kid))
+            return false;
+        if (Emit1(cx, bce, JSOP_BINDXMLNAME) < 0)
+            return false;
+        if (!EmitElemIncDec(cx, NULL, op, bce))
+            return false;
+        break;
+#endif
+      default:
+        JS_ASSERT(pn2->isKind(PNK_NAME));
+        pn2->setOp(op);
+        if (!BindNameToSlot(cx, bce, pn2))
+            return false;
+        op = pn2->getOp();
+        if (op == JSOP_CALLEE) {
+            if (Emit1(cx, bce, op) < 0)
+                return false;
+        } else if (!pn2->pn_cookie.isFree()) {
+            jsatomid atomIndex = pn2->pn_cookie.asInteger();
+            EMIT_UINT16_IMM_OP(op, atomIndex);
+        } else {
+            JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
+            if (js_CodeSpec[op].format & (JOF_INC | JOF_DEC)) {
+                if (!EmitNameIncDec(cx, pn2, op, bce))
+                    return false;
+            } else {
+                if (!EmitAtomOp(cx, pn2, op, bce))
+                    return false;
+            }
+            break;
+        }
+        if (pn2->isConst()) {
+            if (Emit1(cx, bce, JSOP_POS) < 0)
+                return false;
+            op = pn->getOp();
+            if (!(js_CodeSpec[op].format & JOF_POST)) {
+                if (Emit1(cx, bce, JSOP_ONE) < 0)
+                    return false;
+                op = (js_CodeSpec[op].format & JOF_INC) ? JSOP_ADD : JSOP_SUB;
+                if (Emit1(cx, bce, op) < 0)
+                    return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool
+EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /*
+     * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
+     * following the labeled statement. This op has either a SRC_LABEL or
+     * SRC_LABELBRACE source note for the decompiler.
+     */
+    JSAtom *atom = pn->pn_atom;
+
+    jsatomid index;
+    if (!bce->makeAtomIndex(atom, &index))
+        return false;
+
+    ParseNode *pn2 = pn->expr();
+    SrcNoteType noteType = (pn2->isKind(PNK_STATEMENTLIST) ||
+                            (pn2->isKind(PNK_LEXICALSCOPE) &&
+                             pn2->expr()->isKind(PNK_STATEMENTLIST)))
+                           ? SRC_LABELBRACE
+                           : SRC_LABEL;
+    ptrdiff_t noteIndex = NewSrcNote2(cx, bce, noteType, ptrdiff_t(index));
+    if (noteIndex < 0)
+        return false;
+
+    ptrdiff_t top = EmitJump(cx, bce, JSOP_LABEL, 0);
+    if (top < 0)
+        return false;
+
+    /* Emit code for the labeled statement. */
+    StmtInfo stmtInfo;
+    PushStatement(bce, &stmtInfo, STMT_LABEL, bce->offset());
+    stmtInfo.label = atom;
+    if (!EmitTree(cx, bce, pn2))
+        return false;
+    if (!PopStatementBCE(cx, bce))
+        return false;
+
+    /* Patch the JSOP_LABEL offset. */
+    CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, top);
+
+    /* If the statement was compound, emit a note for the end brace. */
+    if (noteType == SRC_LABELBRACE) {
+        if (NewSrcNote(cx, bce, SRC_ENDBRACE) < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
+            return false;
+    }
+
+    return true;
+}
+
+static bool
+EmitSyntheticStatements(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
+{
+    JS_ASSERT(pn->isArity(PN_LIST));
+    StmtInfo stmtInfo;
+    PushStatement(bce, &stmtInfo, STMT_SEQ, top);
+    for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+        if (!EmitTree(cx, bce, pn2))
+            return false;
+    }
+    return PopStatementBCE(cx, bce);
+}
+
+static bool
+EmitConditionalExpression(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /* Emit the condition, then branch if false to the else part. */
+    if (!EmitTree(cx, bce, pn->pn_kid1))
+        return false;
+    ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_COND);
+    if (noteIndex < 0)
+        return false;
+    ptrdiff_t beq = EmitJump(cx, bce, JSOP_IFEQ, 0);
+    if (beq < 0 || !EmitTree(cx, bce, pn->pn_kid2))
+        return false;
+
+    /* Jump around else, fixup the branch, emit else, fixup jump. */
+    ptrdiff_t jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
+    if (jmp < 0)
+        return false;
+    CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, beq);
+
+    /*
+     * Because each branch pushes a single value, but our stack budgeting
+     * analysis ignores branches, we now have to adjust bce->stackDepth to
+     * ignore the value pushed by the first branch.  Execution will follow
+     * only one path, so we must decrement bce->stackDepth.
+     *
+     * Failing to do this will foil code, such as let expression and block
+     * code generation, which must use the stack depth to compute local
+     * stack indexes correctly.
+     */
+    JS_ASSERT(bce->stackDepth > 0);
+    bce->stackDepth--;
+    if (!EmitTree(cx, bce, pn->pn_kid3))
+        return false;
+    CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, jmp);
+    return SetSrcNoteOffset(cx, bce, noteIndex, 0, jmp - beq);
+}
+
+static bool
+EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, jsint sharpnum)
+{
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+    if (pn->pn_xflags & PNX_DESTRUCT) {
+        ReportCompileErrorNumber(cx, bce->tokenStream(), pn, JSREPORT_ERROR,
+                                 JSMSG_BAD_OBJECT_INIT);
+        return false;
+    }
+#endif
+
+    if (!bce->hasSharps() && !(pn->pn_xflags & PNX_NONCONST) && pn->pn_head &&
+        bce->checkSingletonContext())
+    {
+        return EmitSingletonInitialiser(cx, bce, pn);
+    }
+
+    /*
+     * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
+     * a new object and in source order evaluating each property value and
+     * adding the property to the object, without invoking latent setters.
+     * We use the JSOP_NEWINIT and JSOP_INITELEM/JSOP_INITPROP bytecodes to
+     * ignore setters and to avoid dup'ing and popping the object as each
+     * property is added, as JSOP_SETELEM/JSOP_SETPROP would do.
+     */
+    ptrdiff_t offset = bce->next() - bce->base();
+    if (!EmitNewInit(cx, bce, JSProto_Object, pn, sharpnum))
+        return false;
+
+    /*
+     * Try to construct the shape of the object as we go, so we can emit a
+     * JSOP_NEWOBJECT with the final shape instead.
+     */
+    JSObject *obj = NULL;
+    if (!bce->hasSharps() && bce->compileAndGo()) {
+        gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
+        obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
+        if (!obj)
+            return false;
+    }
+
+    uintN methodInits = 0, slowMethodInits = 0;
+    for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+        /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
+        ParseNode *pn3 = pn2->pn_left;
+        if (pn3->isKind(PNK_NUMBER)) {
+            if (!EmitNumberOp(cx, pn3->pn_dval, bce))
+                return false;
+        }
+
+        /* Emit code for the property initializer. */
+        if (!EmitTree(cx, bce, pn2->pn_right))
+            return false;
+
+        JSOp op = pn2->getOp();
+        if (op == JSOP_GETTER || op == JSOP_SETTER) {
+            obj = NULL;
+            if (Emit1(cx, bce, op) < 0)
+                return false;
+        }
+
+        /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */
+        if (pn3->isKind(PNK_NUMBER)) {
+            obj = NULL;
+            if (NewSrcNote(cx, bce, SRC_INITPROP) < 0)
+                return false;
+            if (Emit1(cx, bce, JSOP_INITELEM) < 0)
+                return false;
+        } else {
+            JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
+            jsatomid index;
+            if (!bce->makeAtomIndex(pn3->pn_atom, &index))
+                return false;
+
+            /* Check whether we can optimize to JSOP_INITMETHOD. */
+            ParseNode *init = pn2->pn_right;
+            bool lambda = init->isOp(JSOP_LAMBDA);
+            if (lambda)
+                ++methodInits;
+            if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) {
+                obj = NULL;
+                op = JSOP_INITMETHOD;
+                if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
+                    return JS_FALSE;
+                pn2->setOp(op);
+            } else {
+                /*
+                 * Disable NEWOBJECT on initializers that set __proto__, which has
+                 * a non-standard setter on objects.
+                 */
+                if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
+                    obj = NULL;
+                op = JSOP_INITPROP;
+                if (lambda)
+                    ++slowMethodInits;
+            }
+
+            if (obj) {
+                JS_ASSERT(!obj->inDictionaryMode());
+                if (!DefineNativeProperty(cx, obj, ATOM_TO_JSID(pn3->pn_atom),
+                                          UndefinedValue(), NULL, NULL,
+                                          JSPROP_ENUMERATE, 0, 0))
+                {
+                    return false;
+                }
+                if (obj->inDictionaryMode())
+                    obj = NULL;
+            }
+
+            EMIT_INDEX_OP(op, index);
+        }
+    }
+
+    if (!EmitEndInit(cx, bce, pn->pn_count))
+        return false;
+
+    if (obj) {
+        /*
+         * The object survived and has a predictable shape.  Update the original bytecode,
+         * as long as we can do so without using a big index prefix/suffix.
+         */
+        ObjectBox *objbox = bce->parser->newObjectBox(obj);
+        if (!objbox)
+            return false;
+        uintN index = bce->objectList.index(objbox);
+        if (FitsWithoutBigIndex(index))
+            EMIT_UINT16_IN_PLACE(offset, JSOP_NEWOBJECT, uint16(index));
+    }
+
+    return true;
+}
+
+static bool
+EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, jsint sharpnum)
+{
+    /*
+     * Emit code for [a, b, c] that is equivalent to constructing a new
+     * array and in source order evaluating each element value and adding
+     * it to the array, without invoking latent setters.  We use the
+     * JSOP_NEWINIT and JSOP_INITELEM bytecodes to ignore setters and to
+     * avoid dup'ing and popping the array as each element is added, as
+     * JSOP_SETELEM/JSOP_SETPROP would do.
+     */
+
+#if JS_HAS_GENERATORS
+    if (pn->isKind(PNK_ARRAYCOMP)) {
+        if (!EmitNewInit(cx, bce, JSProto_Array, pn, sharpnum))
+            return false;
+
+        /*
+         * Pass the new array's stack index to the PNK_ARRAYPUSH case via
+         * bce->arrayCompDepth, then simply traverse the PNK_FOR node and
+         * its kids under pn2 to generate this comprehension.
+         */
+        JS_ASSERT(bce->stackDepth > 0);
+        uintN saveDepth = bce->arrayCompDepth;
+        bce->arrayCompDepth = (uint32) (bce->stackDepth - 1);
+        if (!EmitTree(cx, bce, pn->pn_head))
+            return false;
+        bce->arrayCompDepth = saveDepth;
+
+        /* Emit the usual op needed for decompilation. */
+        if (!EmitEndInit(cx, bce, 1))
+            return false;
+        return true;
+    }
+#endif /* JS_HAS_GENERATORS */
+
+    if (!bce->hasSharps() && !(pn->pn_xflags & PNX_NONCONST) && pn->pn_head &&
+        bce->checkSingletonContext())
+    {
+        return EmitSingletonInitialiser(cx, bce, pn);
+    }
+
+    /* Use the slower NEWINIT for arrays in scripts containing sharps. */
+    if (bce->hasSharps()) {
+        if (!EmitNewInit(cx, bce, JSProto_Array, pn, sharpnum))
+            return false;
+    } else {
+        ptrdiff_t off = EmitN(cx, bce, JSOP_NEWARRAY, 3);
+        if (off < 0)
+            return false;
+        jsbytecode *pc = bce->code(off);
+        SET_UINT24(pc, pn->pn_count);
+    }
+
+    ParseNode *pn2 = pn->pn_head;
+    jsatomid atomIndex;
+    for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
+        if (!EmitNumberOp(cx, atomIndex, bce))
+            return false;
+        if (pn2->isKind(PNK_COMMA) && pn2->isArity(PN_NULLARY)) {
+            if (Emit1(cx, bce, JSOP_HOLE) < 0)
+                return false;
+        } else {
+            if (!EmitTree(cx, bce, pn2))
+                return false;
+        }
+        if (Emit1(cx, bce, JSOP_INITELEM) < 0)
+            return false;
+    }
+    JS_ASSERT(atomIndex == pn->pn_count);
+
+    if (pn->pn_xflags & PNX_ENDCOMMA) {
+        /* Emit a source note so we know to decompile an extra comma. */
+        if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
+            return false;
+    }
+
+    /*
+     * Emit an op to finish the array and, secondarily, to aid in sharp
+     * array cleanup (if JS_HAS_SHARP_VARS) and decompilation.
+     */
+    return EmitEndInit(cx, bce, atomIndex);
+}
+
+static bool
+EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    /* Unary op, including unary +/-. */
+    JSOp op = pn->getOp();
+    ParseNode *pn2 = pn->pn_kid;
+
+    JS_ASSERT(op != JSOP_XMLNAME);
+    if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
+        op = JSOP_TYPEOFEXPR;
+
+    uintN oldflags = bce->flags;
+    bce->flags &= ~TCF_IN_FOR_INIT;
+    if (!EmitTree(cx, bce, pn2))
+        return false;
+
+    bce->flags |= oldflags & TCF_IN_FOR_INIT;
+    return Emit1(cx, bce, op) >= 0;
+}
+
+JSBool
+frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+{
+    ptrdiff_t top, off, tmp, jmp;
+    ParseNode *pn2;
+    JSAtom *atom;
+    ptrdiff_t noteIndex;
+    JSOp op;
+    EmitLevelManager elm(bce);
+    jsint sharpnum = -1;
+
+    JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+    JSBool ok = true;
+    pn->pn_offset = top = bce->offset();
+
+    /* Emit notes to tell the current bytecode's source line number. */
+    UPDATE_LINE_NUMBER_NOTES(cx, bce, pn->pn_pos.begin.lineno);
+
+    switch (pn->getKind()) {
+      case PNK_FUNCTION:
+        ok = EmitFunc(cx, bce, pn);
+        break;
 
       case PNK_ARGSBODY:
       {
         ParseNode *pnlast = pn->last();
         for (ParseNode *pn2 = pn->pn_head; pn2 != pnlast; pn2 = pn2->pn_next) {
             if (!pn2->isDefn())
                 continue;
             if (!BindNameToSlot(cx, bce, pn2))
@@ -5970,172 +6972,34 @@ frontend::EmitTree(JSContext *cx, Byteco
         ok = EmitIf(cx, bce, pn);
         break;
 
       case PNK_SWITCH:
         ok = EmitSwitch(cx, bce, pn);
         break;
 
       case PNK_WHILE:
-        /*
-         * Minimize bytecodes issued for one or more iterations by jumping to
-         * the condition below the body and closing the loop if the condition
-         * is true with a backward branch. For iteration count i:
-         *
-         *  i    test at the top                 test at the bottom
-         *  =    ===============                 ==================
-         *  0    ifeq-pass                       goto; ifne-fail
-         *  1    ifeq-fail; goto; ifne-pass      goto; ifne-pass; ifne-fail
-         *  2    2*(ifeq-fail; goto); ifeq-pass  goto; 2*ifne-pass; ifne-fail
-         *  . . .
-         *  N    N*(ifeq-fail; goto); ifeq-pass  goto; N*ifne-pass; ifne-fail
-         *
-         * SpiderMonkey, pre-mozilla.org, emitted while parsing and so used
-         * test at the top. When ParseNode trees were added during the ES3
-         * work (1998-9), the code generation scheme was not optimized, and
-         * the decompiler continued to take advantage of the branch and jump
-         * that bracketed the body. But given the SRC_WHILE note, it is easy
-         * to support the more efficient scheme.
-         */
-        PushStatement(bce, &stmtInfo, STMT_WHILE_LOOP, top);
-        noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
-        if (noteIndex < 0)
-            return JS_FALSE;
-        jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
-        if (jmp < 0)
-            return JS_FALSE;
-        noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
-        if (noteIndex2 < 0)
-            return JS_FALSE;
-        top = EmitTraceOp(cx, bce, pn->pn_right);
-        if (top < 0)
-            return JS_FALSE;
-        if (!EmitTree(cx, bce, pn->pn_right))
-            return JS_FALSE;
-        CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, jmp);
-        if (!EmitTree(cx, bce, pn->pn_left))
-            return JS_FALSE;
-        beq = EmitJump(cx, bce, JSOP_IFNE, top - bce->offset());
-        if (beq < 0)
-            return JS_FALSE;
-        /*
-         * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
-         * note gets bigger.
-         */
-        if (!SetSrcNoteOffset(cx, bce, noteIndex2, 0, beq - top))
-            return JS_FALSE;
-        if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, beq - jmp))
-            return JS_FALSE;
-        ok = PopStatementBCE(cx, bce);
+        ok = EmitWhile(cx, bce, pn, top);
         break;
 
       case PNK_DOWHILE:
-        /* Emit an annotated nop so we know to decompile a 'do' keyword. */
-        noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
-        if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
-            return JS_FALSE;
-
-        noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
-        if (noteIndex2 < 0)
-            return JS_FALSE;
-
-        /* Compile the loop body. */
-        top = EmitTraceOp(cx, bce, pn->pn_left);
-        if (top < 0)
-            return JS_FALSE;
-        PushStatement(bce, &stmtInfo, STMT_DO_LOOP, top);
-        if (!EmitTree(cx, bce, pn->pn_left))
-            return JS_FALSE;
-
-        /* Set loop and enclosing label update offsets, for continue. */
-        off = bce->offset();
-        stmt = &stmtInfo;
-        do {
-            stmt->update = off;
-        } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
-
-        /* Compile the loop condition, now that continues know where to go. */
-        if (!EmitTree(cx, bce, pn->pn_right))
-            return JS_FALSE;
-
-        /*
-         * Since we use JSOP_IFNE for other purposes as well as for do-while
-         * loops, we must store 1 + (beq - top) in the SRC_WHILE note offset,
-         * and the decompiler must get that delta and decompile recursively.
-         */
-        beq = EmitJump(cx, bce, JSOP_IFNE, top - bce->offset());
-        if (beq < 0)
-            return JS_FALSE;
-        /*
-         * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
-         * note gets bigger.
-         */
-        if (!SetSrcNoteOffset(cx, bce, noteIndex2, 0, beq - top))
-            return JS_FALSE;
-        if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, 1 + (off - top)))
-            return JS_FALSE;
-        ok = PopStatementBCE(cx, bce);
+        ok = EmitDo(cx, bce, pn);
         break;
 
       case PNK_FOR:
         ok = EmitFor(cx, bce, pn, top);
         break;
 
-      case PNK_BREAK: {
-        stmt = bce->topStmt;
-        atom = pn->pn_atom;
-
-        jsatomid labelIndex;
-        if (atom) {
-            if (!bce->makeAtomIndex(atom, &labelIndex))
-                return JS_FALSE;
-
-            while (stmt->type != STMT_LABEL || stmt->label != atom)
-                stmt = stmt->down;
-            noteType = SRC_BREAK2LABEL;
-        } else {
-            labelIndex = INVALID_ATOMID;
-            while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)
-                stmt = stmt->down;
-            noteType = (stmt->type == STMT_SWITCH) ? SRC_SWITCHBREAK : SRC_BREAK;
-        }
-
-        if (EmitGoto(cx, bce, stmt, &stmt->breaks, labelIndex, noteType) < 0)
-            return JS_FALSE;
+      case PNK_BREAK:
+        ok = EmitBreak(cx, bce, pn);
         break;
-      }
-
-      case PNK_CONTINUE: {
-        stmt = bce->topStmt;
-        atom = pn->pn_atom;
-
-        jsatomid labelIndex;
-        if (atom) {
-            /* Find the loop statement enclosed by the matching label. */
-            StmtInfo *loop = NULL;
-            if (!bce->makeAtomIndex(atom, &labelIndex))
-                return JS_FALSE;
-            while (stmt->type != STMT_LABEL || stmt->label != atom) {
-                if (STMT_IS_LOOP(stmt))
-                    loop = stmt;
-                stmt = stmt->down;
-            }
-            stmt = loop;
-            noteType = SRC_CONT2LABEL;
-        } else {
-            labelIndex = INVALID_ATOMID;
-            while (!STMT_IS_LOOP(stmt))
-                stmt = stmt->down;
-            noteType = SRC_CONTINUE;
-        }
-
-        if (EmitGoto(cx, bce, stmt, &stmt->continues, labelIndex, noteType) < 0)
-            return JS_FALSE;
+
+      case PNK_CONTINUE:
+        ok = EmitContinue(cx, bce, pn);
         break;
-      }
 
       case PNK_WITH:
         ok = EmitWith(cx, bce, pn);
         break;
 
       case PNK_TRY:
         if (!EmitTry(cx, bce, pn))
             return false;
@@ -6148,49 +7012,17 @@ frontend::EmitTree(JSContext *cx, Byteco
 
       case PNK_VAR:
       case PNK_CONST:
         if (!EmitVariables(cx, bce, pn, JS_FALSE, &noteIndex))
             return JS_FALSE;
         break;
 
       case PNK_RETURN:
-        /* Push a return value */
-        pn2 = pn->pn_kid;
-        if (pn2) {
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-        } else {
-            if (Emit1(cx, bce, JSOP_PUSH) < 0)
-                return JS_FALSE;
-        }
-
-        /*
-         * EmitNonLocalJumpFixup may add fixup bytecode to close open try
-         * blocks having finally clauses and to exit intermingled let blocks.
-         * We can't simply transfer control flow to our caller in that case,
-         * because we must gosub to those finally clauses from inner to outer,
-         * with the correct stack pointer (i.e., after popping any with,
-         * for/in, etc., slots nested inside the finally's try).
-         *
-         * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
-         * extra JSOP_RETRVAL after the fixups.
-         */
-        top = bce->offset();
-        if (Emit1(cx, bce, JSOP_RETURN) < 0)
-            return JS_FALSE;
-        if (!EmitNonLocalJumpFixup(cx, bce, NULL))
-            return JS_FALSE;
-        if (top + JSOP_RETURN_LENGTH != bce->offset()) {
-            bce->base()[top] = JSOP_SETRVAL;
-            if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
-                return JS_FALSE;
-            if (EmitBlockChain(cx, bce) < 0)
-                return JS_FALSE;
-        }
+        ok = EmitReturn(cx, bce, pn);
         break;
 
 #if JS_HAS_GENERATORS
       case PNK_YIELD:
         JS_ASSERT(bce->inFunction());
         if (pn->pn_kid) {
             if (!EmitTree(cx, bce, pn->pn_kid))
                 return JS_FALSE;
@@ -6211,217 +7043,29 @@ frontend::EmitTree(JSContext *cx, Byteco
         if (!EmitTree(cx, bce, pn->pn_kid))
             return JS_FALSE;
         if (Emit1(cx, bce, pn->getOp()) < 0)
             return JS_FALSE;
         break;
 #endif
 
       case PNK_STATEMENTLIST:
-      {
-        JS_ASSERT(pn->isArity(PN_LIST));
-
-        noteIndex = -1;
-        tmp = bce->offset();
-        if (pn->pn_xflags & PNX_NEEDBRACES) {
-            noteIndex = NewSrcNote2(cx, bce, SRC_BRACE, 0);
-            if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
-                return JS_FALSE;
-        }
-
-        PushStatement(bce, &stmtInfo, STMT_BLOCK, top);
-
-        ParseNode *pnchild = pn->pn_head;
-        if (pn->pn_xflags & PNX_FUNCDEFS) {
-            /*
-             * This block contains top-level function definitions. To ensure
-             * that we emit the bytecode defining them before the rest of code
-             * in the block we use a separate pass over functions. During the
-             * main pass later the emitter will add JSOP_NOP with source notes
-             * for the function to preserve the original functions position
-             * when decompiling.
-             *
-             * Currently this is used only for functions, as compile-as-we go
-             * mode for scripts does not allow separate emitter passes.
-             */
-            JS_ASSERT(bce->inFunction());
-            if (pn->pn_xflags & PNX_DESTRUCT) {
-                /*
-                 * Assign the destructuring arguments before defining any
-                 * functions, see bug 419662.
-                 */
-                JS_ASSERT(pnchild->isKind(PNK_SEMI));
-                JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_CONST));
-                if (!EmitTree(cx, bce, pnchild))
-                    return JS_FALSE;
-                pnchild = pnchild->pn_next;
-            }
-
-            for (pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
-                if (pn2->isKind(PNK_FUNCTION)) {
-                    if (pn2->isOp(JSOP_NOP)) {
-                        if (!EmitTree(cx, bce, pn2))
-                            return JS_FALSE;
-                    } else {
-                        /*
-                         * JSOP_DEFFUN in a top-level block with function
-                         * definitions appears, for example, when "if (true)"
-                         * is optimized away from "if (true) function x() {}".
-                         * See bug 428424.
-                         */
-                        JS_ASSERT(pn2->isOp(JSOP_DEFFUN));
-                    }
-                }
-            }
-        }
-        for (pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-        }
-
-        if (noteIndex >= 0 && !SetSrcNoteOffset(cx, bce, (uintN)noteIndex, 0, bce->offset() - tmp))
-            return JS_FALSE;
-
-        ok = PopStatementBCE(cx, bce);
+        ok = EmitStatementList(cx, bce, pn, top);
         break;
-      }
 
       case PNK_SEQ:
-        JS_ASSERT(pn->isArity(PN_LIST));
-        PushStatement(bce, &stmtInfo, STMT_SEQ, top);
-        for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-        }
-        ok = PopStatementBCE(cx, bce);
+        ok = EmitSyntheticStatements(cx, bce, pn, top);
         break;
 
       case PNK_SEMI:
-        pn2 = pn->pn_kid;
-        if (pn2) {
-            /*
-             * Top-level or called-from-a-native JS_Execute/EvaluateScript,
-             * debugger, and eval frames may need the value of the ultimate
-             * expression statement as the script's result, despite the fact
-             * that it appears useless to the compiler.
-             *
-             * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
-             * calling JS_Compile* to suppress JSOP_POPV.
-             */
-            useful = wantval = !(bce->flags & (TCF_IN_FUNCTION | TCF_NO_SCRIPT_RVAL));
-
-            /* Don't eliminate expressions with side effects. */
-            if (!useful) {
-                if (!CheckSideEffects(cx, bce, pn2, &useful))
-                    return JS_FALSE;
-            }
-
-            /*
-             * Don't eliminate apparently useless expressions if they are
-             * labeled expression statements.  The tc->topStmt->update test
-             * catches the case where we are nesting in EmitTree for a labeled
-             * compound statement.
-             */
-            if (!useful &&
-                bce->topStmt &&
-                bce->topStmt->type == STMT_LABEL &&
-                bce->topStmt->update >= bce->offset()) {
-                useful = true;
-            }
-
-            if (!useful) {
-                /* Don't complain about directive prologue members; just don't emit their code. */
-                if (!pn->isDirectivePrologueMember()) {
-                    bce->current->currentLine = pn2->pn_pos.begin.lineno;
-                    if (!ReportCompileErrorNumber(cx, bce->tokenStream(), pn2,
-                                                  JSREPORT_WARNING | JSREPORT_STRICT,
-                                                  JSMSG_USELESS_EXPR)) {
-                        return JS_FALSE;
-                    }
-                }
-            } else {
-                op = wantval ? JSOP_POPV : JSOP_POP;
-                JS_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
-#if JS_HAS_DESTRUCTURING
-                if (!wantval &&
-                    pn2->isKind(PNK_ASSIGN) &&
-                    !MaybeEmitGroupAssignment(cx, bce, op, pn2, &op)) {
-                    return JS_FALSE;
-                }
-#endif
-                if (op != JSOP_NOP) {
-                    /*
-                     * Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or
-                     * avoid null closure cloning. Do this only for assignment
-                     * statements that are not completion values wanted by a
-                     * script evaluator, to ensure that the joined function
-                     * can't escape directly.
-                     */
-                    if (!wantval &&
-                        pn2->isKind(PNK_ASSIGN) &&
-                        pn2->pn_left->isOp(JSOP_SETPROP) &&
-                        pn2->pn_right->isOp(JSOP_LAMBDA) &&
-                        pn2->pn_right->pn_funbox->joinable()) {
-                        if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
-                            return JS_FALSE;
-                        pn2->pn_left->setOp(JSOP_SETMETHOD);
-                    }
-                    if (!EmitTree(cx, bce, pn2))
-                        return JS_FALSE;
-                    if (Emit1(cx, bce, op) < 0)
-                        return JS_FALSE;
-                }
-            }
-        }
+        ok = EmitStatement(cx, bce, pn);
         break;
 
       case PNK_COLON:
-        /*
-         * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
-         * following the labeled statement. This op has either a SRC_LABEL or
-         * SRC_LABELBRACE source note for the decompiler.
-         */
-        atom = pn->pn_atom;
-
-        jsatomid index;
-        if (!bce->makeAtomIndex(atom, &index))
-            return JS_FALSE;
-
-        pn2 = pn->expr();
-        noteType = (pn2->isKind(PNK_STATEMENTLIST) ||
-                    (pn2->isKind(PNK_LEXICALSCOPE) &&
-                     pn2->expr()->isKind(PNK_STATEMENTLIST)))
-                   ? SRC_LABELBRACE
-                   : SRC_LABEL;
-        noteIndex = NewSrcNote2(cx, bce, noteType, ptrdiff_t(index));
-        if (noteIndex < 0)
-            return JS_FALSE;
-
-        top = EmitJump(cx, bce, JSOP_LABEL, 0);
-        if (top < 0)
-            return JS_FALSE;
-
-        /* Emit code for the labeled statement. */
-        PushStatement(bce, &stmtInfo, STMT_LABEL, bce->offset());
-        stmtInfo.label = atom;
-        if (!EmitTree(cx, bce, pn2))
-            return JS_FALSE;
-        if (!PopStatementBCE(cx, bce))
-            return JS_FALSE;
-
-        /* Patch the JSOP_LABEL offset. */
-        CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, top);
-
-        /* If the statement was compound, emit a note for the end brace. */
-        if (noteType == SRC_LABELBRACE) {
-            if (NewSrcNote(cx, bce, SRC_ENDBRACE) < 0 ||
-                Emit1(cx, bce, JSOP_NOP) < 0) {
-                return JS_FALSE;
-            }
-        }
+        ok = EmitLabel(cx, bce, pn);
         break;
 
       case PNK_COMMA:
         /*
          * Emit SRC_PCDELTA notes on each JSOP_POP between comma operands.
          * These notes help the decompiler bracket the bytecodes generated
          * from each sub-expression that follows a comma.
          */
@@ -6457,120 +7101,22 @@ frontend::EmitTree(JSContext *cx, Byteco
       case PNK_MULASSIGN:
       case PNK_DIVASSIGN:
       case PNK_MODASSIGN:
         if (!EmitAssignment(cx, bce, pn->pn_left, pn->getOp(), pn->pn_right))
             return false;
         break;
 
       case PNK_HOOK:
-        /* Emit the condition, then branch if false to the else part. */
-        if (!EmitTree(cx, bce, pn->pn_kid1))
-            return JS_FALSE;
-        noteIndex = NewSrcNote(cx, bce, SRC_COND);
-        if (noteIndex < 0)
-            return JS_FALSE;
-        beq = EmitJump(cx, bce, JSOP_IFEQ, 0);
-        if (beq < 0 || !EmitTree(cx, bce, pn->pn_kid2))
-            return JS_FALSE;
-
-        /* Jump around else, fixup the branch, emit else, fixup jump. */
-        jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
-        if (jmp < 0)
-            return JS_FALSE;
-        CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, beq);
-
-        /*
-         * Because each branch pushes a single value, but our stack budgeting
-         * analysis ignores branches, we now have to adjust bce->stackDepth to
-         * ignore the value pushed by the first branch.  Execution will follow
-         * only one path, so we must decrement bce->stackDepth.
-         *
-         * Failing to do this will foil code, such as the try/catch/finally
-         * exception handling code generator, that samples bce->stackDepth for
-         * use at runtime (JSOP_SETSP), or in let expression and block code
-         * generation, which must use the stack depth to compute local stack
-         * indexes correctly.
-         */
-        JS_ASSERT(bce->stackDepth > 0);
-        bce->stackDepth--;
-        if (!EmitTree(cx, bce, pn->pn_kid3))
-            return JS_FALSE;
-        CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, jmp);
-        if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, jmp - beq))
-            return JS_FALSE;
+        ok = EmitConditionalExpression(cx, bce, pn);
         break;
 
       case PNK_OR:
       case PNK_AND:
-        /*
-         * JSOP_OR converts the operand on the stack to boolean, leaves the original
-         * value on the stack and jumps if true; otherwise it falls into the next
-         * bytecode, which pops the left operand and then evaluates the right operand.
-         * The jump goes around the right operand evaluation.
-         *
-         * JSOP_AND converts the operand on the stack to boolean and jumps if false;
-         * otherwise it falls into the right operand's bytecode.
-         */
-        if (pn->isArity(PN_BINARY)) {
-            if (!EmitTree(cx, bce, pn->pn_left))
-                return JS_FALSE;
-            top = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
-            if (top < 0)
-                return JS_FALSE;
-            if (Emit1(cx, bce, JSOP_POP) < 0)
-                return JS_FALSE;
-            if (!EmitTree(cx, bce, pn->pn_right))
-                return JS_FALSE;
-            off = bce->offset();
-            pc = bce->code(top);
-            CHECK_AND_SET_JUMP_OFFSET(cx, bce, pc, off - top);
-            *pc = pn->getOp();
-        } else {
-            JS_ASSERT(pn->isArity(PN_LIST));
-            JS_ASSERT(pn->pn_head->pn_next->pn_next);
-
-            /* Left-associative operator chain: avoid too much recursion. */
-            pn2 = pn->pn_head;
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-            top = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
-            if (top < 0)
-                return JS_FALSE;
-            if (Emit1(cx, bce, JSOP_POP) < 0)
-                return JS_FALSE;
-
-            /* Emit nodes between the head and the tail. */
-            jmp = top;
-            while ((pn2 = pn2->pn_next)->pn_next) {
-                if (!EmitTree(cx, bce, pn2))
-                    return JS_FALSE;
-                off = EmitJump(cx, bce, JSOP_BACKPATCH, 0);
-                if (off < 0)
-                    return JS_FALSE;
-                if (Emit1(cx, bce, JSOP_POP) < 0)
-                    return JS_FALSE;
-                if (!SetBackPatchDelta(cx, bce, bce->code(jmp), off - jmp))
-                    return JS_FALSE;
-                jmp = off;
-
-            }
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-
-            pn2 = pn->pn_head;
-            off = bce->offset();
-            do {
-                pc = bce->code(top);
-                tmp = GetJumpOffset(bce, pc);
-                CHECK_AND_SET_JUMP_OFFSET(cx, bce, pc, off - top);
-                *pc = pn->getOp();
-                top += tmp;
-            } while ((pn2 = pn2->pn_next)->pn_next);
-        }
+        ok = EmitLogical(cx, bce, pn);
         break;
 
       case PNK_ADD:
       case PNK_SUB:
       case PNK_BITOR:
       case PNK_BITXOR:
       case PNK_BITAND:
       case PNK_STRICTEQ:
@@ -6664,181 +7210,26 @@ frontend::EmitTree(JSContext *cx, Byteco
         /* FALL THROUGH */
 #endif
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
       case PNK_POS:
       case PNK_NEG:
-      {
-        /* Unary op, including unary +/-. */
-        op = pn->getOp();
-        pn2 = pn->pn_kid;
-
-        JS_ASSERT(op != JSOP_XMLNAME);
-        if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
-            op = JSOP_TYPEOFEXPR;
-
-        uintN oldflags = bce->flags;
-        bce->flags &= ~TCF_IN_FOR_INIT;
-        if (!EmitTree(cx, bce, pn2))
-            return JS_FALSE;
-        bce->flags |= oldflags & TCF_IN_FOR_INIT;
-        if (Emit1(cx, bce, op) < 0)
-            return JS_FALSE;
+        ok = EmitUnary(cx, bce, pn);
         break;
-      }
 
       case PNK_INC:
       case PNK_DEC:
-        /* Emit lvalue-specialized code for ++/-- operators. */
-        pn2 = pn->pn_kid;
-        JS_ASSERT(!pn2->isKind(PNK_RP));
-        op = pn->getOp();
-        switch (pn2->getKind()) {
-          default:
-            JS_ASSERT(pn2->isKind(PNK_NAME));
-            pn2->setOp(op);
-            if (!BindNameToSlot(cx, bce, pn2))
-                return JS_FALSE;
-            op = pn2->getOp();
-            if (op == JSOP_CALLEE) {
-                if (Emit1(cx, bce, op) < 0)
-                    return JS_FALSE;
-            } else if (!pn2->pn_cookie.isFree()) {
-                atomIndex = pn2->pn_cookie.asInteger();
-                EMIT_UINT16_IMM_OP(op, atomIndex);
-            } else {
-                JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
-                if (js_CodeSpec[op].format & (JOF_INC | JOF_DEC)) {
-                    if (!EmitNameIncDec(cx, pn2, op, bce))
-                        return JS_FALSE;
-                } else {
-                    if (!EmitAtomOp(cx, pn2, op, bce))
-                        return JS_FALSE;
-                }
-                break;
-            }
-            if (pn2->isConst()) {
-                if (Emit1(cx, bce, JSOP_POS) < 0)
-                    return JS_FALSE;
-                op = pn->getOp();
-                if (!(js_CodeSpec[op].format & JOF_POST)) {
-                    if (Emit1(cx, bce, JSOP_ONE) < 0)
-                        return JS_FALSE;
-                    op = (js_CodeSpec[op].format & JOF_INC) ? JSOP_ADD : JSOP_SUB;
-                    if (Emit1(cx, bce, op) < 0)
-                        return JS_FALSE;
-                }
-            }
-            break;
-          case PNK_DOT:
-            if (!EmitPropIncDec(cx, pn2, op, bce))
-                return JS_FALSE;
-            break;
-          case PNK_LB:
-            if (!EmitElemIncDec(cx, pn2, op, bce))
-                return JS_FALSE;
-            break;
-          case PNK_LP:
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-            if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
-                return JS_FALSE;
-            if (Emit1(cx, bce, op) < 0)
-                return JS_FALSE;
-            /*
-             * This is dead code for the decompiler, don't generate
-             * a decomposed version of the opcode. We do need to balance
-             * the stacks in the decomposed version.
-             */
-            JS_ASSERT(js_CodeSpec[op].format & JOF_DECOMPOSE);
-            JS_ASSERT(js_CodeSpec[op].format & JOF_ELEM);
-            if (Emit1(cx, bce, (JSOp)1) < 0)
-                return JS_FALSE;
-            if (Emit1(cx, bce, JSOP_POP) < 0)
-                return JS_FALSE;
-            break;
-#if JS_HAS_XML_SUPPORT
-          case PNK_XMLUNARY:
-            JS_ASSERT(!bce->inStrictMode());
-            JS_ASSERT(pn2->isOp(JSOP_SETXMLNAME));
-            if (!EmitTree(cx, bce, pn2->pn_kid))
-                return JS_FALSE;
-            if (Emit1(cx, bce, JSOP_BINDXMLNAME) < 0)
-                return JS_FALSE;
-            if (!EmitElemIncDec(cx, NULL, op, bce))
-                return JS_FALSE;
-            break;
-#endif
-        }
+        ok = EmitIncOrDec(cx, bce, pn);
         break;
 
       case PNK_DELETE:
-        /*
-         * Under ECMA 3, deleting a non-reference returns true -- but alas we
-         * must evaluate the operand if it appears it might have side effects.
-         */
-        pn2 = pn->pn_kid;
-        switch (pn2->getKind()) {
-          case PNK_NAME:
-            if (!BindNameToSlot(cx, bce, pn2))
-                return JS_FALSE;
-            op = pn2->getOp();
-            if (op == JSOP_FALSE) {
-                if (Emit1(cx, bce, op) < 0)
-                    return JS_FALSE;
-            } else {
-                if (!EmitAtomOp(cx, pn2, op, bce))
-                    return JS_FALSE;
-            }
-            break;
-          case PNK_DOT:
-            if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce, JS_FALSE))
-                return JS_FALSE;
-            break;
-#if JS_HAS_XML_SUPPORT
-          case PNK_DBLDOT:
-            JS_ASSERT(!bce->inStrictMode());
-            if (!EmitElemOp(cx, pn2, JSOP_DELDESC, bce))
-                return JS_FALSE;
-            break;
-#endif
-          case PNK_LB:
-            if (!EmitElemOp(cx, pn2, JSOP_DELELEM, bce))
-                return JS_FALSE;
-            break;
-          default:
-            /*
-             * If useless, just emit JSOP_TRUE; otherwise convert delete foo()
-             * to foo(), true (a comma expression, requiring SRC_PCDELTA).
-             */
-            useful = JS_FALSE;
-            if (!CheckSideEffects(cx, bce, pn2, &useful))
-                return JS_FALSE;
-            if (!useful) {
-                off = noteIndex = -1;
-            } else {
-                JS_ASSERT_IF(pn2->isKind(PNK_LP), !(pn2->pn_xflags & PNX_SETCALL));
-                if (!EmitTree(cx, bce, pn2))
-                    return JS_FALSE;
-                off = bce->offset();
-                noteIndex = NewSrcNote2(cx, bce, SRC_PCDELTA, 0);
-                if (noteIndex < 0 || Emit1(cx, bce, JSOP_POP) < 0)
-                    return JS_FALSE;
-            }
-            if (Emit1(cx, bce, JSOP_TRUE) < 0)
-                return JS_FALSE;
-            if (noteIndex >= 0) {
-                tmp = bce->offset();
-                if (!SetSrcNoteOffset(cx, bce, (uintN)noteIndex, 0, tmp-off))
-                    return JS_FALSE;
-            }
-        }
+        ok = EmitDelete(cx, bce, pn);
         break;
 
 #if JS_HAS_XML_SUPPORT
       case PNK_FILTER:
         JS_ASSERT(!bce->inStrictMode());
 
         if (!EmitTree(cx, bce, pn->pn_left))
             return JS_FALSE;
@@ -6881,99 +7272,18 @@ frontend::EmitTree(JSContext *cx, Byteco
          * push its value.  Set the "obj" register to the result of ToObject
          * on the left operand.
          */
         ok = EmitElemOp(cx, pn, pn->getOp(), bce);
         break;
 
       case PNK_NEW:
       case PNK_LP:
-      {
-        bool callop = pn->isKind(PNK_LP);
-
-        /*
-         * Emit callable invocation or operator new (constructor call) code.
-         * First, emit code for the left operand to evaluate the callable or
-         * constructable object expression.
-         *
-         * For operator new applied to other expressions than E4X ones, we emit
-         * JSOP_GETPROP instead of JSOP_CALLPROP, etc. This is necessary to
-         * interpose the lambda-initialized method read barrier -- see the code
-         * in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP.
-         *
-         * Then (or in a call case that has no explicit reference-base
-         * object) we emit JSOP_PUSH to produce the |this| slot required
-         * for calls (which non-strict mode functions will box into the
-         * global object).
-         */
-        pn2 = pn->pn_head;
-        switch (pn2->getKind()) {
-          case PNK_NAME:
-            if (!EmitNameOp(cx, bce, pn2, callop))
-                return JS_FALSE;
-            break;
-          case PNK_DOT:
-            if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
-                return JS_FALSE;
-            break;
-          case PNK_LB:
-            JS_ASSERT(pn2->isOp(JSOP_GETELEM));
-            if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce))
-                return JS_FALSE;
-            break;
-#if JS_HAS_XML_SUPPORT
-          case PNK_XMLUNARY:
-            JS_ASSERT(pn2->isOp(JSOP_XMLNAME));
-            if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, bce))
-                return JS_FALSE;
-            callop = true;          /* suppress JSOP_PUSH after */
-            break;
-#endif
-          default:
-            if (!EmitTree(cx, bce, pn2))
-                return JS_FALSE;
-            callop = false;             /* trigger JSOP_PUSH after */
-            break;
-        }
-        if (!callop && Emit1(cx, bce, JSOP_PUSH) < 0)
-            return JS_FALSE;
-
-        /* Remember start of callable-object bytecode for decompilation hint. */
-        off = top;
-
-        /*
-         * Emit code for each argument in order, then emit the JSOP_*CALL or
-         * JSOP_NEW bytecode with a two-byte immediate telling how many args
-         * were pushed on the operand stack.
-         */
-        uintN oldflags = bce->flags;
-        bce->flags &= ~TCF_IN_FOR_INIT;
-        for (pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
-            if (!EmitTree(cx, bce, pn3))
-                return JS_FALSE;
-        }
-        bce->flags |= oldflags & TCF_IN_FOR_INIT;
-        if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
-            return JS_FALSE;
-
-        argc = pn->pn_count - 1;
-        if (Emit3(cx, bce, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0)
-            return JS_FALSE;
-        CheckTypeSet(cx, bce, pn->getOp());
-        if (pn->isOp(JSOP_EVAL)) {
-            EMIT_UINT16_IMM_OP(JSOP_LINENO, pn->pn_pos.begin.lineno);
-            if (EmitBlockChain(cx, bce) < 0)
-                return JS_FALSE;
-        }
-        if (pn->pn_xflags & PNX_SETCALL) {
-            if (Emit1(cx, bce, JSOP_SETCALL) < 0)
-                return JS_FALSE;
-        }
+        ok = EmitCallOrNew(cx, bce, pn, top);
         break;
-      }
 
       case PNK_LEXICALSCOPE:
         ok = EmitLexicalScope(cx, bce, pn);
         break;
 
 #if JS_HAS_BLOCK_SCOPE
       case PNK_LET:
         if (!EmitLet(cx, bce, pn))
@@ -6998,251 +7308,42 @@ frontend::EmitTree(JSContext *cx, Byteco
         break;
       }
 #endif
 
       case PNK_RB:
 #if JS_HAS_GENERATORS
       case PNK_ARRAYCOMP:
 #endif
-        /*
-         * Emit code for [a, b, c] that is equivalent to constructing a new
-         * array and in source order evaluating each element value and adding
-         * it to the array, without invoking latent setters.  We use the
-         * JSOP_NEWINIT and JSOP_INITELEM bytecodes to ignore setters and to
-         * avoid dup'ing and popping the array as each element is added, as
-         * JSOP_SETELEM/JSOP_SETPROP would do.
-         */
-#if JS_HAS_SHARP_VARS
-        sharpnum = -1;
-      do_emit_array:
-#endif
-
-#if JS_HAS_GENERATORS
-        if (pn->isKind(PNK_ARRAYCOMP)) {
-            uintN saveDepth;
-
-            if (!EmitNewInit(cx, bce, JSProto_Array, pn, sharpnum))
-                return JS_FALSE;
-
-            /*
-             * Pass the new array's stack index to the PNK_ARRAYPUSH case via
-             * bce->arrayCompDepth, then simply traverse the PNK_FOR node and
-             * its kids under pn2 to generate this comprehension.
-             */
-            JS_ASSERT(bce->stackDepth > 0);
-            saveDepth = bce->arrayCompDepth;
-            bce->arrayCompDepth = (uint32) (bce->stackDepth - 1);
-            if (!EmitTree(cx, bce, pn->pn_head))
-                return JS_FALSE;
-            bce->arrayCompDepth = saveDepth;
-
-            /* Emit the usual op needed for decompilation. */
-            if (!EmitEndInit(cx, bce, 1))
-                return JS_FALSE;
-            break;
-        }
-#endif /* JS_HAS_GENERATORS */
-
-        if (!bce->hasSharps() && !(pn->pn_xflags & PNX_NONCONST) && pn->pn_head &&
-            bce->checkSingletonContext()) {
-            if (!EmitSingletonInitialiser(cx, bce, pn))
-                return JS_FALSE;
-            break;
-        }
-
-        /* Use the slower NEWINIT for arrays in scripts containing sharps. */
-        if (bce->hasSharps()) {
-            if (!EmitNewInit(cx, bce, JSProto_Array, pn, sharpnum))
-                return JS_FALSE;
-        } else {
-            ptrdiff_t off = EmitN(cx, bce, JSOP_NEWARRAY, 3);
-            if (off < 0)
-                return JS_FALSE;
-            pc = bce->code(off);
-            SET_UINT24(pc, pn->pn_count);
-        }
-
-        pn2 = pn->pn_head;
-        for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
-            if (!EmitNumberOp(cx, atomIndex, bce))
-                return JS_FALSE;
-            if (pn2->isKind(PNK_COMMA) && pn2->isArity(PN_NULLARY)) {
-                if (Emit1(cx, bce, JSOP_HOLE) < 0)
-                    return JS_FALSE;
-            } else {
-                if (!EmitTree(cx, bce, pn2))
-                    return JS_FALSE;
-            }
-            if (Emit1(cx, bce, JSOP_INITELEM) < 0)
-                return JS_FALSE;
-        }
-        JS_ASSERT(atomIndex == pn->pn_count);
-
-        if (pn->pn_xflags & PNX_ENDCOMMA) {
-            /* Emit a source note so we know to decompile an extra comma. */
-            if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
-                return JS_FALSE;
-        }
-
-        /*
-         * Emit an op to finish the array and, secondarily, to aid in sharp
-         * array cleanup (if JS_HAS_SHARP_VARS) and decompilation.
-         */
-        if (!EmitEndInit(cx, bce, atomIndex))
-            return JS_FALSE;
+        ok = EmitArray(cx, bce, pn, -1);
         break;
 
-      case PNK_RC: {
-#if JS_HAS_SHARP_VARS
-        sharpnum = -1;
-      do_emit_object:
-#endif
-#if JS_HAS_DESTRUCTURING_SHORTHAND
-        if (pn->pn_xflags & PNX_DESTRUCT) {
-            ReportCompileErrorNumber(cx, bce->tokenStream(), pn, JSREPORT_ERROR,
-                                     JSMSG_BAD_OBJECT_INIT);
-            return JS_FALSE;
-        }
-#endif
-
-        if (!bce->hasSharps() && !(pn->pn_xflags & PNX_NONCONST) && pn->pn_head &&
-            bce->checkSingletonContext()) {
-            if (!EmitSingletonInitialiser(cx, bce, pn))
-                return JS_FALSE;
-            break;
-        }
-
-        /*
-         * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
-         * a new object and in source order evaluating each property value and
-         * adding the property to the object, without invoking latent setters.
-         * We use the JSOP_NEWINIT and JSOP_INITELEM/JSOP_INITPROP bytecodes to
-         * ignore setters and to avoid dup'ing and popping the object as each
-         * property is added, as JSOP_SETELEM/JSOP_SETPROP would do.
-         */
-        ptrdiff_t offset = bce->next() - bce->base();
-        if (!EmitNewInit(cx, bce, JSProto_Object, pn, sharpnum))
-            return JS_FALSE;
-
-        /*
-         * Try to construct the shape of the object as we go, so we can emit a
-         * JSOP_NEWOBJECT with the final shape instead.
-         */
-        JSObject *obj = NULL;
-        if (!bce->hasSharps() && bce->compileAndGo()) {
-            gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
-            obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
-            if (!obj)
-                return JS_FALSE;
-        }
-
-        uintN methodInits = 0, slowMethodInits = 0;
-        for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
-            /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
-            pn3 = pn2->pn_left;
-            if (pn3->isKind(PNK_NUMBER)) {
-                if (!EmitNumberOp(cx, pn3->pn_dval, bce))
-                    return JS_FALSE;
-            }
-
-            /* Emit code for the property initializer. */
-            if (!EmitTree(cx, bce, pn2->pn_right))
-                return JS_FALSE;
-
-            op = pn2->getOp();
-            if (op == JSOP_GETTER || op == JSOP_SETTER) {
-                obj = NULL;
-                if (Emit1(cx, bce, op) < 0)
-                    return JS_FALSE;
-            }
-
-            /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */
-            if (pn3->isKind(PNK_NUMBER)) {
-                obj = NULL;
-                if (NewSrcNote(cx, bce, SRC_INITPROP) < 0)
-                    return JS_FALSE;
-                if (Emit1(cx, bce, JSOP_INITELEM) < 0)
-                    return JS_FALSE;
-            } else {
-                JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
-                jsatomid index;
-                if (!bce->makeAtomIndex(pn3->pn_atom, &index))
-                    return JS_FALSE;
-
-                /* Check whether we can optimize to JSOP_INITMETHOD. */
-                ParseNode *init = pn2->pn_right;
-                bool lambda = init->isOp(JSOP_LAMBDA);
-                if (lambda)
-                    ++methodInits;
-                if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) {
-                    obj = NULL;
-                    op = JSOP_INITMETHOD;
-                    pn2->setOp(op);
-                    if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
-                        return JS_FALSE;
-                } else {
-                    /*
-                     * Disable NEWOBJECT on initializers that set __proto__, which has
-                     * a non-standard setter on objects.
-                     */
-                    if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
-                        obj = NULL;
-                    op = JSOP_INITPROP;
-                    if (lambda)
-                        ++slowMethodInits;
-                }
-
-                if (obj) {
-                    JS_ASSERT(!obj->inDictionaryMode());
-                    if (!DefineNativeProperty(cx, obj, ATOM_TO_JSID(pn3->pn_atom),
-                                              UndefinedValue(), NULL, NULL,
-                                              JSPROP_ENUMERATE, 0, 0)) {
-                        return false;
-                    }
-                    if (obj->inDictionaryMode())
-                        obj = NULL;
-                }
-
-                EMIT_INDEX_OP(op, index);
-            }
-        }
-
-        if (!EmitEndInit(cx, bce, pn->pn_count))
-            return JS_FALSE;
-
-        if (obj) {
-            /*
-             * The object survived and has a predictable shape.  Update the original bytecode,
-             * as long as we can do so without using a big index prefix/suffix.
-             */
-            ObjectBox *objbox = bce->parser->newObjectBox(obj);
-            if (!objbox)
-                return JS_FALSE;
-            unsigned index = bce->objectList.index(objbox);
-            if (FitsWithoutBigIndex(index))
-                EMIT_UINT16_IN_PLACE(offset, JSOP_NEWOBJECT, uint16(index));
-        }
-
+      case PNK_RC:
+        ok = EmitObject(cx, bce, pn, -1);
         break;
-      }
 
 #if JS_HAS_SHARP_VARS
       case PNK_DEFSHARP:
         JS_ASSERT(bce->hasSharps());
         sharpnum = pn->pn_num;
         pn = pn->pn_kid;
-        if (pn->isKind(PNK_RB))
-            goto do_emit_array;
+        if (pn->isKind(PNK_RB)) {
+            ok = EmitArray(cx, bce, pn, sharpnum);
+            break;
+        }
 # if JS_HAS_GENERATORS
-        if (pn->isKind(PNK_ARRAYCOMP))
-            goto do_emit_array;
+        if (pn->isKind(PNK_ARRAYCOMP)) {
+            ok = EmitArray(cx, bce, pn, sharpnum);
+            break;
+        }
 # endif
-        if (pn->isKind(PNK_RC))
-            goto do_emit_object;
+        if (pn->isKind(PNK_RC)) {
+            ok = EmitObject(cx, bce, pn, sharpnum);
+            break;
+        }
 
         if (!EmitTree(cx, bce, pn))
             return JS_FALSE;
         EMIT_UINT16PAIR_IMM_OP(JSOP_DEFSHARP, bce->sharpSlotBase, (jsatomid) sharpnum);
         break;
 
       case PNK_USESHARP:
         JS_ASSERT(bce->hasSharps());
--- a/js/src/jit-test/jit_test.py
+++ b/js/src/jit-test/jit_test.py
@@ -45,26 +45,24 @@ os.path.relpath = _relpath
 class Test:
     def __init__(self, path):
         self.path = path       # path to test file
         
         self.jitflags = []     # jit flags to enable
         self.slow = False      # True means the test is slow-running
         self.allow_oom = False # True means that OOM is not considered a failure
         self.valgrind = False  # True means run under valgrind
-        self.tmflags = ''      # Value of TMFLAGS env var to pass
         self.error = ''        # Errors to expect and consider passing
 
     def copy(self):
         t = Test(self.path)
         t.jitflags = self.jitflags[:]
         t.slow = self.slow
         t.allow_oom = self.allow_oom
         t.valgrind = self.valgrind
-        t.tmflags = self.tmflags
         t.error = self.error
         return t
 
     COOKIE = '|jit-test|'
 
     @classmethod
     def from_file(cls, path, options):
         test = cls(path)
@@ -76,19 +74,17 @@ class Test:
             parts = meta.split(';')
             for part in parts:
                 part = part.strip()
                 if not part:
                     continue
                 name, _, value = part.partition(':')
                 if value:
                     value = value.strip()
-                    if name == 'TMFLAGS':
-                        test.tmflags = value
-                    elif name == 'error':
+                    if name == 'error':
                         test.error = value
                     else:
                         print('warning: unrecognized |jit-test| attribute %s'%part)
                 else:
                     if name == 'slow':
                         test.slow = True
                     elif name == 'allow-oom':
                         test.allow_oom = True
@@ -196,19 +192,16 @@ def run_cmd(cmdline, env, timeout):
 def run_cmd_avoid_stdio(cmdline, env, timeout):
     stdoutPath, stderrPath = tmppath('jsstdout'), tmppath('jsstderr')
     env['JS_STDOUT'] = stdoutPath
     env['JS_STDERR'] = stderrPath       
     _, __, code = run_timeout_cmd(cmdline, { 'env': env }, timeout)
     return read_and_unlink(stdoutPath), read_and_unlink(stderrPath), code
 
 def run_test(test, lib_dir, shell_args):
-    env = os.environ.copy()
-    if test.tmflags:
-        env['TMFLAGS'] = test.tmflags
     cmd = get_test_cmd(test.path, test.jitflags, lib_dir, shell_args)
 
     if (test.valgrind and