Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 23 Jun 2012 08:35:25 -0400
changeset 99078 87e239ca45c65753eaf4e6c0f6c451cf420bd9f3
parent 99076 879b2a08107a70eb6a37ff8196a67ebf4f346b91 (current diff)
parent 99077 53d0ad70087b0796e89f59bac8ba3b8e5fd8c670 (diff)
child 99079 51bda50648bc21f5bf73fd5cf046bdd860551248
push idunknown
push userunknown
push dateunknown
milestone16.0a1
Merge the last PGO-green inbound changeset to m-c.
browser/components/migration/src/MigrationUtils.jsm
browser/components/tabview/ui.js
browser/modules/WebappsInstaller.jsm
browser/modules/webappsUI.jsm
browser/themes/gnomestripe/browser.css
browser/themes/gnomestripe/identity-icons-https-mixed.png
browser/themes/gnomestripe/jar.mn
browser/themes/pinstripe/browser.css
browser/themes/pinstripe/identity-icons-https-mixed.png
browser/themes/pinstripe/jar.mn
browser/themes/winstripe/browser.css
browser/themes/winstripe/identity-icons-https-mixed.png
browser/themes/winstripe/jar.mn
build/autoconf/android.m4
build/mobile/sutagent/android/DoCommand.java
config/autoconf.mk.in
config/config.mk
config/rules.mk
configure.in
content/base/src/nsContentUtils.cpp
content/base/src/nsGkAtomList.h
content/base/test/file_bug416317.xhtml
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/events/src/nsDOMKeyboardEvent.cpp
content/events/src/nsEventStateManager.cpp
content/media/MediaStreamGraph.cpp
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/Configuration.py
dom/bindings/parser/WebIDL.py
dom/bindings/parser/tests/test_arraybuffer.py
dom/bindings/parser/tests/test_callback_interface.py
dom/bindings/parser/tests/test_distinguishability.py
dom/bindings/parser/tests/test_error_lineno.py
dom/bindings/parser/tests/test_implements.py
dom/bindings/parser/tests/test_overload.py
dom/bindings/test/Makefile.in
dom/indexedDB/IDBObjectStore.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/system/OSFileConstants.cpp
dom/workers/WorkerScope.cpp
extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
gfx/gl/GLContext.cpp
gfx/skia/include/utils/mac/SkCGUtils.h
gfx/skia/patches/0015-Bug-766017-warnings.patch
gfx/skia/patches/README
gfx/skia/src/core/SkAAClip.cpp
gfx/skia/src/core/SkBlitMask_D32.cpp
gfx/skia/src/core/SkConcaveToTriangles.cpp
gfx/skia/src/core/SkPath.cpp
gfx/skia/src/core/SkRegion.cpp
gfx/skia/src/core/SkScalerContext.cpp
gfx/skia/src/core/SkScan_AntiPath.cpp
gfx/skia/src/effects/SkGradientShader.cpp
gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
js/ductwork/debugger/JSDebugger.h
js/jsd/jsd_high.c
js/src/build/autoconf/android.m4
js/src/config/config.mk
js/src/config/rules.mk
js/src/configure.in
js/src/frontend/BytecodeEmitter.cpp
js/src/gc/Marking.cpp
js/src/gc/Statistics.cpp
js/src/jit-test/tests/basic/bug719750.js
js/src/jit-test/tests/basic/bug767234.js
js/src/jit-test/tests/basic/testBug766064.js
js/src/jit-test/tests/debug/Debugger-debuggees-11.js
js/src/jit-test/tests/debug/Object-seal-01.js
js/src/jit-test/tests/debug/gc-05.js
js/src/jsapi-tests/testBug604087.cpp
js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsfriendapi.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsinferinlines.h
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/shell/js.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/XPCWrappedNativeProto.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSRenderingBorders.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsIComboboxControlFrame.h
layout/forms/nsIListControlFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/reftests/bugs/621253-1-ref.html
layout/reftests/bugs/reftest.list
layout/reftests/svg/reftest.list
layout/reftests/transform/reftest.list
layout/style/nsCSSParser.cpp
layout/svg/base/src/nsSVGEffects.cpp
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterFrame.h
layout/svg/base/src/nsSVGIntegrationUtils.cpp
layout/xul/base/public/nsXULPopupManager.h
layout/xul/base/src/nsMenuPopupFrame.cpp
media/webrtc/Android.mk
mobile/android/base/AwesomeBar.java
mobile/android/base/BrowserApp.java
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Tab.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/menu-sw600dp/gecko_menu.xml.in
mobile/android/base/resources/menu-v11/gecko_menu.xml.in
mobile/android/base/resources/menu-xlarge/gecko_menu.xml.in
mobile/android/base/resources/menu/gecko_menu.xml.in
mobile/android/base/strings.xml.in
mobile/android/base/tests/MotionEventHelper.java.in
mobile/android/base/tests/PixelTest.java.in
mobile/android/base/tests/robocop.ini
mobile/android/chrome/content/aboutReader.js
mobile/android/chrome/content/browser.js
mobile/android/locales/en-US/chrome/aboutReader.properties
mobile/android/themes/core/aboutReader.css
mobile/android/themes/core/images/reader-dark-bg.png
mobile/android/themes/core/images/reader-dropdown-arrow-hdpi.png
mobile/android/themes/core/images/reader-dropdown-arrow-mdpi.png
mobile/android/themes/core/images/reader-dropdown-arrow-xhdpi.png
mobile/android/themes/core/images/reader-dropdown-arrow.png
mobile/android/themes/core/images/reader-light-bg.png
mobile/android/themes/core/images/reader-minus-icon-hdpi.png
mobile/android/themes/core/images/reader-minus-icon-mdpi.png
mobile/android/themes/core/images/reader-minus-icon-xhdpi.png
mobile/android/themes/core/images/reader-plus-icon-hdpi.png
mobile/android/themes/core/images/reader-plus-icon-mdpi.png
mobile/android/themes/core/images/reader-plus-icon-xhdpi.png
mobile/android/themes/core/images/reader-sepia-bg.png
mobile/android/themes/core/images/reader-share-icon-land-hdpi.png
mobile/android/themes/core/images/reader-share-icon-land-mdpi.png
mobile/android/themes/core/images/reader-share-icon-land-xhdpi.png
mobile/android/themes/core/images/reader-share-icon-port-hdpi.png
mobile/android/themes/core/images/reader-share-icon-port-mdpi.png
mobile/android/themes/core/images/reader-share-icon-port-xhdpi.png
mobile/android/themes/core/images/reader-share-icon-xlarge-hdpi.png
mobile/android/themes/core/images/reader-share-icon-xlarge-mdpi.png
mobile/android/themes/core/images/reader-share-icon-xlarge-xhdpi.png
mobile/android/themes/core/images/reader-style-icon-land-hdpi.png
mobile/android/themes/core/images/reader-style-icon-land-mdpi.png
mobile/android/themes/core/images/reader-style-icon-land-xhdpi.png
mobile/android/themes/core/images/reader-style-icon-port-hdpi.png
mobile/android/themes/core/images/reader-style-icon-port-mdpi.png
mobile/android/themes/core/images/reader-style-icon-port-xhdpi.png
mobile/android/themes/core/images/reader-style-icon-xlarge-hdpi.png
mobile/android/themes/core/images/reader-style-icon-xlarge-mdpi.png
mobile/android/themes/core/images/reader-style-icon-xlarge-xhdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-land-hdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-land-mdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-land-xhdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-port-hdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-port-mdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-port-xhdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-xlarge-hdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-xlarge-mdpi.png
mobile/android/themes/core/images/reader-toolbar-bg-xlarge-xhdpi.png
mobile/android/themes/core/jar.mn
netwerk/dns/effective_tld_names.dat
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/websocket/WebSocketChannel.cpp
startupcache/test/TestStartupCache.cpp
toolkit/components/maintenanceservice/serviceinstall.cpp
toolkit/components/osfile/osfile_shared.jsm
toolkit/components/osfile/osfile_win_front.jsm
toolkit/components/telemetry/Telemetry.cpp
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
toolkit/content/aboutSupport.js
webapprt/CommandLineHandler.js
widget/cocoa/nsChildView.mm
widget/gtk2/nsWindow.cpp
widget/nsIRollupListener.h
widget/os2/nsWindow.cpp
widget/qt/nsWindow.cpp
widget/windows/nsWindow.cpp
widget/xpwidgets/nsBaseWidget.h
xpcom/base/ClearOnShutdown.h
xpcom/stub/Makefile.in
xpcom/stub/dependentlibs.py
--- a/browser/components/migration/src/MigrationUtils.jsm
+++ b/browser/components/migration/src/MigrationUtils.jsm
@@ -261,27 +261,24 @@ let MigratorPrototype = {
       // from another profile.
       const BOOKMARKS = MigrationUtils.resourceTypes.BOOKMARKS;
       let migratingBookmarks = resources.some(function(r) r.type == BOOKMARKS);
       if (migratingBookmarks) {
         let browserGlue = Cc["@mozilla.org/browser/browserglue;1"].
                           getService(Ci.nsIObserver);
         browserGlue.observe(null, TOPIC_WILL_IMPORT_BOOKMARKS, "");
 
-        let bookmarksHTMLFile = Services.dirsvc.get("BMarks", Ci.nsIFile);
-        if (bookmarksHTMLFile.exists()) {
-          // Note doMigrate doesn't care about the success value of the
-          // callback.
-          BookmarkHTMLUtils.importFromURL(
-            NetUtil.newURI(bookmarksHTMLFile).spec, true, function(a) {
-              browserGlue.observe(null, TOPIC_DID_IMPORT_BOOKMARKS, "");
-              doMigrate();
-            });
-          return;
-        }
+        // Note doMigrate doesn't care about the success value of the
+        // callback.
+        BookmarkHTMLUtils.importFromURL(
+          "resource:///defaults/profile/bookmarks.html", true, function(a) {
+            browserGlue.observe(null, TOPIC_DID_IMPORT_BOOKMARKS, "");
+            doMigrate();
+          });
+        return;
       }
     }
     doMigrate();
   },
 
   /**
    * DO NOT OVERRIDE - After deCOMing migration, this code
    * won't be part of the migrator itself.
--- a/browser/components/tabview/ui.js
+++ b/browser/components/tabview/ui.js
@@ -245,19 +245,16 @@ let UI = {
       this._frameInitialized = true;
       this._save();
 
       // fire an iframe initialized event so everyone knows tab view is 
       // initialized.
       let event = document.createEvent("Events");
       event.initEvent("tabviewframeinitialized", true, false);
       dispatchEvent(event);
-
-      // XXX this can be removed when bug 731868 is fixed
-      event = null;
     } catch(e) {
       Utils.log(e);
     } finally {
       GroupItems.resumeArrange();
     }
   },
 
   // Function: uninit
--- a/browser/modules/WebappsInstaller.jsm
+++ b/browser/modules/WebappsInstaller.jsm
@@ -37,20 +37,20 @@ let WebappsInstaller = {
 #else
     return false;
 #endif
 
     try {
       shell.install();
     } catch (ex) {
       Cu.reportError("Error installing app: " + ex);
-      return false;
+      return null;
     }
 
-    return true;
+    return shell;
   }
 }
 
 /**
  * This function implements the common constructor for
  * the Windows, Mac and Linux native app shells. It reads and parses
  * the data from the app manifest and stores it in the NativeApp
  * object. It's meant to be called as NativeApp.call(this, aData)
@@ -102,36 +102,40 @@ function NativeApp(aData) {
   if (app.manifest.description) {
     let firstLine = app.manifest.description.split("\n")[0];
     shortDesc = firstLine.length <= 256
                 ? firstLine
                 : firstLine.substr(0, 253) + "...";
   }
   this.shortDescription = sanitize(shortDesc);
 
+  this.appcacheDefined = (app.manifest.appcache_path != undefined);
+
   this.manifest = app.manifest;
 
-  this.profileFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
+  // The app registry is the Firefox profile from which the app
+  // was installed.
+  this.registryFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
 
   this.webappJson = {
-    "registryDir": this.profileFolder.path,
+    "registryDir": this.registryFolder.path,
     "app": app
   };
 
   this.runtimeFolder = Services.dirsvc.get("GreD", Ci.nsIFile);
 }
 
 #ifdef XP_WIN
 /*************************************
  * Windows app installer
  *
  * The Windows installation process will generate the following files:
  *
- * ${FolderName} = app-origin;protocol;port
- *                 e.g.: subdomain.example.com;http;-1
+ * ${FolderName} = protocol;app-origin[;port]
+ *                 e.g.: subdomain.example.com;http;85
  *
  * %APPDATA%/${FolderName}
  *   - webapp.ini
  *   - webapp.json
  *   - ${AppName}.exe
  *   - ${AppName}.lnk
  *   / uninstall
  *     - webapp-uninstaller.exe
@@ -165,16 +169,17 @@ WinNativeApp.prototype = {
     this._removeInstallation();
 
     try {
       this._createDirectoryStructure();
       this._copyPrebuiltFiles();
       this._createConfigFiles();
       this._createShortcutFiles();
       this._writeSystemKeys();
+      this._createAppProfile();
     } catch (ex) {
       this._removeInstallation();
       throw(ex);
     }
 
     getIconForApp(this, function() {});
   },
 
@@ -186,18 +191,18 @@ WinNativeApp.prototype = {
     let filenameRE = new RegExp("[<>:\"/\\\\|\\?\\*]", "gi");
 
     this.appNameAsFilename = this.appNameAsFilename.replace(filenameRE, "");
     if (this.appNameAsFilename == "") {
       this.appNameAsFilename = "webapp";
     }
 
     // The ${InstallDir} format is as follows:
-    //  host of the app origin + ";" +
     //  protocol
+    //  + ";" + host of the app origin
     //  + ";" + port (only if port is not default)
     this.installDir = Services.dirsvc.get("AppData", Ci.nsIFile);
     let installDirLeaf = this.launchURI.scheme
                        + ";"
                        + this.launchURI.host;
     if (this.launchURI.port != -1) {
       installDirLeaf += ";" + this.launchURI.port;
     }
@@ -276,16 +281,30 @@ WinNativeApp.prototype = {
    * Creates the main directory structure.
    */
   _createDirectoryStructure: function() {
     this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
     this.uninstallDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
   },
 
   /**
+   * Creates the profile to be used for this app.
+   */
+  _createAppProfile: function() {
+    if (!this.appcacheDefined)
+      return;
+
+    let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
+                    .getService(Ci.nsIToolkitProfileService);
+
+    this.appProfile = profSvc.createDefaultProfileForApp(this.installDir.leafName,
+                                                         null, null);
+  },
+
+  /**
    * Copy the pre-built files into their destination folders.
    */
   _copyPrebuiltFiles: function() {
     let webapprt = this.runtimeFolder.clone();
     webapprt.append("webapprt-stub.exe");
     webapprt.copyTo(this.installDir, this.appNameAsFilename + ".exe");
 
     let uninstaller = this.runtimeFolder.clone();
@@ -490,16 +509,17 @@ MacNativeApp.prototype = {
   },
 
   install: function() {
     this._removeInstallation(true);
     try {
       this._createDirectoryStructure();
       this._copyPrebuiltFiles();
       this._createConfigFiles();
+      this._createAppProfile();
     } catch (ex) {
       this._removeInstallation(false);
       throw(ex);
     }
 
     getIconForApp(this, this._moveToApplicationsFolder);
   },
 
@@ -528,16 +548,27 @@ MacNativeApp.prototype = {
     if (!this.appProfileDir.exists())
       this.appProfileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
 
     this.contentsDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
     this.macOSDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
     this.resourcesDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
   },
 
+  _createAppProfile: function() {
+    if (!this.appcacheDefined)
+      return;
+
+    let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
+                    .getService(Ci.nsIToolkitProfileService);
+
+    this.appProfile = profSvc.createDefaultProfileForApp(this.appProfileDir.leafName,
+                                                         null, null);
+  },
+
   _copyPrebuiltFiles: function() {
     let webapprt = this.runtimeFolder.clone();
     webapprt.append("webapprt-stub");
     webapprt.copyTo(this.macOSDir, "webapprt");
   },
 
   _createConfigFiles: function() {
     // ${ProfileDir}/webapp.json
@@ -690,16 +721,17 @@ LinuxNativeApp.prototype = {
 
   install: function() {
     this._removeInstallation();
 
     try {
       this._createDirectoryStructure();
       this._copyPrebuiltFiles();
       this._createConfigFiles();
+      this._createAppProfile();
     } catch (ex) {
       this._removeInstallation();
       throw(ex);
     }
 
     getIconForApp(this, function() {});
   },
 
@@ -719,16 +751,27 @@ LinuxNativeApp.prototype = {
   },
 
   _copyPrebuiltFiles: function() {
     let webapprtPre = this.runtimeFolder.clone();
     webapprtPre.append(this.webapprt.leafName);
     webapprtPre.copyTo(this.installDir, this.webapprt.leafName);
   },
 
+  _createAppProfile: function() {
+    if (!this.appcacheDefined)
+      return;
+
+    let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
+                    .getService(Ci.nsIToolkitProfileService);
+
+    return profSvc.createDefaultProfileForApp(this.installDir.leafName,
+                                              null, null);
+  },
+
   _createConfigFiles: function() {
     // ${InstallDir}/webapp.json
     let configJson = this.installDir.clone();
     configJson.append("webapp.json");
     writeToFile(configJson, JSON.stringify(this.webappJson), function() {});
 
     // ${InstallDir}/webapp.ini
     let webappINI = this.installDir.clone();
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -104,18 +104,24 @@ let webappsUI = {
 
   doInstall: function(aData, aBrowser, aWindow) {
     let bundle = aWindow.gNavigatorBundle;
 
     let mainAction = {
       label: bundle.getString("webapps.install"),
       accessKey: bundle.getString("webapps.install.accesskey"),
       callback: function(notification) {
-        if (WebappsInstaller.install(aData)) {
-          DOMApplicationRegistry.confirmInstall(aData);
+        let app = WebappsInstaller.install(aData);
+        if (app) {
+          let localDir = null;
+          if (app.appcacheDefined && app.appProfile) {
+            localDir = app.appProfile.localDir;
+          }
+
+          DOMApplicationRegistry.confirmInstall(aData, false, localDir);
         } else {
           DOMApplicationRegistry.denyInstall(aData);
         }
       }
     };
 
     let requestingURI = aWindow.makeURI(aData.from);
     let manifest = new DOMApplicationManifest(aData.app.manifest, aData.app.origin);
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1004,20 +1004,16 @@ toolbar[iconsize="small"] #feed-button {
 .verifiedDomain > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https.png);
 }
 
 .verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
 }
 
-.mixedContent > #page-proxy-favicon[pageproxystate="valid"] {
-  list-style-image: url(chrome://browser/skin/identity-icons-https-mixed.png);
-}
-
 #identity-box:hover > #page-proxy-favicon {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #identity-box:hover:active > #page-proxy-favicon,
 #identity-box[open=true] > #page-proxy-favicon {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
deleted file mode 100644
index 23890a82faf4d3590c8bbf834a210915545afb4d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -21,17 +21,16 @@ browser.jar:
 * skin/classic/browser/engineManager.css              (engineManager.css)
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-64.png
   skin/classic/browser/Go-arrow.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity-icons-generic.png
   skin/classic/browser/identity-icons-https.png
   skin/classic/browser/identity-icons-https-ev.png
-  skin/classic/browser/identity-icons-https-mixed.png
   skin/classic/browser/Info.png
   skin/classic/browser/KUI-close.png
   skin/classic/browser/monitor.png
   skin/classic/browser/monitor_16-10.png
 * skin/classic/browser/pageInfo.css
   skin/classic/browser/pageInfo.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/Privacy-16.png
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -1061,20 +1061,16 @@ toolbar[mode="icons"] #zoom-in-button {
 .verifiedDomain > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https.png);
 }
 
 .verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
 }
 
-.mixedContent > #page-proxy-favicon[pageproxystate="valid"] {
-  list-style-image: url(chrome://browser/skin/identity-icons-https-mixed.png);
-}
-
 #identity-box:hover:active > #page-proxy-favicon,
 #identity-box[open=true] > #page-proxy-favicon {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.3;
 }
deleted file mode 100644
index caf6097c40a068748063798fa116735d633d20e3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -27,17 +27,16 @@ browser.jar:
   skin/classic/browser/hud-style-expander-closed.png
   skin/classic/browser/hud-style-expander-open.png
   skin/classic/browser/hud-style-new-folder-plus-sign.png
   skin/classic/browser/hud-style-twisties.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity-icons-generic.png
   skin/classic/browser/identity-icons-https.png
   skin/classic/browser/identity-icons-https-ev.png
-  skin/classic/browser/identity-icons-https-mixed.png
   skin/classic/browser/Info.png
   skin/classic/browser/KUI-background.png
   skin/classic/browser/KUI-close.png
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/pageInfo.css
   skin/classic/browser/Privacy-16.png
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1440,20 +1440,16 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
 .verifiedDomain > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https.png);
 }
 
 .verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] {
   list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
 }
 
-.mixedContent > #page-proxy-favicon[pageproxystate="valid"] {
-  list-style-image: url(chrome://browser/skin/identity-icons-https-mixed.png);
-}
-
 #identity-box:hover > #page-proxy-favicon {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #identity-box:hover:active > #page-proxy-favicon,
 #identity-box[open=true] > #page-proxy-favicon {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
deleted file mode 100644
index 23890a82faf4d3590c8bbf834a210915545afb4d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -27,17 +27,16 @@ browser.jar:
         skin/classic/browser/Geolocation-64.png
         skin/classic/browser/webapps-16.png
         skin/classic/browser/webapps-64.png
         skin/classic/browser/Info.png                                (Info.png)
         skin/classic/browser/identity.png                            (identity.png)
         skin/classic/browser/identity-icons-generic.png
         skin/classic/browser/identity-icons-https.png
         skin/classic/browser/identity-icons-https-ev.png
-        skin/classic/browser/identity-icons-https-mixed.png
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/KUI-close.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png                            (pageInfo.png)
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
         skin/classic/browser/livemark-folder.png                     (livemark-folder.png)
         skin/classic/browser/Privacy-16.png
@@ -225,17 +224,16 @@ browser.jar:
         skin/classic/aero/browser/Geolocation-64.png
         skin/classic/aero/browser/webapps-16.png
         skin/classic/aero/browser/webapps-64.png
         skin/classic/aero/browser/Info.png                           (Info-aero.png)
         skin/classic/aero/browser/identity.png                       (identity-aero.png)
         skin/classic/aero/browser/identity-icons-generic.png
         skin/classic/aero/browser/identity-icons-https.png
         skin/classic/aero/browser/identity-icons-https-ev.png
-        skin/classic/aero/browser/identity-icons-https-mixed.png
         skin/classic/aero/browser/keyhole-forward-mask.svg
         skin/classic/aero/browser/KUI-background.png
         skin/classic/aero/browser/KUI-close.png
         skin/classic/aero/browser/pageInfo.css
         skin/classic/aero/browser/pageInfo.png                       (pageInfo-aero.png)
         skin/classic/aero/browser/page-livemarks.png                 (feeds/feedIcon16-aero.png)
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
--- a/build/autoconf/android.m4
+++ b/build/autoconf/android.m4
@@ -93,16 +93,17 @@ case "$target" in
         if test -d "$android_platform" ; then
             AC_MSG_RESULT([$android_platform])
         else
             AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.])
         fi
     fi
 
     dnl set up compilers
+    TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-"
     AS="$android_toolchain"/bin/"$android_tool_prefix"-as
     CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc
     CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++
     CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp
     LD="$android_toolchain"/bin/"$android_tool_prefix"-ld
     AR="$android_toolchain"/bin/"$android_tool_prefix"-ar
     RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib
     STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -100,17 +100,17 @@ public class DoCommand {
 
     String    currentDir = "/";
     String    sErrorPrefix = "##AGENT-WARNING## ";
     boolean bTraceOn = false;
 
     String ffxProvider = "org.mozilla.ffxcp";
     String fenProvider = "org.mozilla.fencp";
 
-    private final String prgVersion = "SUTAgentAndroid Version 1.08";
+    private final String prgVersion = "SUTAgentAndroid Version 1.09";
 
     public enum Command
         {
         RUN ("run"),
         EXEC ("exec"),
         EXECCWD ("execcwd"),
         ENVRUN ("envrun"),
         KILL ("kill"),
@@ -157,16 +157,17 @@ public class DoCommand {
         QUIT ("quit"),
         EXIT ("exit"),
         HELP ("help"),
         FTPG ("ftpg"),
         FTPP ("ftpp"),
         INST ("inst"),
         UPDT ("updt"),
         UNINST ("uninst"),
+        UNINSTALL ("uninstall"),
         TEST ("test"),
         DBG ("dbg"),
         TRACE ("trace"),
         VER ("ver"),
         TZGET ("tzget"),
         TZSET ("tzset"),
         ADB ("adb"),
         CHMOD ("chmod"),
@@ -351,19 +352,26 @@ public class DoCommand {
                 if (Argc >= 2)
                     strReturn = InstallApp(Argv[1], cmdOut);
                 else
                     strReturn = sErrorPrefix + "Wrong number of arguments for inst command!";
                 break;
 
             case UNINST:
                 if (Argc >= 2)
-                    strReturn = UnInstallApp(Argv[1], cmdOut);
+                    strReturn = UnInstallApp(Argv[1], cmdOut, true);
                 else
-                    strReturn = sErrorPrefix + "Wrong number of arguments for inst command!";
+                    strReturn = sErrorPrefix + "Wrong number of arguments for uninst command!";
+                break;
+
+            case UNINSTALL:
+                if (Argc >= 2)
+                    strReturn = UnInstallApp(Argv[1], cmdOut, false);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for uninstall command!";
                 break;
 
             case ALRT:
                 if (Argc > 1)
                     {
                     if (Argv[1].contentEquals("on"))
                         {
                         String sTitle = "Agent Alert";
@@ -3110,23 +3118,27 @@ private void CancelNotification()
         theArgs[0] = "su";
         theArgs[1] = "-c";
         // as a security measure, ICS and later resets LD_LIBRARY_PATH. reset
         // it here when executing the command
         theArgs[2] = "LD_LIBRARY_PATH=/vendor/lib:/system/lib " + cmdString;
         return theArgs;
         }
 
-    public String UnInstallApp(String sApp, OutputStream out)
+    public String UnInstallApp(String sApp, OutputStream out, boolean reboot)
         {
         String sRet = "";
 
         try
             {
-            pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";reboot;exit"));
+            if (reboot == true) {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";reboot;exit"));
+            } else {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";exit"));
+            }
 
             RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
             outThrd.start();
             try {
                 outThrd.join(60000);
                 int nRet = pProc.exitValue();
                 sRet = "\nuninst complete [" + nRet + "]";
                 }
@@ -3757,17 +3769,18 @@ private void CancelNotification()
             "mems                         - dump memory stats\n" +
             "ls                           - print directory\n" +
             "tmpd                         - print temp directory\n" +
             "ping [hostname/ipaddr]       - ping a network device\n" +
             "unzp zipfile destdir         - unzip the zipfile into the destination dir\n" +
             "zip zipfile src              - zip the source file/dir into zipfile\n" +
             "rebt                         - reboot device\n" +
             "inst /path/filename.apk      - install the referenced apk file\n" +
-            "uninst packagename           - uninstall the referenced package\n" +
+            "uninst packagename           - uninstall the referenced package and reboot\n" +
+            "uninstall packagename        - uninstall the referenced package without a reboot\n" +
             "updt pkgname pkgfile         - unpdate the referenced package\n" +
             "clok                         - the current device time expressed as the" +
             "                               number of millisecs since epoch\n" +
             "settime date time            - sets the device date and time\n" +
             "                               (YYYY/MM/DD HH:MM:SS)\n" +
             "tzset timezone               - sets the device timezone format is\n" +
             "                               GMTxhh:mm x = +/- or a recognized Olsen string\n" +
             "tzget                        - returns the current timezone set on the device\n" +
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -352,16 +352,17 @@ ASM_SUFFIX	= @ASM_SUFFIX@
 IMPORT_LIB_SUFFIX = @IMPORT_LIB_SUFFIX@
 LIBS_DESC_SUFFIX = @LIBS_DESC_SUFFIX@
 USE_N32		= @USE_N32@
 HAVE_64BIT_OS	= @HAVE_64BIT_OS@
 
 CC		    = @CC@
 CXX		    = @CXX@
 CPP       = @CPP@
+TOOLCHAIN_PREFIX = @TOOLCHAIN_PREFIX@
 
 CC_VERSION	= @CC_VERSION@
 CXX_VERSION	= @CXX_VERSION@
 
 GNU_AS		= @GNU_AS@
 GNU_LD		= @GNU_LD@
 GNU_CC		= @GNU_CC@
 GNU_CXX		= @GNU_CXX@
--- a/config/config.mk
+++ b/config/config.mk
@@ -731,18 +731,18 @@ ifdef TIERS
 DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_dirs))
 STATIC_DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_staticdirs))
 endif
 
 OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
 
 CREATE_PRECOMPLETE_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/createprecomplete.py)
 
-EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py $(if $@,--depend $(MDDEPDIR)/$(basename $(@F)).pp --target $@)
-EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py $(if $@,--depend $(MDDEPDIR)/$(basename $(@F)).pp)
+EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp --target $@)
+EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp)
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -281,17 +281,17 @@ HOST_CMOBJS = $(addprefix host_,$(HOST_C
 HOST_CMMOBJS = $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
 ifndef HOST_OBJS
 _HOST_OBJS = $(HOST_COBJS) $(HOST_CCOBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
 HOST_OBJS = $(strip $(_HOST_OBJS))
 endif
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
-MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
+MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
 ifndef NO_GEN_XPT
 MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
 endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
--- a/configure.in
+++ b/configure.in
@@ -166,16 +166,17 @@ MOZ_ARG_WITH_STRING(gonk-toolchain-prefi
 
 if test -n "$gonkdir" ; then
     kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
     android_source="$gonkdir"
     ANDROID_SOURCE="$android_source"
     ANDROID_NDK="${ANDROID_SOURCE}/ndk"
 
     dnl set up compilers
+    TOOLCHAIN_PREFIX="$gonk_toolchain_prefix"
     AS="$gonk_toolchain_prefix"as
     CC="$gonk_toolchain_prefix"gcc
     CXX="$gonk_toolchain_prefix"g++
     CPP="$gonk_toolchain_prefix"cpp
     LD="$gonk_toolchain_prefix"ld
     AR="$gonk_toolchain_prefix"ar
     RANLIB="$gonk_toolchain_prefix"ranlib
     STRIP="$gonk_toolchain_prefix"strip
@@ -7757,17 +7758,17 @@ MOZ_ARG_DISABLE_BOOL(md,
      _cpp_md_flag=1
    fi
   dnl Default is to use -xM if using Sun Studio on Solaris
    if test "$SOLARIS_SUNPRO_CC"; then
      _cpp_md_flag=1
    fi])
 if test "$_cpp_md_flag"; then
   COMPILER_DEPEND=1
-  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(basename $(@F)).pp)'
+  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(@F).pp)'
   dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
   if test "$SOLARIS_SUNPRO_CC"; then
     _DEPEND_CFLAGS=
   fi
 else
   COMPILER_DEPEND=
   dnl Don't override this for MSVC
   if test -z "$_WIN32_MSVC"; then
@@ -8315,16 +8316,17 @@ AC_SUBST(MOZ_ETW)
 AC_SUBST(MOZ_PROFILING)
 AC_SUBST(LIBICONV)
 AC_SUBST(MOZ_PLACES)
 AC_SUBST(MOZ_TOOLKIT_SEARCH)
 AC_SUBST(MOZ_FEEDS)
 AC_SUBST(NS_PRINTING)
 AC_SUBST(MOZ_WEBGL)
 AC_SUBST(MOZ_HELP_VIEWER)
+AC_SUBST(TOOLCHAIN_PREFIX)
 
 AC_SUBST(JAVA)
 AC_SUBST(JAVAC)
 AC_SUBST(JAR)
 
 AC_SUBST(MOZ_PROFILELOCKING)
 
 AC_SUBST(ENABLE_TESTS)
@@ -8459,17 +8461,16 @@ AC_SUBST(MAR_CHANNEL_ID)
 AC_SUBST(ACCEPTED_MAR_CHANNEL_IDS)
 AC_SUBST(MOZ_PROFILE_MIGRATOR)
 AC_SUBST(MOZ_EXTENSION_MANAGER)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
 AC_SUBST(MOZ_APP_UA_NAME)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
 AC_SUBST(MOZ_APP_VERSION)
 AC_SUBST(MOZ_APP_MAXVERSION)
-AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
 AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
 AC_SUBST(FIREFOX_VERSION)
 
 # We can't use the static application.ini data when building against
 # a libxul SDK.
 if test -n "$LIBXUL_SDK"; then
     MOZ_APP_STATIC_INI=
 fi
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6246,16 +6246,22 @@ nsContentUtils::IsFocusedContent(const n
 bool
 nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
 {
   nsIDocument* doc = aContent->GetCurrentDoc();
   if (!doc) {
     return false;
   }
 
+  // If the subdocument lives in another process, the frame is
+  // tabbable.
+  if (nsEventStateManager::IsRemoteTarget(aContent)) {
+    return true;
+  }
+
   // XXXbz should this use OwnerDoc() for GetSubDocumentFor?
   // sXBL/XBL2 issue!
   nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
   if (!subDoc) {
     return false;
   }
 
   nsCOMPtr<nsISupports> container = subDoc->GetContainer();
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -196,23 +196,24 @@ GK_ATOM(combobox, "combobox")
 GK_ATOM(command, "command")
 GK_ATOM(commands, "commands")
 GK_ATOM(commandset, "commandset")
 GK_ATOM(commandupdate, "commandupdate")
 GK_ATOM(commandupdater, "commandupdater")
 GK_ATOM(comment, "comment")
 GK_ATOM(compact, "compact")
 GK_ATOM(concat, "concat")
-GK_ATOM(contenteditable, "contenteditable")
 GK_ATOM(conditions, "conditions")
 GK_ATOM(constructor, "constructor")
+GK_ATOM(consumeoutsideclicks, "consumeoutsideclicks")
 GK_ATOM(container, "container")
 GK_ATOM(containment, "containment")
 GK_ATOM(contains, "contains")
 GK_ATOM(content, "content")
+GK_ATOM(contenteditable, "contenteditable")
 GK_ATOM(headerContentDisposition, "content-disposition")
 GK_ATOM(headerContentLanguage, "content-language")
 GK_ATOM(contentLocation, "content-location")
 GK_ATOM(headerContentScriptType, "content-script-type")
 GK_ATOM(headerContentStyleType, "content-style-type")
 GK_ATOM(headerContentType, "content-type")
 GK_ATOM(context, "context")
 GK_ATOM(contextmenu, "contextmenu")
--- a/content/base/test/file_bug416317.xhtml
+++ b/content/base/test/file_bug416317.xhtml
@@ -489,17 +489,16 @@
 
     function jqTests(type, root, select) {
 
       function query(q, resolver){
         try {
           return root[select](q, resolver);
         } catch(e){
           if ( e.message.indexOf("ERR") > -1 ||
-              (e.name == "NamespaceError" && e.code == DOMException.NAMESPACE_ERR) ||
               (e.name == "SyntaxError" && e.code == DOMException.SYNTAX_ERR) )
             throw e;
         }
       }
 
       var all = query("*");
 
       function checkMatchesSelector(results, q) {
@@ -544,17 +543,17 @@
         if ( namespaced ) {
           for ( var i = 0; i < badNamespace.length; i++ ) {
             var resolver = badNamespace[i], pass = false, results = null;
 
             try {
               results = query(q, resolver);
             } catch(e) {
               pass = (e.message === "bad ERROR" ||
-                      (e.name == "NamespaceError" && e.code == DOMException.NAMESPACE_ERR));
+                      (e.name == "SyntaxError" && e.code == DOMException.SYNTAX_ERR));
             }
 
             assert( pass, type + ": " + name + " Bad Resolver #" + (i+1) + " (" + nq + ")" + 
               (pass ? "" : " Expected: " + extra(ids) + " Received: " + extra(results)) );
           }
         } else {
           var pass = false;
 
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -297,16 +297,17 @@ DOMCI_DATA(TextMetrics, nsTextMetrics)
 NS_INTERFACE_MAP_BEGIN(nsTextMetrics)
   NS_INTERFACE_MAP_ENTRY(nsTextMetrics)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTextMetrics)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TextMetrics)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 struct nsCanvasBidiProcessor;
+class CanvasRenderingContext2DUserData;
 
 /**
  ** nsCanvasRenderingContext2D
  **/
 class nsCanvasRenderingContext2D :
     public nsIDOMCanvasRenderingContext2D,
     public nsICanvasRenderingContextInternal
 {
@@ -376,16 +377,17 @@ public:
                 mContext->AppendPath(mPath);
             }
         }
     private:
         gfxContext *mContext;
         nsRefPtr<gfxPath> mPath;
     };
     friend class PathAutoSaveRestore;
+    friend class CanvasRenderingContext2DUserData;
 
 protected:
     nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                                uint32_t aWidth, uint32_t aHeight,
                                JSObject** aRetval);
 
     /**
      * The number of living nsCanvasRenderingContexts.  When this goes down to
@@ -444,16 +446,17 @@ protected:
     bool mResetLayer;
     bool mIPC;
 
     // Initialize the Thebes rendering context
     void CreateThebes();
 
     // If mCanvasElement is not provided, then a docshell is
     nsCOMPtr<nsIDocShell> mDocShell;
+    nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
 
     // our drawing surfaces, contexts, and layers
     nsRefPtr<gfxContext> mThebes;
     nsRefPtr<gfxASurface> mSurface;
     bool mSurfaceCreated;
 
     PRUint32 mSaveCount;
 
@@ -750,16 +753,50 @@ protected:
             *perDevPixel = devPixel;
         if (perCSSPixel)
             *perCSSPixel = cssPixel;
     }
 
     friend struct nsCanvasBidiProcessor;
 };
 
+class CanvasRenderingContext2DUserData : public LayerUserData {
+public:
+    CanvasRenderingContext2DUserData(nsCanvasRenderingContext2D *aContext)
+        : mContext(aContext)
+    {
+        aContext->mUserDatas.AppendElement(this);
+    }
+    ~CanvasRenderingContext2DUserData()
+    {
+        if (mContext) {
+            mContext->mUserDatas.RemoveElement(this);
+        }
+    }
+    static void DidTransactionCallback(void* aData)
+    {
+        CanvasRenderingContext2DUserData* self =
+            static_cast<CanvasRenderingContext2DUserData*>(aData);
+        if (self->mContext) {
+            self->mContext->MarkContextClean();
+        }
+    }
+    bool IsForContext(nsCanvasRenderingContext2D *aContext)
+    {
+        return mContext == aContext;
+    }
+    void Forget()
+    {
+        mContext = nsnull;
+    }
+
+private:
+    nsCanvasRenderingContext2D *mContext;
+};
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2D)
@@ -805,16 +842,20 @@ nsCanvasRenderingContext2D::nsCanvasRend
     , mLastStyle(STYLE_MAX), mStyleStack(20)
 {
     sNumLivingContexts++;
 }
 
 nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
 {
     Reset();
+    // Drop references from all CanvasRenderingContext2DUserDatas to this context
+    for (PRUint32 i = 0; i < mUserDatas.Length(); ++i) {
+        mUserDatas[i]->Forget();
+    }
     sNumLivingContexts--;
     if (!sNumLivingContexts) {
         delete[] sUnpremultiplyTable;
         delete[] sPremultiplyTable;
         sUnpremultiplyTable = nsnull;
         sPremultiplyTable = nsnull;
     }
 }
@@ -4149,41 +4190,32 @@ nsCanvasRenderingContext2D::SetMozImageS
         DirtyAllStyles();
     }
 
     return NS_OK;
 }
 
 static PRUint8 g2DContextLayerUserData;
 
-class CanvasRenderingContext2DUserData : public LayerUserData {
-public:
-  CanvasRenderingContext2DUserData(nsHTMLCanvasElement *aContent)
-    : mContent(aContent) {}
-  static void DidTransactionCallback(void* aData)
-  {
-    static_cast<CanvasRenderingContext2DUserData*>(aData)->mContent->MarkContextClean();
-  }
-
-private:
-  nsRefPtr<nsHTMLCanvasElement> mContent;
-};
-
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                            CanvasLayer *aOldLayer,
                                            LayerManager *aManager)
 {
     if (!EnsureSurface()) 
         return nsnull;
 
-    if (!mResetLayer && aOldLayer &&
-        aOldLayer->HasUserData(&g2DContextLayerUserData)) {
-        NS_ADDREF(aOldLayer);
-        return aOldLayer;
+    if (!mResetLayer && aOldLayer) {
+        CanvasRenderingContext2DUserData* userData =
+            static_cast<CanvasRenderingContext2DUserData*>(
+                    aOldLayer->GetUserData(&g2DContextLayerUserData));
+        if (userData && userData->IsForContext(this)) {
+            NS_ADDREF(aOldLayer);
+            return aOldLayer;
+        }
     }
 
     nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nsnull;
     }
     CanvasRenderingContext2DUserData *userData = nsnull;
@@ -4195,17 +4227,17 @@ nsCanvasRenderingContext2D::GetCanvasLay
       // and if there is, flushing the invalidation state more often than
       // necessary is harmless).
 
       // The layer will be destroyed when we tear down the presentation
       // (at the latest), at which time this userData will be destroyed,
       // releasing the reference to the element.
       // The userData will receive DidTransactionCallbacks, which flush the
       // the invalidation state to indicate that the canvas is up to date.
-      userData = new CanvasRenderingContext2DUserData(mCanvasElement);
+      userData = new CanvasRenderingContext2DUserData(this);
       canvasLayer->SetDidTransactionCallback(
               CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
     }
     canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
     CanvasLayer::Data data;
 
     data.mSurface = mSurface.get();
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -352,16 +352,17 @@ NS_IMPL_RELEASE(nsTextMetricsAzure)
 NS_INTERFACE_MAP_BEGIN(nsTextMetricsAzure)
   NS_INTERFACE_MAP_ENTRY(nsTextMetricsAzure)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTextMetrics)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TextMetrics)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 struct nsCanvasBidiProcessorAzure;
+class CanvasRenderingContext2DUserDataAzure;
 
 // Cap sigma to avoid overly large temp surfaces.
 static const Float SIGMA_MAX = 100;
 
 /**
  ** nsCanvasRenderingContext2DAzure
  **/
 class nsCanvasRenderingContext2DAzure :
@@ -418,16 +419,18 @@ public:
     STYLE_STROKE = 0,
     STYLE_FILL,
     STYLE_MAX
   };
   
   nsresult LineTo(const Point& aPoint);
   nsresult BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3);
 
+  friend class CanvasRenderingContext2DUserDataAzure;
+
 protected:
   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                              uint32_t aWidth, uint32_t aHeight,
                              JSObject** aRetval);
 
   nsresult InitializeWithTarget(DrawTarget *surface, PRInt32 width, PRInt32 height);
 
   /**
@@ -499,16 +502,18 @@ protected:
   bool mOpaque;
 
   // This is true when the next time our layer is retrieved we need to
   // recreate it (i.e. our backing surface changed)
   bool mResetLayer;
   // This is needed for drawing in drawAsyncXULElement
   bool mIPC;
 
+  nsTArray<CanvasRenderingContext2DUserDataAzure*> mUserDatas;
+
   // If mCanvasElement is not provided, then a docshell is
   nsCOMPtr<nsIDocShell> mDocShell;
 
   // our drawing surfaces, contexts, and layers
   RefPtr<DrawTarget> mTarget;
 
   /**
     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
@@ -930,16 +935,50 @@ protected:
       *perDevPixel = devPixel;
     if (perCSSPixel)
       *perCSSPixel = cssPixel;
   }
 
   friend struct nsCanvasBidiProcessorAzure;
 };
 
+class CanvasRenderingContext2DUserDataAzure : public LayerUserData {
+public:
+    CanvasRenderingContext2DUserDataAzure(nsCanvasRenderingContext2DAzure *aContext)
+    : mContext(aContext)
+  {
+    aContext->mUserDatas.AppendElement(this);
+  }
+  ~CanvasRenderingContext2DUserDataAzure()
+  {
+    if (mContext) {
+      mContext->mUserDatas.RemoveElement(this);
+    }
+  }
+  static void DidTransactionCallback(void* aData)
+  {
+      CanvasRenderingContext2DUserDataAzure* self =
+      static_cast<CanvasRenderingContext2DUserDataAzure*>(aData);
+    if (self->mContext) {
+      self->mContext->MarkContextClean();
+    }
+  }
+  bool IsForContext(nsCanvasRenderingContext2DAzure *aContext)
+  {
+    return mContext == aContext;
+  }
+  void Forget()
+  {
+    mContext = nsnull;
+  }
+
+private:
+  nsCanvasRenderingContext2DAzure *mContext;
+};
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2DAzure)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2DAzure)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -1024,16 +1063,20 @@ nsCanvasRenderingContext2DAzure::nsCanva
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
 }
 
 nsCanvasRenderingContext2DAzure::~nsCanvasRenderingContext2DAzure()
 {
   Reset();
+  // Drop references from all CanvasRenderingContext2DUserDataAzure to this context
+  for (PRUint32 i = 0; i < mUserDatas.Length(); ++i) {
+    mUserDatas[i]->Forget();
+  }
   sNumLivingContexts--;
   if (!sNumLivingContexts) {
     delete[] sUnpremultiplyTable;
     delete[] sPremultiplyTable;
     sUnpremultiplyTable = nsnull;
     sPremultiplyTable = nsnull;
   }
 }
@@ -4394,70 +4437,61 @@ nsCanvasRenderingContext2DAzure::SetMozI
       CurrentState().imageSmoothingEnabled = val;
   }
 
   return NS_OK;
 }
 
 static PRUint8 g2DContextLayerUserData;
 
-class CanvasRenderingContext2DUserData : public LayerUserData {
-public:
-  CanvasRenderingContext2DUserData(nsHTMLCanvasElement *aContent)
-    : mContent(aContent) {}
-  static void DidTransactionCallback(void* aData)
-  {
-    static_cast<CanvasRenderingContext2DUserData*>(aData)->mContent->MarkContextClean();
-  }
-
-private:
-  nsRefPtr<nsHTMLCanvasElement> mContent;
-};
-
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                            CanvasLayer *aOldLayer,
                                            LayerManager *aManager)
 {
   if (!mValid) {
     return nsnull;
   }
 
   if (mTarget) {
     mTarget->Flush();
   }
 
-  if (!mResetLayer && aOldLayer &&
-      aOldLayer->HasUserData(&g2DContextLayerUserData)) {
+  if (!mResetLayer && aOldLayer) {
+      CanvasRenderingContext2DUserDataAzure* userData =
+      static_cast<CanvasRenderingContext2DUserDataAzure*>(
+        aOldLayer->GetUserData(&g2DContextLayerUserData));
+    if (userData && userData->IsForContext(this)) {
       NS_ADDREF(aOldLayer);
       return aOldLayer;
+    }
   }
 
   nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
   if (!canvasLayer) {
-      NS_WARNING("CreateCanvasLayer returned null!");
-      return nsnull;
+    NS_WARNING("CreateCanvasLayer returned null!");
+    return nsnull;
   }
-  CanvasRenderingContext2DUserData *userData = nsnull;
+  CanvasRenderingContext2DUserDataAzure *userData = nsnull;
   if (aBuilder->IsPaintingToWindow()) {
     // Make the layer tell us whenever a transaction finishes (including
     // the current transaction), so we can clear our invalidation state and
     // start invalidating again. We need to do this for the layer that is
     // being painted to a window (there shouldn't be more than one at a time,
     // and if there is, flushing the invalidation state more often than
     // necessary is harmless).
 
     // The layer will be destroyed when we tear down the presentation
     // (at the latest), at which time this userData will be destroyed,
     // releasing the reference to the element.
     // The userData will receive DidTransactionCallbacks, which flush the
     // the invalidation state to indicate that the canvas is up to date.
-    userData = new CanvasRenderingContext2DUserData(mCanvasElement);
+    userData = new CanvasRenderingContext2DUserDataAzure(this);
     canvasLayer->SetDidTransactionCallback(
-            CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
+            CanvasRenderingContext2DUserDataAzure::DidTransactionCallback, userData);
   }
   canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
   CanvasLayer::Data data;
 
   data.mDrawTarget = mTarget;
   data.mSize = nsIntSize(mWidth, mHeight);
 
--- a/content/events/src/nsDOMKeyboardEvent.cpp
+++ b/content/events/src/nsDOMKeyboardEvent.cpp
@@ -91,16 +91,17 @@ nsDOMKeyboardEvent::GetCharCode(PRUint32
   case NS_KEY_UP:
   case NS_KEY_DOWN:
     *aCharCode = 0;
     break;
   case NS_KEY_PRESS:
     *aCharCode = ((nsKeyEvent*)mEvent)->charCode;
     break;
   default:
+    *aCharCode = 0;
     break;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetKeyCode(PRUint32* aKeyCode)
 {
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1673,20 +1673,20 @@ nsEventStateManager::IsRemoteTarget(nsIC
       target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
                           nsGkAtoms::_true, eIgnoreCase)) {
     return true;
   }
 
   // <frame/iframe mozbrowser>
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target);
   if (browserFrame) {
-    bool isRemote = false;
-    browserFrame->GetReallyIsBrowser(&isRemote);
-    if (isRemote) {
-      return true;
+    bool isBrowser = false;
+    browserFrame->GetReallyIsBrowser(&isBrowser);
+    if (isBrowser) {
+      return !!TabParent::GetFrom(target);
     }
   }
 
   return false;
 }
 
 
 bool
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -544,16 +544,17 @@ MediaStreamGraphImpl::IsAlwaysExplicitly
   }
 }
 
 void
 MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
 {
   if (aStream->mFinished)
     return;
+  printf("MediaStreamGraphImpl::FinishStream\n");
   LOG(PR_LOG_DEBUG, ("MediaStream %p will finish", aStream));
   aStream->mFinished = true;
   // Force at least one more iteration of the control loop, since we rely
   // on UpdateCurrentTime to notify our listeners once the stream end
   // has been reached.
   EnsureNextIteration();
 }
 
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -924,26 +924,33 @@ nsFocusManager::WindowHidden(nsIDOMWindo
     return NS_OK;
 
   // at this point, we know that the window being hidden is either the focused
   // window, or an ancestor of the focused window. Either way, the focus is no
   // longer valid, so it needs to be updated.
 
   nsCOMPtr<nsIContent> oldFocusedContent = mFocusedContent.forget();
 
+  nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
+  nsCOMPtr<nsIPresShell> presShell;
+  focusedDocShell->GetPresShell(getter_AddRefs(presShell));
+
   if (oldFocusedContent && oldFocusedContent->IsInDoc()) {
     NotifyFocusStateChange(oldFocusedContent,
                            mFocusedWindow->ShouldShowFocusRing(),
                            false);
+    window->UpdateCommands(NS_LITERAL_STRING("focus"));
+
+    if (presShell) {
+      SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
+                           oldFocusedContent->GetCurrentDoc(),
+                           oldFocusedContent, 1, false);
+    }
   }
 
-  nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
-  nsCOMPtr<nsIPresShell> presShell;
-  focusedDocShell->GetPresShell(getter_AddRefs(presShell));
-
   nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
   if (presShell) {
     nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nsnull,
                                      GetFocusMoveActionCause(0));
     SetCaretVisible(presShell, false, nsnull);
   }
 
   // if the docshell being hidden is being destroyed, then we want to move
@@ -1558,18 +1565,17 @@ nsFocusManager::Blur(nsPIDOMWindow* aWin
           nsCOMPtr<nsIWidget> widget;
           vm->GetRootWidget(getter_AddRefs(widget));
           if (widget)
             widget->SetFocus(false);
         }
       }
 
       // if the object being blurred is a remote browser, deactivate remote content
-      TabParent* remote = GetRemoteForContent(content);
-      if (remote) {
+      if (TabParent* remote = TabParent::GetFrom(content)) {
         remote->Deactivate();
   #ifdef DEBUG_FOCUS
       printf("*Remote browser deactivated\n");
   #endif
       }
     }
   }
 
@@ -1770,18 +1776,17 @@ nsFocusManager::Focus(nsPIDOMWindow* aWi
       // if this is an object/plug-in/remote browser, focus its widget.  Note that we might
       // no longer be in the same document, due to the events we fired above when
       // aIsNewDocument.
       if (presShell->GetDocument() == aContent->GetDocument()) {
         if (aAdjustWidgets && objectFrameWidget && !sTestMode)
           objectFrameWidget->SetFocus(false);
 
         // if the object being focused is a remote browser, activate remote content
-        TabParent* remote = GetRemoteForContent(aContent);
-        if (remote) {
+        if (TabParent* remote = TabParent::GetFrom(aContent)) {
           remote->Activate();
 #ifdef DEBUG_FOCUS
           printf("*Remote browser activated\n");
 #endif
         }
       }
 
       nsIMEStateManager::OnChangeFocus(presContext, aContent,
@@ -3001,39 +3006,16 @@ nsFocusManager::GetRootForFocus(nsPIDOMW
   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
   if (htmlDoc && aDocument->GetHtmlChildElement(nsGkAtoms::frameset)) {
     return nsnull;
   }
 
   return rootElement;
 }
 
-TabParent*
-nsFocusManager::GetRemoteForContent(nsIContent* aContent) {
-  if (!aContent ||
-      (aContent->Tag() != nsGkAtoms::browser &&
-       aContent->Tag() != nsGkAtoms::iframe) ||
-      !aContent->IsXUL() ||
-      !aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
-                             nsGkAtoms::_true, eIgnoreCase))
-    return nsnull;
-
-  nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent);
-  if (!loaderOwner)
-    return nsnull;
-
-  nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
-  if (!frameLoader)
-    return nsnull;
-
-  PBrowserParent* remoteBrowser = frameLoader->GetRemoteBrowser();
-  TabParent* remote = static_cast<TabParent*>(remoteBrowser);
-  return remote;
-}
-
 void
 nsFocusManager::GetLastDocShell(nsIDocShellTreeItem* aItem,
                                 nsIDocShellTreeItem** aResult)
 {
   *aResult = nsnull;
 
   nsCOMPtr<nsIDocShellTreeItem> curItem = aItem;
   while (curItem) {
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -16,22 +16,16 @@
 #define FOCUSMETHOD_MASK 0xF000
 #define FOCUSMETHODANDRING_MASK 0xF0F000
 
 #define FOCUSMANAGER_CONTRACTID "@mozilla.org/focus-manager;1"
 
 class nsIDocShellTreeItem;
 class nsPIDOMWindow;
 
-namespace mozilla {
-namespace dom {
-  class TabParent;
-}
-}
-
 struct nsDelayedBlurOrFocusEvent;
 
 /**
  * The focus manager keeps track of where the focus is, that is, the node
  * which receives key events.
  */
 
 class nsFocusManager MOZ_FINAL : public nsIFocusManager,
@@ -410,22 +404,16 @@ protected:
    * - if aDocument is a frameset document.
    */
   nsIContent* GetRootForFocus(nsPIDOMWindow* aWindow,
                               nsIDocument* aDocument,
                               bool aIsForDocNavigation,
                               bool aCheckVisibility);
 
   /**
-   * Get the TabParent associated with aContent if it is a remote browser,
-   * or null in all other cases.
-   */
-  mozilla::dom::TabParent* GetRemoteForContent(nsIContent* aContent);
-
-  /**
    * Get the last docshell child of aItem and return it in aResult.
    */
   void GetLastDocShell(nsIDocShellTreeItem* aItem,
                        nsIDocShellTreeItem** aResult);
 
   /**
    * Get the next docshell child of aItem and return it in aResult.
    */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -171,16 +171,17 @@ DOMInterfaces = {
     'workers': True,
     'nativeType': 'JSObject',
     'headerFile': 'jsapi.h',
     'castable': False
 }],
 
 'WebGLRenderingContext': {
   'nativeType': 'mozilla::WebGLContext',
+  'headerFile': 'WebGLContext.h',
   'prefable': True,
   'resultNotAddRefed': [ 'canvas', 'getContextAttributes', 'getExtension',
                          'getAttachedShaders' ],
   'implicitJSContext': [ 'texImage2D', 'texSubImage2D' ],
   'infallible': [ 'canvas', 'drawingBufferWidth', 'drawingBufferHeight',
                   'isContextLost', 'getSupportedExtensions',
                   'getExtension', 'activeTexture',
                   'attachShader', 'bindAttribLocation', 'bindBuffer',
@@ -351,18 +352,17 @@ def addExternalIface(iface, nativeType=N
 def addExternalHTMLElement(element):
    nativeElement = 'ns' + element
    addExternalIface(element, nativeType=nativeElement,
                     headerFile=nativeElement + '.h')
 
 addExternalHTMLElement('HTMLCanvasElement')
 addExternalHTMLElement('HTMLImageElement')
 addExternalHTMLElement('HTMLVideoElement')
-addExternalIface('ImageData', nativeType='mozilla::dom::ImageData',
-                 headerFile='mozilla/dom/ImageData.h')
+addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
 addExternalIface('WebGLActiveInfo', nativeType='mozilla::WebGLActiveInfo',
                  headerFile='WebGLContext.h')
 addExternalIface('WebGLBuffer', nativeType='mozilla::WebGLBuffer',
                  headerFile='WebGLContext.h')
 addExternalIface('WebGLContextAttributes', nativeType='JSObject',
                  headerFile='jsapi.h')
 addExternalIface('WebGLExtension', nativeType='nsIWebGLExtension',
                  headerFile='WebGLContext.h')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1559,21 +1559,21 @@ for (uint32_t i = 0; i < length; ++i) {
             templateBody += str(CallbackObjectUnwrapper(
                     descriptor,
                     "&${val}.toObject()",
                     "${declName}",
                     codeOnFailure=failureCode))
         elif descriptor.workers:
             templateBody += "${declName} = &${val}.toObject();"
         else:
-            # External interface.  We always have a holder for these,
-            # because we don't actually know whether we have to addref
-            # when unwrapping or not.  So we just pass an
-            # getter_AddRefs(nsRefPtr) to XPConnect and if we'll need
-            # a release it'll put a non-null pointer in there.
+            # Either external, or new-binding non-castable.  We always have a
+            # holder for these, because we don't actually know whether we have
+            # to addref when unwrapping or not.  So we just pass an
+            # getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
+            # it'll put a non-null pointer in there.
             if forceOwningType:
                 # Don't return a holderType in this case; our declName
                 # will just own stuff.
                 templateBody += "nsRefPtr<" + typeName + "> ${holderName};\n"
             else:
                 holderType = "nsRefPtr<" + typeName + ">"
             templateBody += (
                 "jsval tmpVal = ${val};\n" +
@@ -2478,39 +2478,16 @@ class CGMethodCall(CGThing):
             arguments = signature[1]
             if len(arguments) == 0:
                 return 0
             requiredArgs = len(arguments)
             while requiredArgs and arguments[requiredArgs-1].optional:
                 requiredArgs -= 1
             return requiredArgs
 
-        def maxSigLength(signatures):
-            return max([len(s[1]) for s in signatures])
-
-        def signaturesForArgCount(i, signatures):
-            return filter(
-                lambda s: len(s[1]) == i or (len(s[1]) > i and
-                                             s[1][i].optional),
-                    signatures)
-
-        def findDistinguishingIndex(argCount, signatures):
-            def isValidDistinguishingIndex(idx, signatures):
-                for firstSigIndex in range(0, len(signatures)):
-                    for secondSigIndex in range(0, firstSigIndex):
-                        firstType = signatures[firstSigIndex][1][idx].type
-                        secondType = signatures[secondSigIndex][1][idx].type
-                        if not firstType.isDistinguishableFrom(secondType):
-                            return False
-                return True
-            for idx in range(0, argCount):
-                if isValidDistinguishingIndex(idx, signatures):
-                    return idx
-            return -1
-
         def getPerSignatureCall(signature, argConversionStartsAt=0):
             return CGPerSignatureCall(signature[0], argsPre, signature[1],
                                       nativeMethodName, static, descriptor,
                                       method, argConversionStartsAt)
             
 
         signatures = method.signatures()
         if len(signatures) == 1:
@@ -2530,65 +2507,43 @@ class CGMethodCall(CGThing):
                                 "}" % (requiredArgs,
                                        toStringBool(not descriptor.workers)))
                             ),
                         pre="\n", post="\n")
                     )
             return
 
         # Need to find the right overload
-        maxSigArgs = maxSigLength(signatures)
-        allowedArgCounts = [ i for i in range(0, maxSigArgs+1)
-                             if len(signaturesForArgCount(i, signatures)) != 0 ]
+        maxArgCount = method.maxArgCount
+        allowedArgCounts = method.allowedArgCounts
 
         argCountCases = []
         for argCount in allowedArgCounts:
-            possibleSignatures = signaturesForArgCount(argCount, signatures)
+            possibleSignatures = method.signaturesForArgCount(argCount)
             if len(possibleSignatures) == 1:
                 # easy case!
                 signature = possibleSignatures[0]
 
                 # (possibly) important optimization: if signature[1] has >
                 # argCount arguments and signature[1][argCount] is optional and
                 # there is only one signature for argCount+1, then the
                 # signature for argCount+1 is just ourselves and we can fall
                 # through.
                 if (len(signature[1]) > argCount and
                     signature[1][argCount].optional and
                     (argCount+1) in allowedArgCounts and
-                    len(signaturesForArgCount(argCount+1, signatures)) == 1):
+                    len(method.signaturesForArgCount(argCount+1)) == 1):
                     argCountCases.append(
                         CGCase(str(argCount), None, True))
                 else:
                     argCountCases.append(
                         CGCase(str(argCount), getPerSignatureCall(signature)))
                 continue
 
-            distinguishingIndex = findDistinguishingIndex(argCount,
-                                                          possibleSignatures)
-            if distinguishingIndex == -1:
-                raise TypeError(("Signatures with %s arguments for " +
-                                 descriptor.interface.identifier.name + "." +
-                                 method.identifier.name +
-                                 " are not distinguishable") % argCount)
-
-            for idx in range(0, distinguishingIndex):
-                firstSigType = possibleSignatures[0][1][idx].type
-                for sigIdx in range(1, len(possibleSignatures)):
-                    if possibleSignatures[sigIdx][1][idx].type != firstSigType:
-                        raise TypeError(("Signatures with %d arguments for " +
-                                         descriptor.interface.identifier.name +
-                                         "." + method.identifier.name +
-                                         " have different types at index %d" +
-                                         " which is before distinguishing" +
-                                         " index %d.  Types are %s and %s") %
-                                        (argCount, idx,
-                                         distinguishingIndex,
-                                         str(possibleSignatures[sigIdx][1][idx].type),
-                                         str(firstSigType)))
+            distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
 
             # Convert all our arguments up to the distinguishing index.
             # Doesn't matter which of the possible signatures we use, since
             # they all have the same types up to that point; just use
             # possibleSignatures[0]
             caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
             caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
                                                   i, "argv_start", "argc",
@@ -2718,17 +2673,17 @@ class CGMethodCall(CGThing):
                                           toStringBool(not descriptor.workers)))
 
             argCountCases.append(CGCase(str(argCount),
                                         CGList(caseBody, "\n")))
 
         overloadCGThings = []
         overloadCGThings.append(
             CGGeneric("unsigned argcount = NS_MIN(argc, %du);" %
-                      maxSigArgs))
+                      maxArgCount))
         overloadCGThings.append(
             CGSwitch("argcount",
                      argCountCases,
                      CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);" %
                                toStringBool(not descriptor.workers))))
         overloadCGThings.append(
                 CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
                           'return false;'))
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -126,17 +126,17 @@ class Descriptor(DescriptorProvider):
         DescriptorProvider.__init__(self, config, desc.get('workers', False))
         self.interface = interface
 
         # Read the desc, and fill in the relevant defaults.
         self.nativeType = desc['nativeType']
         self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
 
         headerDefault = self.nativeType
-        headerDefault = headerDefault.split("::")[-1] + ".h"
+        headerDefault = headerDefault.replace("::", "/") + ".h"
         self.headerFile = desc.get('headerFile', headerDefault)
 
         castableDefault = not self.interface.isCallback()
         self.castable = desc.get('castable', castableDefault)
 
         self.notflattened = desc.get('notflattened', False)
         self.register = desc.get('register', True)
 
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -46,29 +46,31 @@ def M_add_class_attribs(attribs):
 def enum(*names):
     class Foo(object):
         __metaclass__ = M_add_class_attribs(names)
         def __setattr__(self, name, value):  # this makes it read-only
             raise NotImplementedError
     return Foo()
 
 class WebIDLError(Exception):
-    def __init__(self, message, location, warning=False, extraLocation=""):
+    def __init__(self, message, location, warning=False, extraLocations=[]):
         self.message = message
         self.location = location
         self.warning = warning
-        self.extraLocation = extraLocation
+        self.extraLocations = [str(loc) for loc in extraLocations]
 
     def __str__(self):
-        return "%s: %s%s%s%s%s" % (self.warning and 'warning' or 'error',
-                                   self.message,
-                                   ", " if self.location else "",
-                                   self.location,
-                                   "\n" if self.extraLocation else "",
-                                   self.extraLocation)
+        extraLocationsStr = (
+            "" if len(self.extraLocations) == 0 else
+            "\n" + "\n".join(self.extraLocations))
+        return "%s: %s%s%s%s" % (self.warning and 'warning' or 'error',
+                                 self.message,
+                                 ", " if self.location else "",
+                                 self.location,
+                                 extraLocationsStr)
 
 class Location(object):
     def __init__(self, lexer, lineno, lexpos, filename):
         self._line = None
         self._lineno = lineno
         self._lexpos = lexpos
         self._lexdata = lexer.lexdata
         self._file = filename if filename else "<unknown>"
@@ -340,22 +342,28 @@ class IDLExternalInterface(IDLObjectWith
         assert isinstance(parentScope, IDLScope)
         self.parent = None
         IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
         IDLObjectWithIdentifier.resolve(self, parentScope)
 
     def finish(self, scope):
         pass
 
+    def validate(self):
+        pass
+
     def isExternal(self):
         return True
 
     def isInterface(self):
         return True
 
+    def isConsequential(self):
+        return False
+
     def addExtendedAttributes(self, attrs):
         assert len(attrs) == 0
 
     def resolve(self, parentScope):
         pass
 
 class IDLInterface(IDLObjectWithScope):
     def __init__(self, location, parentScope, name, parent, members):
@@ -363,16 +371,21 @@ class IDLInterface(IDLObjectWithScope):
         assert isinstance(name, IDLUnresolvedIdentifier)
         assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
 
         self.parent = parent
         self._callback = False
         self._finished = False
         self.members = list(members) # clone the list
         self.implementedInterfaces = set()
+        self._consequential = False
+        # self.interfacesBasedOnSelf is the set of interfaces that inherit from
+        # self or have self as a consequential interface, including self itself.
+        # Used for distinguishability checking.
+        self.interfacesBasedOnSelf = set([self])
 
         IDLObjectWithScope.__init__(self, location, parentScope, name)
 
     def __str__(self):
         return "Interface '%s'" % self.identifier.name
 
     def ctor(self):
         identifier = IDLUnresolvedIdentifier(self.location, "constructor",
@@ -414,29 +427,50 @@ class IDLInterface(IDLObjectWithScope):
 
         assert iter(self.members)
 
         if self.parent:
             self.parent.finish(scope)
 
             # Callbacks must not inherit from non-callbacks or inherit from
             # anything that has consequential interfaces.
+            # XXXbz Can non-callbacks inherit from callbacks?  Spec issue pending.
+            # XXXbz Can callbacks have consequential interfaces?  Spec issue pending
             if self.isCallback():
-                assert(self.parent.isCallback())
-                assert(len(self.parent.getConsequentialInterfaces()) == 0)
+                if not self.parent.isCallback():
+                    raise WebIDLError("Callback interface %s inheriting from "
+                                      "non-callback interface %s" %
+                                      (self.identifier.name,
+                                       self.parent.identifier.name),
+                                      self.location,
+                                      extraLocations=[self.parent.location])
+            elif self.parent.isCallback():
+                raise WebIDLError("Non-callback interface %s inheriting from "
+                                  "callback interface %s" %
+                                  (self.identifier.name,
+                                   self.parent.identifier.name),
+                                  self.location,
+                                  extraLocations=[self.parent.location])
 
         for iface in self.implementedInterfaces:
             iface.finish(scope)
 
         cycleInGraph = self.findInterfaceLoopPoint(self)
         if cycleInGraph:
             raise WebIDLError("Interface %s has itself as ancestor or "
                               "implemented interface" % self.identifier.name,
                               self.location,
-                              extraLocation=cycleInGraph.location)
+                              extraLocations=[cycleInGraph.location])
+
+        if self.isCallback():
+            # "implements" should have made sure we have no
+            # consequential interfaces.
+            assert len(self.getConsequentialInterfaces()) == 0
+            # And that we're not consequential.
+            assert not self.isConsequential()
 
         # Now resolve() and finish() our members before importing the
         # ones from our implemented interfaces.
 
         # resolve() will modify self.members, so we need to iterate
         # over a copy of the member list here.
         for member in list(self.members):
             member.resolve(self)
@@ -454,27 +488,34 @@ class IDLInterface(IDLObjectWithScope):
         self.originalMembers = list(self.members)
 
         # Import everything from our consequential interfaces into
         # self.members.  Sort our consequential interfaces by name
         # just so we have a consistent order.
         for iface in sorted(self.getConsequentialInterfaces(),
                             cmp=cmp,
                             key=lambda x: x.identifier.name):
+            # Flag the interface as being someone's consequential interface
+            iface.setIsConsequentialInterfaceOf(self)
             additionalMembers = iface.originalMembers;
             for additionalMember in additionalMembers:
                 for member in self.members:
                     if additionalMember.identifier.name == member.identifier.name:
                         raise WebIDLError(
                             "Multiple definitions of %s on %s coming from 'implements' statements" %
                             (member.identifier.name, self),
                             additionalMember.location,
-                            extraLocation=member.location)
+                            extraLocations=[member.location])
             self.members.extend(additionalMembers)
 
+        for ancestor in self.getInheritedInterfaces():
+            ancestor.interfacesBasedOnSelf.add(self)
+            for ancestorConsequential in ancestor.getConsequentialInterfaces():
+                ancestorConsequential.interfacesBasedOnSelf.add(self)
+
         # Ensure that there's at most one of each {named,indexed}
         # {getter,setter,creator,deleter}.
         specialMembersSeen = set()
         for member in self.members:
             if member.tag != IDLInterfaceMember.Tags.Method:
                 continue
 
             if member.isGetter():
@@ -496,22 +537,33 @@ class IDLInterface(IDLObjectWithScope):
                 continue
 
             if memberType in specialMembersSeen:
                 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
                                    self.location)
 
             specialMembersSeen.add(memberType)
 
+    def validate(self):
+        for member in self.members:
+            member.validate()
+
     def isInterface(self):
         return True
 
     def isExternal(self):
         return False
 
+    def setIsConsequentialInterfaceOf(self, other):
+        self._consequential = True
+        self.interfacesBasedOnSelf.add(other)
+
+    def isConsequential(self):
+        return self._consequential
+
     def setCallback(self, value):
         self._callback = value
 
     def isCallback(self):
         return self._callback
 
     def inheritanceDepth(self):
         depth = 0
@@ -648,17 +700,17 @@ class IDLDictionary(IDLObjectWithScope):
         if self.parent:
             assert isinstance(self.parent, IDLIdentifierPlaceholder)
             oldParent = self.parent
             self.parent = self.parent.finish(scope)
             if not isinstance(self.parent, IDLDictionary):
                 raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
                                   self.identifier.name,
                                   oldParent.location,
-                                  extraLocation=self.parent.location)
+                                  extraLocations=[self.parent.location])
 
             # Make sure the parent resolves all its members before we start
             # looking at them.
             self.parent.finish(scope)
 
         for member in self.members:
             member.resolve(self)
             if not member.type.isComplete():
@@ -682,17 +734,20 @@ class IDLDictionary(IDLObjectWithScope):
 
         # Catch name duplication
         for inheritedMember in inheritedMembers:
             for member in self.members:
                 if member.identifier.name == inheritedMember.identifier.name:
                     raise WebIDLError("Dictionary %s has two members with name %s" %
                                       (self.identifier.name, member.identifier.name),
                                       member.location,
-                                      extraLocation=inheritedMember.location)
+                                      extraLocations=[inheritedMember.location])
+
+    def validate(self):
+        pass
 
     def addExtendedAttributes(self, attrs):
         assert len(attrs) == 0
 
 
 class IDLEnum(IDLObjectWithIdentifier):
     def __init__(self, location, parentScope, name, values):
         assert isinstance(parentScope, IDLScope)
@@ -705,16 +760,19 @@ class IDLEnum(IDLObjectWithIdentifier):
         self._values = values
 
     def values(self):
         return self._values
 
     def finish(self, scope):
         pass
 
+    def validate(self):
+        pass
+
     def isEnum(self):
         return True
 
     def addExtendedAttributes(self, attrs):
         assert len(attrs) == 0
 
 class IDLType(IDLObject):
     Tags = enum(
@@ -1250,33 +1308,44 @@ class IDLWrapperType(IDLType):
 
     def isDistinguishableFrom(self, other):
         assert self.isInterface() or self.isEnum() or self.isDictionary()
         if self.isEnum():
             return (other.isInterface() or other.isObject() or
                     other.isCallback() or other.isDictionary() or
                     other.isSequence() or other.isArray() or
                     other.isDate())
-        if other.isPrimitive() or other.isString() or other.isEnum():
+        if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate():
             return True
         if self.isDictionary():
             return (other.isNonCallbackInterface() or other.isSequence() or
-                    other.isArray() or other.isDate())
+                    other.isArray())
 
         assert self.isInterface()
         # XXXbz need to check that the interfaces can't be implemented
         # by the same object
         if other.isInterface():
-            return (self != other and
+            if other.isSpiderMonkeyInterface():
+                # Just let |other| handle things
+                return other.isDistinguishableFrom(self)
+            assert self.isGeckoInterface() and other.isGeckoInterface()
+            if self.inner.isExternal() or other.unroll().inner.isExternal():
+                return self != other
+            return (len(self.inner.interfacesBasedOnSelf &
+                        other.unroll().inner.interfacesBasedOnSelf) == 0 and
                     (self.isNonCallbackInterface() or
                      other.isNonCallbackInterface()))
         if (other.isDictionary() or other.isCallback() or
             other.isSequence() or other.isArray()):
             return self.isNonCallbackInterface()
 
+        # Not much else |other| can be
+        assert other.isObject()
+        return False
+
 class IDLBuiltinType(IDLType):
 
     Types = enum(
         # The integer types
         'byte',
         'octet',
         'short',
         'unsigned_short',
@@ -1633,16 +1702,19 @@ class IDLConst(IDLInterfaceMember):
         self.value = coercedValue
 
     def __str__(self):
         return "'%s' const '%s'" % (self.type, self.identifier)
 
     def finish(self, scope):
         assert self.type.isComplete()
 
+    def validate(self):
+        pass
+
 class IDLAttribute(IDLInterfaceMember):
     def __init__(self, location, identifier, type, readonly, inherit):
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Attr)
 
         assert isinstance(type, IDLType)
         self.type = type
         self.readonly = readonly
@@ -1661,16 +1733,19 @@ class IDLAttribute(IDLInterfaceMember):
 
             assert not isinstance(t, IDLUnresolvedType)
             assert not isinstance(t.name, IDLUnresolvedIdentifier)
             if t.isDictionary():
                 raise WebIDLError("An attribute cannot be of a dictionary type",
                                   self.location)
             self.type = t
 
+    def validate(self):
+        pass
+
     def handleExtendedAttribute(self, name, list):
         if name == "TreatNonCallableAsNull":
             self.type.markTreatNonCallableAsNull();
         IDLInterfaceMember.handleExtendedAttribute(self, name, list)
 
     def resolve(self, parentScope):
         assert isinstance(parentScope, IDLScope)
         self.type.resolveType(parentScope)
@@ -1734,16 +1809,19 @@ class IDLCallbackType(IDLType, IDLObject
                 continue
 
             type = argument.type.complete(scope)
 
             assert not isinstance(type, IDLUnresolvedType)
             assert not isinstance(type.name, IDLUnresolvedIdentifier)
             argument.type = type
 
+    def validate(self):
+        pass
+
     def isDistinguishableFrom(self, other):
         return (other.isPrimitive() or other.isString() or other.isEnum() or
                 other.isNonCallbackInterface() or other.isDate())
 
 class IDLMethod(IDLInterfaceMember, IDLScope):
 
     Special = enum(
         'None',
@@ -1775,16 +1853,19 @@ class IDLMethod(IDLInterfaceMember, IDLS
         # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Method)
 
         self._hasOverloads = False
 
         assert isinstance(returnType, IDLType)
         self._returnType = [returnType]
+        # We store a list of all the overload locations, matching our
+        # signature list.
+        self._location = [location]
 
         assert isinstance(static, bool)
         self._static = static
         assert isinstance(getter, bool)
         self._getter = getter
         assert isinstance(setter, bool)
         self._setter = setter
         assert isinstance(creator, bool)
@@ -1821,30 +1902,42 @@ class IDLMethod(IDLInterfaceMember, IDLS
             assert not self._arguments[0][1].optional and not self._arguments[0][1].variadic
             assert self._arguments[0][1].type == self._returnType[0]
 
         if self._stringifier:
             assert len(self._arguments[0]) == 0
             assert self._returnType[0] == BuiltinTypes[IDLBuiltinType.Types.domstring]
 
         inOptionalArguments = False
-        sawVariadicArgument = False
+        variadicArgument = None
+        sawOptionalWithNoDefault = False
 
         assert len(self._arguments) == 1
         arguments = self._arguments[0]
 
         for argument in arguments:
             # Only the last argument can be variadic
-            assert not sawVariadicArgument
+            if variadicArgument:
+                raise WebIDLError("Variadic argument is not last argument",
+                                  variadicArgument.location)
             # Once we see an optional argument, there can't be any non-optional
             # arguments.
-            if inOptionalArguments:
-                assert argument.optional
+            if inOptionalArguments and not argument.optional:
+                raise WebIDLError("Non-optional argument after optional arguments",
+                                  argument.location)
+            # Once we see an argument with no default value, there can
+            # be no more default values.
+            if sawOptionalWithNoDefault and argument.defaultValue:
+                raise WebIDLError("Argument with default value after optional "
+                                  "arguments with no default values",
+                                  argument.location)
             inOptionalArguments = argument.optional
-            sawVariadicArgument = argument.variadic
+            if argument.variadic:
+                variadicArgument = argument
+            sawOptionalWithNoDefault = argument.optional and not argument.defaultValue
 
     def isStatic(self):
         return self._static
 
     def isGetter(self):
         return self._getter
 
     def isSetter(self):
@@ -1883,19 +1976,21 @@ class IDLMethod(IDLInterfaceMember, IDLS
             for argument in arguments:
                 argument.resolve(self)
 
     def addOverload(self, method):
         checkDistinguishability(self._arguments, method._arguments)
 
         assert len(method._returnType) == 1
         assert len(method._arguments) == 1
+        assert len(method._location) == 1
 
         self._returnType.extend(method._returnType)
         self._arguments.extend(method._arguments)
+        self._location.extend(method._location)
 
         self._hasOverloads = True
 
         if self.isStatic() != method.isStatic():
             raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method1.identifier,
                               method.location)
 
         if self.isLegacycaller() != method.isLegacycaller():
@@ -1937,29 +2032,109 @@ class IDLMethod(IDLInterfaceMember, IDLS
                     continue
 
                 type = argument.type.complete(scope)
 
                 assert not isinstance(type, IDLUnresolvedType)
                 assert not isinstance(type.name, IDLUnresolvedIdentifier)
                 argument.type = type
 
+        # Now compute various information that will be used by the
+        # WebIDL overload resolution algorithm.
+        self.maxArgCount = max(len(s[1]) for s in self.signatures())
+        self.allowedArgCounts = [ i for i in range(self.maxArgCount+1)
+                                  if len(self.signaturesForArgCount(i)) != 0 ]
+
+    def validate(self):
+        # Make sure our overloads are properly distinguishable and don't have
+        # different argument types before the distinguishing args.
+        for argCount in self.allowedArgCounts:
+            possibleSignatures = self.signaturesForArgCount(argCount)
+            if len(possibleSignatures) == 1:
+                continue
+            distinguishingIndex = self.distinguishingIndexForArgCount(argCount)
+            arglists = [ s[1] for s in possibleSignatures ]
+            for idx in range(distinguishingIndex):
+                firstSigType = arglists[0][idx].type
+                for (otherArgList, location) in zip(arglists[1:],
+                                                    self._location[1:]):
+                    if otherArgList[idx].type != firstSigType:
+                        raise WebIDLError(
+                            "Signatures for method '%s' with %d arguments have "
+                            "different types of arguments at index %d, which "
+                            "is before distinguishing index %d" %
+                            (self.identifier.name, argCount, idx,
+                             distinguishingIndex),
+                            self.location,
+                            extraLocations=[location])
+
+    def signaturesForArgCount(self, argc):
+        return [(retval, args) for (retval, args) in self.signatures() if
+                len(args) == argc or (len(args) > argc and args[argc].optional)]
+
+    def locationsForArgCount(self, argc):
+        return [ self._location[i] for (i, args) in enumerate(self._arguments) if
+                 len(args) == argc or
+                 (len(args) > argc and args[argc].optional)]
+
+    def distinguishingIndexForArgCount(self, argc):
+        def isValidDistinguishingIndex(idx, signatures):
+            for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]):
+                for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]:
+                    firstType = firstArgs[idx].type
+                    secondType = secondArgs[idx].type
+                    if not firstType.isDistinguishableFrom(secondType):
+                        return False
+            return True
+        signatures = self.signaturesForArgCount(argc)
+        for idx in range(argc):
+            if isValidDistinguishingIndex(idx, signatures):
+                return idx
+        # No valid distinguishing index.  Time to throw
+        locations = self.locationsForArgCount(argc)
+        raise WebIDLError("Signatures with %d arguments for method '%s' are not "
+                          "distinguishable" % (argc, self.identifier.name),
+                          locations[0],
+                          extraLocations=locations[1:])
+
 class IDLImplementsStatement(IDLObject):
     def __init__(self, location, implementor, implementee):
         IDLObject.__init__(self, location)
         self.implementor = implementor;
         self.implementee = implementee
 
     def finish(self, scope):
         assert(isinstance(self.implementor, IDLIdentifierPlaceholder))
         assert(isinstance(self.implementee, IDLIdentifierPlaceholder))
         implementor = self.implementor.finish(scope)
         implementee = self.implementee.finish(scope)
+        # NOTE: we depend on not setting self.implementor and
+        # self.implementee here to keep track of the original
+        # locations.
+        if not isinstance(implementor, IDLInterface):
+            raise WebIDLError("Left-hand side of 'implements' is not an "
+                              "interface",
+                              self.implementor.location)
+        if implementor.isCallback():
+            raise WebIDLError("Left-hand side of 'implements' is a callback "
+                              "interface",
+                              self.implementor.location)
+        if not isinstance(implementee, IDLInterface):
+            raise WebIDLError("Right-hand side of 'implements' is not an "
+                              "interface",
+                              self.implementee.location)
+        if implementee.isCallback():
+            raise WebIDLError("Right-hand side of 'implements' is a callback "
+                              "interface",
+                              self.implementee.location)
         implementor.addImplementedInterface(implementee)
 
+    def validate(self):
+        pass
+
     def addExtendedAttributes(self, attrs):
         assert len(attrs) == 0
 
 # Parser
 
 class Tokenizer(object):
     tokens = [
         "INTEGER",
@@ -3196,16 +3371,20 @@ class Parser(Tokenizer):
                                  isinstance(p, IDLImplementsStatement)]
         otherStatements = [ p for p in self._productions if
                             not isinstance(p, IDLImplementsStatement)]
         for production in implementsStatements:
             production.finish(self.globalScope())
         for production in otherStatements:
             production.finish(self.globalScope())
 
+        # Do any post-finish validation we need to do
+        for production in self._productions:
+            production.validate()
+
         # De-duplicate self._productions, without modifying its order.
         seen = set()
         result = []
         for p in self._productions:
             if p not in seen:
                 seen.add(p)
                 result.append(p)
         return result
--- a/dom/bindings/parser/tests/test_arraybuffer.py
+++ b/dom/bindings/parser/tests/test_arraybuffer.py
@@ -47,17 +47,16 @@ def WebIDLTest(parser, harness):
 
     members = iface.members
 
     def checkStuff(attr, method, t):
         harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Expect an IDLAttribute")
         harness.ok(isinstance(method, WebIDL.IDLMethod), "Expect an IDLMethod")
 
         harness.check(str(attr.type), t, "Expect an ArrayBuffer type")
-        print type(attr.type)
         harness.ok(attr.type.isSpiderMonkeyInterface(), "Should test as a js interface")
 
         (retType, arguments) = method.signatures()[0]
         harness.ok(retType.isVoid(), "Should have a void return type")
         harness.check(len(arguments), 4, "Expect 4 arguments")
 
         harness.check(str(arguments[0].type), t,  "Expect an ArrayBuffer type")
         harness.ok(arguments[0].type.isSpiderMonkeyInterface(), "Should test as a js interface")
--- a/dom/bindings/parser/tests/test_callback_interface.py
+++ b/dom/bindings/parser/tests/test_callback_interface.py
@@ -7,8 +7,41 @@ def WebIDLTest(parser, harness):
         };
     """)
 
     results = parser.finish()
 
     iface = results[0]
 
     harness.ok(iface.isCallback(), "Interface should be a callback")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface {
+            };
+            callback interface TestCallbackInterface : TestInterface {
+              attribute boolean bool;
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should not allow non-callback parent of callback interface")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface : TestCallbackInterface {
+            };
+            callback interface TestCallbackInterface {
+              attribute boolean bool;
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should not allow callback parent of non-callback interface")
+
--- a/dom/bindings/parser/tests/test_distinguishability.py
+++ b/dom/bindings/parser/tests/test_distinguishability.py
@@ -1,8 +1,11 @@
+def firstArgType(method):
+    return method.signatures()[0][1][0].type
+
 def WebIDLTest(parser, harness):
     parser.parse("""
       dictionary Dict {
       };
       callback interface Foo {
       };
       interface Bar {
         // Bit of a pain to get things that have dictionary types
@@ -12,22 +15,118 @@ def WebIDLTest(parser, harness):
     """)
     results = parser.finish()
 
     iface = results[2]
     harness.ok(iface.isInterface(), "Should have interface")
     dictMethod = iface.members[0]
     ifaceMethod = iface.members[1]
 
-    def firstArgType(method):
-        return method.signatures()[0][1][0].type
-
     dictType = firstArgType(dictMethod)
     ifaceType = firstArgType(ifaceMethod)
 
     harness.ok(dictType.isDictionary(), "Should have dictionary type");
     harness.ok(ifaceType.isInterface(), "Should have interface type");
     harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type");
 
     harness.ok(not dictType.isDistinguishableFrom(ifaceType),
                "Dictionary not distinguishable from callback interface")
     harness.ok(not ifaceType.isDistinguishableFrom(dictType),
                "Callback interface not distinguishable from dictionary")
+
+    parser = parser.reset()
+    parser.parse("""
+      interface TestIface {
+        void passKid(Kid arg);
+        void passParent(Parent arg);
+        void passGrandparent(Grandparent arg);
+        void passImplemented(Implemented arg);
+        void passImplementedParent(ImplementedParent arg);
+        void passUnrelated1(Unrelated1 arg);
+        void passUnrelated2(Unrelated2 arg);
+        void passArrayBuffer(ArrayBuffer arg);
+        void passArrayBuffer(ArrayBufferView arg);
+      };
+
+      interface Kid : Parent {};
+      interface Parent : Grandparent {};
+      interface Grandparent {};
+      interface Implemented : ImplementedParent {};
+      Parent implements Implemented;
+      interface ImplementedParent {};
+      interface Unrelated1 {};
+      interface Unrelated2 {};
+    """)
+    results = parser.finish()
+
+    iface = results[0]
+    harness.ok(iface.isInterface(), "Should have interface")
+    argTypes = [firstArgType(method) for method in iface.members]
+    unrelatedTypes = [firstArgType(method) for method in iface.members[-3:]]
+
+    for type1 in argTypes:
+        for type2 in argTypes:
+            distinguishable = (type1 is not type2 and
+                               (type1 in unrelatedTypes or
+                                type2 in unrelatedTypes))
+
+            harness.check(type1.isDistinguishableFrom(type2),
+                          distinguishable,
+                          "Type %s should %sbe distinguishable from type %s" %
+                          (type1, "" if distinguishable else "not ", type2))
+            harness.check(type2.isDistinguishableFrom(type1),
+                          distinguishable,
+                          "Type %s should %sbe distinguishable from type %s" %
+                          (type2, "" if distinguishable else "not ", type1))
+
+    parser = parser.reset()
+    parser.parse("""
+      interface Dummy {};
+      interface TestIface {
+        void method(long arg1, TestIface arg2);
+        void method(long arg1, long arg2);
+        void method(long arg1, Dummy arg2);
+        void method(DOMString arg1, DOMString arg2, DOMString arg3);
+      };
+    """)
+    results = parser.finish()
+    harness.check(len(results[1].members), 1,
+                  "Should look like we have one method")
+    harness.check(len(results[1].members[0].signatures()), 4,
+                  "Should have foid signatures")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+          interface Dummy {};
+          interface TestIface {
+            void method(long arg1, TestIface arg2);
+            void method(long arg1, long arg2);
+            void method(any arg1,  Dummy arg2);
+            void method(DOMString arg1, DOMString arg2, DOMString arg3);
+          };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Should throw when args before the distinguishing arg are not "
+               "all the same type")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+          interface Dummy {};
+          interface TestIface {
+            void method(long arg1, TestIface arg2);
+            void method(long arg1, long arg2);
+            void method(any arg1,  DOMString arg2);
+            void method(DOMString arg1, DOMString arg2, DOMString arg3);
+          };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should throw when there is no distinguishing index")
--- a/dom/bindings/parser/tests/test_error_lineno.py
+++ b/dom/bindings/parser/tests/test_error_lineno.py
@@ -12,17 +12,16 @@ interface Foo {
 /* This is also a comment. */
 interface ?"""
     try:
         parser.parse(input)
         results = parser.finish()
     except WebIDL.WebIDLError, e:
         threw = True
         lines = str(e).split('\n')
-        print lines
 
         harness.check(len(lines), 3, 'Expected number of lines in error message')
         harness.ok(lines[0].endswith('line 6:10'), 'First line of error should end with "line 6:10", but was "%s".' % lines[0])
         harness.check(lines[1], 'interface ?', 'Second line of error message is the line which caused the error.')
         harness.check(lines[2], ' ' * (len('interface ?') - 1) + '^',
                       'Correct column pointer in error message.')
 
     harness.ok(threw, "Should have thrown.")
--- a/dom/bindings/parser/tests/test_implements.py
+++ b/dom/bindings/parser/tests/test_implements.py
@@ -110,17 +110,17 @@ def WebIDLTest(parser, harness):
     except:
         threw = True
 
     harness.ok(threw, "Should have thrown on implemented interface and its "
                "ancestor duplicating member names")
 
     # Reset the parser so we can actually find things where we expect
     # them in the list
-    parser = WebIDL.Parser()
+    parser = parser.reset()
 
     # Diamonds should be allowed
     threw = False
     try:
         parser.parse("""
             P implements Q;
             P implements R;
             Q implements S;
@@ -136,8 +136,81 @@ def WebIDLTest(parser, harness):
     except:
         threw = True
 
     harness.ok(not threw, "Diamond inheritance is fine")
     harness.check(results[6].identifier.name, "S", "We should be looking at 'S'")
     harness.check(len(results[6].members), 1, "S should have one member")
     harness.check(results[6].members[0].identifier.name, "x",
                   "S's member should be 'x'")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface {
+            };
+            callback interface TestCallbackInterface {
+            };
+            TestInterface implements TestCallbackInterface;
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Should not allow callback interfaces on the right-hand side "
+               "of 'implements'")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface {
+            };
+            callback interface TestCallbackInterface {
+            };
+            TestCallbackInterface implements TestInterface;
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Should not allow callback interfaces on the left-hand side of "
+               "'implements'")
+    
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface {
+            };
+            dictionary Dict {
+            };
+            Dict implements TestInterface;
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Should not allow non-interfaces on the left-hand side "
+               "of 'implements'")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface TestInterface {
+            };
+            dictionary Dict {
+            };
+            TestInterface implements Dict;
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Should not allow non-interfaces on the right-hand side "
+               "of 'implements'")
+
--- a/dom/bindings/parser/tests/test_overload.py
+++ b/dom/bindings/parser/tests/test_overload.py
@@ -1,18 +1,18 @@
 import WebIDL
 
 def WebIDLTest(parser, harness):
     parser.parse("""
         interface TestOverloads {
           void basic();
           void basic(long arg1);
-          boolean abitharder(unsigned long foo);
+          boolean abitharder(TestOverloads foo);
           boolean abitharder(boolean foo);
-          void abitharder(long? foo);
+          void abitharder(ArrayBuffer? foo);
         };
     """)
 
     results = parser.finish()
 
     harness.ok(True, "TestOverloads interface parsed without error.")
     harness.check(len(results), 1, "Should be one production.")
     iface = results[0]
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -66,8 +66,12 @@ bindinggen_dependencies := \
 
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 check::
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON_PATH) $(PLY_INCLUDE) \
 	  $(srcdir)/../parser/runtests.py
+
+check-interactive:
+	PYTHONDONTWRITEBYTECODE=1 $(PYTHON_PATH) $(PLY_INCLUDE) \
+	  $(srcdir)/../parser/runtests.py -q
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -496,17 +496,17 @@ class ThreadLocalJSRuntime
     mRuntime = JS_NewRuntime(sRuntimeHeapSize);
     NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
 
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
-    mGlobal = JS_NewCompartmentAndGlobalObject(mContext, &sGlobalClass, NULL);
+    mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
     JS_SetGlobalObject(mContext, mGlobal);
     return NS_OK;
   }
 
  public:
   static ThreadLocalJSRuntime *Create()
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -518,16 +518,37 @@ bool
 TabParent::SendSelectionEvent(nsSelectionEvent& event)
 {
   mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
   mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
   event.seqno = ++mIMESeqno;
   return PBrowserParent::SendSelectionEvent(event);
 }
 
+/*static*/ TabParent*
+TabParent::GetFrom(nsFrameLoader* aFrameLoader)
+{
+  if (!aFrameLoader) {
+    return nsnull;
+  }
+  PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
+  return static_cast<TabParent*>(remoteBrowser);
+}
+
+/*static*/ TabParent*
+TabParent::GetFrom(nsIContent* aContent)
+{
+  nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent);
+  if (!loaderOwner) {
+    return nsnull;
+  }
+  nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
+  return GetFrom(frameLoader);
+}
+
 bool
 TabParent::RecvEndIMEComposition(const bool& aCancel,
                                  nsString* aComposition)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return true;
 
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -2,36 +2,36 @@
 /* vim: set sw=4 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_tabs_TabParent_h
 #define mozilla_tabs_TabParent_h
 
+#include "base/basictypes.h"
+
+#include "jsapi.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/PContentDialogParent.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
-
-#include "jsapi.h"
 #include "nsCOMPtr.h"
-#include "nsITabParent.h"
-#include "nsIBrowserDOMWindow.h"
-#include "nsWeakReference.h"
-#include "nsIDialogParamBlock.h"
 #include "nsIAuthPromptProvider.h"
+#include "nsIBrowserDOMWindow.h"
+#include "nsIDialogParamBlock.h"
 #include "nsISecureBrowserUI.h"
+#include "nsITabParent.h"
+#include "nsWeakReference.h"
 
-class nsFrameLoader;
-class nsIURI;
-class nsIDOMElement;
 struct gfxMatrix;
-
 struct JSContext;
 struct JSObject;
+class nsFrameLoader;
+class nsIDOMElement;
+class nsIURI;
 
 namespace mozilla {
 namespace dom {
 
 class ContentDialogParent : public PContentDialogParent {};
 
 class TabParent : public PBrowserParent 
                 , public nsITabParent 
@@ -149,16 +149,20 @@ public:
 
     void HandleDelayedDialogs();
 
     static TabParent *GetIMETabParent() { return mIMETabParent; }
     bool HandleQueryContentEvent(nsQueryContentEvent& aEvent);
     bool SendCompositionEvent(nsCompositionEvent& event);
     bool SendTextEvent(nsTextEvent& event);
     bool SendSelectionEvent(nsSelectionEvent& event);
+
+    static TabParent* GetFrom(nsFrameLoader* aFrameLoader);
+    static TabParent* GetFrom(nsIContent* aContent);
+
 protected:
     bool ReceiveMessage(const nsString& aMessage,
                         bool aSync,
                         const nsString& aJSON,
                         InfallibleTArray<nsString>* aJSONRetVal = nsnull);
 
     void ActorDestroy(ActorDestroyReason why);
 
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -256,16 +256,20 @@ static dom::ConstantSpec gWinProperties[
   // SetFilePointer methods
   INT_CONSTANT(FILE_BEGIN),
   INT_CONSTANT(FILE_CURRENT),
   INT_CONSTANT(FILE_END),
 
   // SetFilePointer error constant
   INT_CONSTANT(INVALID_SET_FILE_POINTER),
 
+  // MoveFile flags
+  INT_CONSTANT(MOVEFILE_COPY_ALLOWED),
+  INT_CONSTANT(MOVEFILE_REPLACE_EXISTING),
+
   // Errors
   INT_CONSTANT(ERROR_FILE_EXISTS),
   INT_CONSTANT(ERROR_FILE_NOT_FOUND),
   INT_CONSTANT(ERROR_ACCESS_DENIED),
 
   PROP_END
 };
 #endif // defined(XP_WIN)
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -904,18 +904,18 @@ JSObject*
 CreateDedicatedWorkerGlobalScope(JSContext* aCx)
 {
   using namespace mozilla::dom;
 
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   JS_ASSERT(worker);
 
   JSObject* global =
-    JS_NewCompartmentAndGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(),
-                                     GetWorkerPrincipal());
+    JS_NewGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(),
+                       GetWorkerPrincipal());
   if (!global) {
     return NULL;
   }
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(aCx, global)) {
     return NULL;
   }
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -122,17 +122,17 @@ nsresult CentralizedAdminPrefManagerInit
 
     JS_SetErrorReporter(autoconfig_cx, autoConfigErrorReporter);
 
     // Create a new Security Manger and set it for the new JS context
     nsCOMPtr<nsIXPCSecurityManager> secman =
         static_cast<nsIXPCSecurityManager*>(new AutoConfigSecMan());
     xpc->SetSecurityManagerForJSContext(autoconfig_cx, secman, 0);
 
-    autoconfig_glob = JS_NewCompartmentAndGlobalObject(autoconfig_cx, &global_class, NULL);
+    autoconfig_glob = JS_NewGlobalObject(autoconfig_cx, &global_class, NULL);
     if (autoconfig_glob) {
         JSAutoEnterCompartment ac;
         if(!ac.enter(autoconfig_cx, autoconfig_glob))
             return NS_ERROR_FAILURE;
         if (JS_InitStandardClasses(autoconfig_cx, autoconfig_glob)) {
             // XPCONNECT enable this JS context
             rv = xpc->InitClasses(autoconfig_cx, autoconfig_glob);
             if (NS_SUCCEEDED(rv)) 
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2258,17 +2258,16 @@ GLContext::UploadSurfaceToTexture(gfxASu
         // to the start of the data block.
         if (!aPixelBuffer) {
               data = imageSurface->Data();
         }
         data += DataOffset(imageSurface, aSrcPoint);
     }
 
     GLenum format;
-    GLenum internalformat;
     GLenum type;
     PRInt32 pixelSize = gfxASurface::BytePerPixelFromFormat(imageSurface->Format());
     ShaderProgramType shader;
 
     switch (imageSurface->Format()) {
         case gfxASurface::ImageFormatARGB32:
             format = LOCAL_GL_RGBA;
             type = LOCAL_GL_UNSIGNED_BYTE;
@@ -2296,18 +2295,16 @@ GLContext::UploadSurfaceToTexture(gfxASu
             NS_ASSERTION(false, "Unhandled image surface format!");
             format = 0;
             type = 0;
             shader = ShaderProgramType(0);
     }
 
     PRInt32 stride = imageSurface->Stride();
 
-    internalformat = mIsGLES2 ? format : LOCAL_GL_RGBA;
-
     nsIntRegionRectIterator iter(paintRegion);
     const nsIntRect *iterRect;
 
     // Top left point of the region's bounding rectangle.
     nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
 
     while ((iterRect = iter.Next())) {
         // The inital data pointer is at the top left point of the region's
@@ -2329,17 +2326,17 @@ GLContext::UploadSurfaceToTexture(gfxASu
                           stride,
                           pixelSize,
                           format,
                           type,
                           rectData);
         } else {
             TexImage2D(LOCAL_GL_TEXTURE_2D,
                        0,
-                       internalformat,
+                       format,
                        iterRect->width,
                        iterRect->height,
                        stride,
                        pixelSize,
                        0,
                        format,
                        type,
                        rectData);
--- a/gfx/skia/include/utils/mac/SkCGUtils.h
+++ b/gfx/skia/include/utils/mac/SkCGUtils.h
@@ -39,18 +39,16 @@ static inline CGImageRef SkCreateCGImage
 /**
  *  Draw the bitmap into the specified CG context. The bitmap will be converted
  *  to a CGImage using the generic RGB colorspace. (x,y) specifies the position
  *  of the top-left corner of the bitmap. The bitmap is converted using the
  *  colorspace returned by CGColorSpaceCreateDeviceRGB()
  */
 void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
 
-bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output);
-
 /**
  *  Return a provider that wraps the specified stream. It will become an
  *  owner of the stream, so the caller must still manage its ownership.
  *
  *  To hand-off ownership of the stream to the provider, the caller must do
  *  something like the following:
  *
  *  SkStream* stream = new ...;
new file mode 100644
--- /dev/null
+++ b/gfx/skia/patches/0015-Bug-766017-warnings.patch
@@ -0,0 +1,865 @@
+From: David Zbarsky <dzbarsky@gmail.com>
+Bug 766017 - Fix some skia warnings r=gw280
+
+diff --git a/gfx/skia/include/utils/mac/SkCGUtils.h b/gfx/skia/include/utils/mac/SkCGUtils.h
+--- a/gfx/skia/include/utils/mac/SkCGUtils.h
++++ b/gfx/skia/include/utils/mac/SkCGUtils.h
+@@ -39,18 +39,16 @@ static inline CGImageRef SkCreateCGImage
+ /**
+  *  Draw the bitmap into the specified CG context. The bitmap will be converted
+  *  to a CGImage using the generic RGB colorspace. (x,y) specifies the position
+  *  of the top-left corner of the bitmap. The bitmap is converted using the
+  *  colorspace returned by CGColorSpaceCreateDeviceRGB()
+  */
+ void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
+ 
+-bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output);
+-
+ /**
+  *  Return a provider that wraps the specified stream. It will become an
+  *  owner of the stream, so the caller must still manage its ownership.
+  *
+  *  To hand-off ownership of the stream to the provider, the caller must do
+  *  something like the following:
+  *
+  *  SkStream* stream = new ...;
+diff --git a/gfx/skia/src/core/SkAAClip.cpp b/gfx/skia/src/core/SkAAClip.cpp
+--- a/gfx/skia/src/core/SkAAClip.cpp
++++ b/gfx/skia/src/core/SkAAClip.cpp
+@@ -246,17 +246,17 @@ static void count_left_right_zeros(const
+             zeros = 0;
+         }
+         row += 2;
+         width -= n;
+     }
+     *riteZ = zeros;
+ }
+ 
+-#ifdef SK_DEBUG
++#if 0
+ static void test_count_left_right_zeros() {
+     static bool gOnce;
+     if (gOnce) {
+         return;
+     }
+     gOnce = true;
+ 
+     const uint8_t data0[] = {  0, 0,     10, 0xFF };
+@@ -1319,22 +1319,16 @@ bool SkAAClip::setPath(const SkPath& pat
+ }
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ 
+ typedef void (*RowProc)(SkAAClip::Builder&, int bottom,
+                         const uint8_t* rowA, const SkIRect& rectA,
+                         const uint8_t* rowB, const SkIRect& rectB);
+ 
+-static void sectRowProc(SkAAClip::Builder& builder, int bottom,
+-                        const uint8_t* rowA, const SkIRect& rectA,
+-                        const uint8_t* rowB, const SkIRect& rectB) {
+-    
+-}
+-
+ typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
+ 
+ static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
+     // Multiply
+     return SkMulDiv255Round(alphaA, alphaB);
+ }
+ 
+ static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
+@@ -1429,31 +1423,16 @@ private:
+ static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
+     if (rite == riteA) {
+         iter.next();
+         leftA = iter.left();
+         riteA = iter.right();
+     }
+ }
+ 
+-static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
+-    SkASSERT(min < max);
+-    SkASSERT(boundsMin < boundsMax);
+-    if (min >= boundsMax || max <= boundsMin) {
+-        return false;
+-    }
+-    if (min < boundsMin) {
+-        min = boundsMin;
+-    }
+-    if (max > boundsMax) {
+-        max = boundsMax;
+-    }
+-    return true;
+-}
+-
+ static void operatorX(SkAAClip::Builder& builder, int lastY,
+                       RowIter& iterA, RowIter& iterB,
+                       AlphaProc proc, const SkIRect& bounds) {
+     int leftA = iterA.left();
+     int riteA = iterA.right();
+     int leftB = iterB.left();
+     int riteB = iterB.right();
+ 
+@@ -1970,34 +1949,33 @@ static void small_bzero(void* dst, size_
+ static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
+     return SkMulDiv255Round(value, alpha);
+ }
+ static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
+     unsigned r = SkGetPackedR16(value);
+     unsigned g = SkGetPackedG16(value);
+     unsigned b = SkGetPackedB16(value);
+     return SkPackRGB16(SkMulDiv255Round(r, alpha),
+-                       SkMulDiv255Round(r, alpha),
+-                       SkMulDiv255Round(r, alpha));
++                       SkMulDiv255Round(g, alpha),
++                       SkMulDiv255Round(b, alpha));
+ }
+ static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
+     unsigned a = SkGetPackedA32(value);
+     unsigned r = SkGetPackedR32(value);
+     unsigned g = SkGetPackedG32(value);
+     unsigned b = SkGetPackedB32(value);
+     return SkPackARGB32(SkMulDiv255Round(a, alpha),
+                         SkMulDiv255Round(r, alpha),
+                         SkMulDiv255Round(g, alpha),
+                         SkMulDiv255Round(b, alpha));
+ }
+ 
+ template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
+                                  const uint8_t* SK_RESTRICT row, int rowN,
+                                  T* SK_RESTRICT dst) {
+-    SkDEBUGCODE(int accumulated = 0;)
+     for (;;) {
+         SkASSERT(rowN > 0);
+         SkASSERT(srcN > 0);
+         
+         int n = SkMin32(rowN, srcN);
+         unsigned rowA = row[1];
+         if (0xFF == rowA) {
+             small_memcpy(dst, src, n * sizeof(T));
+diff --git a/gfx/skia/src/core/SkBlitMask_D32.cpp b/gfx/skia/src/core/SkBlitMask_D32.cpp
+--- a/gfx/skia/src/core/SkBlitMask_D32.cpp
++++ b/gfx/skia/src/core/SkBlitMask_D32.cpp
+@@ -268,107 +268,49 @@ bool SkBlitMask::BlitColor(const SkBitma
+         return true;
+     }
+     return false;
+ }
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ 
+-static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+-                             const uint8_t* SK_RESTRICT mask,
+-                             const SkPMColor* SK_RESTRICT src, int count) {
+-    int i, octuple = (count + 7) >> 3;
+-    for (i = 0; i < octuple; ++i) {
+-        int m = *mask++;
+-        if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+-        if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
+-        if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
+-        if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
+-        if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
+-        if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
+-        if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
+-        if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
+-        src += 8;
+-        dst += 8;
+-    }
+-    count &= 7;
+-    if (count > 0) {
+-        int m = *mask;
+-        do {
+-            if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+-            m <<= 1;
+-            src += 1;
+-            dst += 1;
+-        } while (--count > 0);
+-    }
+-}
+-
+-static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+-                              const uint8_t* SK_RESTRICT mask,
+-                              const SkPMColor* SK_RESTRICT src, int count) {
+-    int i, octuple = (count + 7) >> 3;
+-    for (i = 0; i < octuple; ++i) {
+-        int m = *mask++;
+-        if (m & 0x80) { dst[0] = src[0]; }
+-        if (m & 0x40) { dst[1] = src[1]; }
+-        if (m & 0x20) { dst[2] = src[2]; }
+-        if (m & 0x10) { dst[3] = src[3]; }
+-        if (m & 0x08) { dst[4] = src[4]; }
+-        if (m & 0x04) { dst[5] = src[5]; }
+-        if (m & 0x02) { dst[6] = src[6]; }
+-        if (m & 0x01) { dst[7] = src[7]; }
+-        src += 8;
+-        dst += 8;
+-    }
+-    count &= 7;
+-    if (count > 0) {
+-        int m = *mask;
+-        do {
+-            if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+-            m <<= 1;
+-            src += 1;
+-            dst += 1;
+-        } while (--count > 0);
+-    }
+-}
+-
+ static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+                              const uint8_t* SK_RESTRICT mask,
+                              const SkPMColor* SK_RESTRICT src, int count) {
+     for (int i = 0; i < count; ++i) {
+         if (mask[i]) {
+             dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
+         }
+     }
+ }
+ 
+ // expand the steps that SkAlphaMulQ performs, but this way we can
+-//  exand.. add.. combine
++//  expand.. add.. combine
+ // instead of
+ // expand..combine add expand..combine
+ //
+ #define EXPAND0(v, m, s)    ((v) & (m)) * (s)
+ #define EXPAND1(v, m, s)    (((v) >> 8) & (m)) * (s)
+ #define COMBINE(e0, e1, m)  ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
+ 
+ static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+                               const uint8_t* SK_RESTRICT mask,
+                               const SkPMColor* SK_RESTRICT src, int count) {
+-    const uint32_t rbmask = gMask_00FF00FF;
+     for (int i = 0; i < count; ++i) {
+         int m = mask[i];
+         if (m) {
+             m += (m >> 7);
+ #if 1
+             // this is slightly slower than the expand/combine version, but it
+             // is much closer to the old results, so we use it for now to reduce
+             // rebaselining.
+             dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
+ #else
++            const uint32_t rbmask = gMask_00FF00FF;
+             uint32_t v = src[i];
+             uint32_t s0 = EXPAND0(v, rbmask, m);
+             uint32_t s1 = EXPAND1(v, rbmask, m);
+             v = dst[i];
+             uint32_t d0 = EXPAND0(v, rbmask, m);
+             uint32_t d1 = EXPAND1(v, rbmask, m);
+             dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
+ #endif
+@@ -559,17 +501,17 @@ SkBlitMask::RowProc SkBlitMask::RowFacto
+ // make this opt-in until chrome can rebaseline
+     RowProc proc = PlatformRowProcs(config, format, flags);
+     if (proc) {
+         return proc;
+     }
+ 
+     static const RowProc gProcs[] = {
+         // need X coordinate to handle BW
+-        NULL, NULL, //(RowProc)BW_RowProc_Blend,      (RowProc)BW_RowProc_Opaque,
++        NULL, NULL,
+         (RowProc)A8_RowProc_Blend,      (RowProc)A8_RowProc_Opaque,
+         (RowProc)LCD16_RowProc_Blend,   (RowProc)LCD16_RowProc_Opaque,
+         (RowProc)LCD32_RowProc_Blend,   (RowProc)LCD32_RowProc_Opaque,
+     };
+ 
+     int index;
+     switch (config) {
+         case SkBitmap::kARGB_8888_Config:
+diff --git a/gfx/skia/src/core/SkConcaveToTriangles.cpp b/gfx/skia/src/core/SkConcaveToTriangles.cpp
+--- a/gfx/skia/src/core/SkConcaveToTriangles.cpp
++++ b/gfx/skia/src/core/SkConcaveToTriangles.cpp
+@@ -37,17 +37,16 @@
+ #include "SkTDArray.h"
+ #include "SkGeometry.h"
+ #include "SkTSort.h"
+ 
+ // This is used to prevent runaway code bugs, and can probably be removed after
+ // the code has been proven robust.
+ #define kMaxCount 1000
+ 
+-#define DEBUG
+ #ifdef DEBUG
+ //------------------------------------------------------------------------------
+ // Debugging support
+ //------------------------------------------------------------------------------
+ 
+ #include <cstdio>
+ #include <stdarg.h>
+ 
+diff --git a/gfx/skia/src/core/SkPath.cpp b/gfx/skia/src/core/SkPath.cpp
+--- a/gfx/skia/src/core/SkPath.cpp
++++ b/gfx/skia/src/core/SkPath.cpp
+@@ -469,17 +469,16 @@ void SkPath::incReserve(U16CPU inc) {
+     fPts.setReserve(fPts.count() + inc);
+ 
+     SkDEBUGCODE(this->validate();)
+ }
+ 
+ void SkPath::moveTo(SkScalar x, SkScalar y) {
+     SkDEBUGCODE(this->validate();)
+ 
+-    int      vc = fVerbs.count();
+     SkPoint* pt;
+ 
+     // remember our index
+     fLastMoveToIndex = fPts.count();
+ 
+     pt = fPts.append();
+     *fVerbs.append() = kMove_Verb;
+     pt->set(x, y);
+@@ -1163,17 +1162,16 @@ void SkPath::reversePathTo(const SkPath&
+         }
+         pts -= gPtsInVerb[verbs[i]];
+     }
+ }
+ 
+ void SkPath::reverseAddPath(const SkPath& src) {
+     this->incReserve(src.fPts.count());
+ 
+-    const SkPoint* startPts = src.fPts.begin();
+     const SkPoint* pts = src.fPts.end();
+     const uint8_t* startVerbs = src.fVerbs.begin();
+     const uint8_t* verbs = src.fVerbs.end();
+ 
+     fIsOval = false;
+ 
+     bool needMove = true;
+     bool needClose = false;
+diff --git a/gfx/skia/src/core/SkRegion.cpp b/gfx/skia/src/core/SkRegion.cpp
+--- a/gfx/skia/src/core/SkRegion.cpp
++++ b/gfx/skia/src/core/SkRegion.cpp
+@@ -920,20 +920,16 @@ static int operate(const SkRegion::RunTy
+ /*  Given count RunTypes in a complex region, return the worst case number of
+     logical intervals that represents (i.e. number of rects that would be
+     returned from the iterator).
+  
+     We could just return count/2, since there must be at least 2 values per
+     interval, but we can first trim off the const overhead of the initial TOP
+     value, plus the final BOTTOM + 2 sentinels.
+  */
+-static int count_to_intervals(int count) {
+-    SkASSERT(count >= 6);   // a single rect is 6 values
+-    return (count - 4) >> 1;
+-}
+ 
+ /*  Given a number of intervals, what is the worst case representation of that
+     many intervals?
+  
+     Worst case (from a storage perspective), is a vertical stack of single
+     intervals:  TOP + N * (BOTTOM INTERVALCOUNT LEFT RIGHT SENTINEL) + SENTINEL
+  */
+ static int intervals_to_count(int intervals) {
+diff --git a/gfx/skia/src/core/SkScalerContext.cpp b/gfx/skia/src/core/SkScalerContext.cpp
+--- a/gfx/skia/src/core/SkScalerContext.cpp
++++ b/gfx/skia/src/core/SkScalerContext.cpp
+@@ -336,44 +336,16 @@ SK_ERROR:
+     glyph->fTop     = 0;
+     glyph->fWidth   = 0;
+     glyph->fHeight  = 0;
+     // put a valid value here, in case it was earlier set to
+     // MASK_FORMAT_JUST_ADVANCE
+     glyph->fMaskFormat = fRec.fMaskFormat;
+ }
+ 
+-static bool isLCD(const SkScalerContext::Rec& rec) {
+-    return SkMask::kLCD16_Format == rec.fMaskFormat ||
+-           SkMask::kLCD32_Format == rec.fMaskFormat;
+-}
+-
+-static uint16_t a8_to_rgb565(unsigned a8) {
+-    return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
+-}
+-
+-static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
+-    SkASSERT(SkBitmap::kA8_Config == src.config());
+-    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
+-
+-    const int width = dst.fBounds.width();
+-    const int height = dst.fBounds.height();
+-    const uint8_t* srcP = src.getAddr8(0, 0);
+-    size_t srcRB = src.rowBytes();
+-    uint16_t* dstP = (uint16_t*)dst.fImage;
+-    size_t dstRB = dst.fRowBytes;
+-    for (int y = 0; y < height; ++y) {
+-        for (int x = 0; x < width; ++x) {
+-            dstP[x] = a8_to_rgb565(srcP[x]);
+-        }
+-        srcP += srcRB;
+-        dstP = (uint16_t*)((char*)dstP + dstRB);
+-    }
+-}
+-
+ #define SK_FREETYPE_LCD_LERP    160
+ 
+ static int lerp(int start, int end) {
+     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
+     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
+ }
+ 
+ static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
+diff --git a/gfx/skia/src/core/SkScan_AntiPath.cpp b/gfx/skia/src/core/SkScan_AntiPath.cpp
+--- a/gfx/skia/src/core/SkScan_AntiPath.cpp
++++ b/gfx/skia/src/core/SkScan_AntiPath.cpp
+@@ -230,52 +230,16 @@ void SuperBlitter::blitH(int x, int y, i
+                          fOffsetX);
+ 
+ #ifdef SK_DEBUG
+     fRuns.assertValid(y & MASK, (1 << (8 - SHIFT)));
+     fCurrX = x + width;
+ #endif
+ }
+ 
+-static void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA,
+-                               int n, U8CPU riteA) {
+-    SkASSERT(leftA <= 0xFF);
+-    SkASSERT(riteA <= 0xFF);
+-
+-    int16_t* run = runs.fRuns;
+-    uint8_t* aa = runs.fAlpha;
+-
+-    if (ileft > 0) {
+-        run[0] = ileft;
+-        aa[0] = 0;
+-        run += ileft;
+-        aa += ileft;
+-    }
+-
+-    SkASSERT(leftA < 0xFF);
+-    if (leftA > 0) {
+-        *run++ = 1;
+-        *aa++ = leftA;
+-    }
+-
+-    if (n > 0) {
+-        run[0] = n;
+-        aa[0] = 0xFF;
+-        run += n;
+-        aa += n;
+-    }
+-
+-    SkASSERT(riteA < 0xFF);
+-    if (riteA > 0) {
+-        *run++ = 1;
+-        *aa++ = riteA;
+-    }
+-    run[0] = 0;
+-}
+-
+ void SuperBlitter::blitRect(int x, int y, int width, int height) {
+     SkASSERT(width > 0);
+     SkASSERT(height > 0);
+ 
+     // blit leading rows
+     while ((y & MASK)) {
+         this->blitH(x, y++, width);
+         if (--height <= 0) {
+diff --git a/gfx/skia/src/effects/SkGradientShader.cpp b/gfx/skia/src/effects/SkGradientShader.cpp
+--- a/gfx/skia/src/effects/SkGradientShader.cpp
++++ b/gfx/skia/src/effects/SkGradientShader.cpp
+@@ -865,45 +865,16 @@ bool Linear_Gradient::setContext(const S
+     } while (0)
+ 
+ namespace {
+ 
+ typedef void (*LinearShadeProc)(TileProc proc, SkFixed dx, SkFixed fx,
+                                 SkPMColor* dstC, const SkPMColor* cache,
+                                 int toggle, int count);
+ 
+-// This function is deprecated, and will be replaced by 
+-// shadeSpan_linear_vertical_lerp() once Chrome has been weaned off of it.
+-void shadeSpan_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx,
+-                               SkPMColor* SK_RESTRICT dstC,
+-                               const SkPMColor* SK_RESTRICT cache,
+-                               int toggle, int count) {
+-    if (proc == clamp_tileproc) {
+-        // Read out clamp values from beginning/end of the cache. No need to lerp
+-        // or dither
+-        if (fx < 0) {
+-            sk_memset32(dstC, cache[-1], count);
+-            return;
+-        } else if (fx > 0xFFFF) {
+-            sk_memset32(dstC, cache[Gradient_Shader::kCache32Count * 2], count);
+-            return;
+-        }
+-    }
+-
+-    // We're a vertical gradient, so no change in a span.
+-    // If colors change sharply across the gradient, dithering is
+-    // insufficient (it subsamples the color space) and we need to lerp.
+-    unsigned fullIndex = proc(fx);
+-    unsigned fi = fullIndex >> (16 - Gradient_Shader::kCache32Bits);
+-    sk_memset32_dither(dstC,
+-            cache[toggle + fi],
+-            cache[(toggle ^ Gradient_Shader::kDitherStride32) + fi],
+-            count);
+-}
+-
+ // Linear interpolation (lerp) is unnecessary if there are no sharp
+ // discontinuities in the gradient - which must be true if there are
+ // only 2 colors - but it's cheap.
+ void shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx,
+                                     SkPMColor* SK_RESTRICT dstC,
+                                     const SkPMColor* SK_RESTRICT cache,
+                                     int toggle, int count) {
+     if (proc == clamp_tileproc) {
+@@ -2131,16 +2102,18 @@ protected:
+         buffer.writePoint(fCenter);
+     }
+ 
+ private:
+     typedef Gradient_Shader INHERITED;
+     const SkPoint fCenter;
+ };
+ 
++#ifndef SK_SCALAR_IS_FLOAT 
++
+ #ifdef COMPUTE_SWEEP_TABLE
+ #define PI  3.14159265
+ static bool gSweepTableReady;
+ static uint8_t gSweepTable[65];
+ 
+ /*  Our table stores precomputed values for atan: [0...1] -> [0..PI/4]
+     We scale the results to [0..32]
+ */
+@@ -2168,20 +2141,23 @@ static const uint8_t gSweepTable[] = {
+     10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18,
+     19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26,
+     26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
+     32
+ };
+ static const uint8_t* build_sweep_table() { return gSweepTable; }
+ #endif
+ 
++#endif
++
+ // divide numer/denom, with a bias of 6bits. Assumes numer <= denom
+ // and denom != 0. Since our table is 6bits big (+1), this is a nice fit.
+ // Same as (but faster than) SkFixedDiv(numer, denom) >> 10
+ 
++#ifndef SK_SCALAR_IS_FLOAT
+ //unsigned div_64(int numer, int denom);
+ static unsigned div_64(int numer, int denom) {
+     SkASSERT(numer <= denom);
+     SkASSERT(numer > 0);
+     SkASSERT(denom > 0);
+ 
+     int nbits = SkCLZ(numer);
+     int dbits = SkCLZ(denom);
+@@ -2294,16 +2270,17 @@ static unsigned atan_0_90(SkFixed y, SkF
+         result = 64 - result;
+         // pin to 63
+         result -= result >> 6;
+     }
+ 
+     SkASSERT(result <= 63);
+     return result;
+ }
++#endif
+ 
+ //  returns angle in a circle [0..2PI) -> [0..255]
+ #ifdef SK_SCALAR_IS_FLOAT
+ static unsigned SkATan2_255(float y, float x) {
+     //    static const float g255Over2PI = 255 / (2 * SK_ScalarPI);
+     static const float g255Over2PI = 40.584510488433314f;
+     
+     float result = sk_float_atan2(y, x);
+diff --git a/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp b/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
+--- a/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
++++ b/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
+@@ -112,17 +112,17 @@ void BlitRect32_OpaqueWide_SSE2(SkPMColo
+ }
+ 
+ void ColorRect32_SSE2(SkPMColor* destination,
+                       int width, int height,
+                       size_t rowBytes, uint32_t color) {
+     if (0 == height || 0 == width || 0 == color) {
+         return;
+     }
+-    unsigned colorA = SkGetPackedA32(color);
++    //unsigned colorA = SkGetPackedA32(color);
+     //if (255 == colorA) {
+         //if (width < 31) {
+             //BlitRect32_OpaqueNarrow_SSE2(destination, width, height,
+                                          //rowBytes, color);
+         //} else {
+             //BlitRect32_OpaqueWide_SSE2(destination, width, height,
+                                        //rowBytes, color);
+         //}
+diff --git a/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp b/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
+--- a/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
++++ b/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
+@@ -75,20 +75,16 @@ static CGFloat CGRectGetMinY_inline(cons
+ static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
+     return rect.origin.y + rect.size.height;
+ }
+ 
+ static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
+     return rect.size.width;
+ }
+ 
+-static CGFloat CGRectGetHeight(const CGRect& rect) {
+-    return rect.size.height;
+-}
+-
+ ///////////////////////////////////////////////////////////////////////////////
+ 
+ static void sk_memset_rect32(uint32_t* ptr, uint32_t value, size_t width,
+                              size_t height, size_t rowBytes) {
+     SkASSERT(width);
+     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
+ 
+     if (width >= 32) {
+@@ -125,28 +121,30 @@ static void sk_memset_rect32(uint32_t* p
+                 *ptr++ = value;
+             } while (--w > 0);
+             ptr = (uint32_t*)((char*)ptr + rowBytes);
+             height -= 1;
+         }
+     }
+ }
+ 
++#if 0
+ // Potentially this should be made (1) public (2) optimized when width is small.
+ // Also might want 16 and 32 bit version
+ //
+ static void sk_memset_rect(void* ptr, U8CPU byte, size_t width, size_t height,
+                            size_t rowBytes) {
+     uint8_t* dst = (uint8_t*)ptr;
+     while (height) {
+         memset(dst, byte, width);
+         dst += rowBytes;
+         height -= 1;
+     }
+ }
++#endif
+ 
+ #include <sys/utsname.h>
+ 
+ typedef uint32_t CGRGBPixel;
+ 
+ static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
+     return pixel & 0xFF;
+ }
+@@ -250,23 +248,16 @@ static CGAffineTransform MatrixToCGAffin
+     return CGAffineTransformMake(ScalarToCG(matrix[SkMatrix::kMScaleX]) * sx,
+                                  -ScalarToCG(matrix[SkMatrix::kMSkewY]) * sy,
+                                  -ScalarToCG(matrix[SkMatrix::kMSkewX]) * sx,
+                                  ScalarToCG(matrix[SkMatrix::kMScaleY]) * sy,
+                                  ScalarToCG(matrix[SkMatrix::kMTransX]) * sx,
+                                  ScalarToCG(matrix[SkMatrix::kMTransY]) * sy);
+ }
+ 
+-static void CGAffineTransformToMatrix(const CGAffineTransform& xform, SkMatrix* matrix) {
+-    matrix->setAll(
+-                   CGToScalar(xform.a), CGToScalar(xform.c), CGToScalar(xform.tx),
+-                   CGToScalar(xform.b), CGToScalar(xform.d), CGToScalar(xform.ty),
+-                   0, 0, SK_Scalar1);
+-}
+-
+ static SkScalar getFontScale(CGFontRef cgFont) {
+     int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
+     return SkScalarInvert(SkIntToScalar(unitsPerEm));
+ }
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ 
+ #define BITMAP_INFO_RGB     (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
+@@ -1075,16 +1066,17 @@ static const uint8_t* getInverseTable(bo
+     if (!gInited) {
+         build_power_table(gWhiteTable, 1.5f);
+         build_power_table(gTable, 2.2f);
+         gInited = true;
+     }
+     return isWhite ? gWhiteTable : gTable;
+ }
+ 
++#ifdef SK_USE_COLOR_LUMINANCE
+ static const uint8_t* getGammaTable(U8CPU luminance) {
+     static uint8_t gGammaTables[4][256];
+     static bool gInited;
+     if (!gInited) {
+ #if 1
+         float start = 1.1;
+         float stop = 2.1;
+         for (int i = 0; i < 4; ++i) {
+@@ -1097,45 +1089,49 @@ static const uint8_t* getGammaTable(U8CP
+         build_power_table(gGammaTables[2], 1);
+         build_power_table(gGammaTables[3], 1);
+ #endif
+         gInited = true;
+     }
+     SkASSERT(0 == (luminance >> 8));
+     return gGammaTables[luminance >> 6];
+ }
++#endif
+ 
++#ifndef SK_USE_COLOR_LUMINANCE
+ static void invertGammaMask(bool isWhite, CGRGBPixel rgb[], int width,
+                             int height, size_t rb) {
+     const uint8_t* table = getInverseTable(isWhite);
+     for (int y = 0; y < height; ++y) {
+         for (int x = 0; x < width; ++x) {
+             uint32_t c = rgb[x];
+             int r = (c >> 16) & 0xFF;
+             int g = (c >>  8) & 0xFF;
+             int b = (c >>  0) & 0xFF;
+             rgb[x] = (table[r] << 16) | (table[g] << 8) | table[b];
+         }
+         rgb = (CGRGBPixel*)((char*)rgb + rb);
+     }
+ }
++#endif
+ 
+ static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
+     while (count > 0) {
+         uint8_t mask = 0;
+         for (int i = 7; i >= 0; --i) {
+             mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i;
+             if (0 == --count) {
+                 break;
+             }
+         }
+         *dst++ = mask;
+     }
+ }
+ 
++#ifdef SK_USE_COLOR_LUMINANCE
+ static int lerpScale(int dst, int src, int scale) {
+     return dst + (scale * (src - dst) >> 23);
+ }
+ 
+ static CGRGBPixel lerpPixel(CGRGBPixel dst, CGRGBPixel src,
+                             int scaleR, int scaleG, int scaleB) {
+     int sr = (src >> 16) & 0xFF;
+     int sg = (src >>  8) & 0xFF;
+@@ -1147,37 +1143,31 @@ static CGRGBPixel lerpPixel(CGRGBPixel d
+     int rr = lerpScale(dr, sr, scaleR);
+     int rg = lerpScale(dg, sg, scaleG);
+     int rb = lerpScale(db, sb, scaleB);
+     return (rr << 16) | (rg << 8) | rb;
+ }
+ 
+ static void lerpPixels(CGRGBPixel dst[], const CGRGBPixel src[], int width,
+                        int height, int rowBytes, int lumBits) {
+-#ifdef SK_USE_COLOR_LUMINANCE
+     int scaleR = (1 << 23) * SkColorGetR(lumBits) / 0xFF;
+     int scaleG = (1 << 23) * SkColorGetG(lumBits) / 0xFF;
+     int scaleB = (1 << 23) * SkColorGetB(lumBits) / 0xFF;
+-#else
+-    int scale = (1 << 23) * lumBits / SkScalerContext::kLuminance_Max;
+-    int scaleR = scale;
+-    int scaleG = scale;
+-    int scaleB = scale;
+-#endif
+ 
+     for (int y = 0; y < height; ++y) {
+         for (int x = 0; x < width; ++x) {
+             // bit-not the src, since it was drawn from black, so we need the
+             // compliment of those bits
+             dst[x] = lerpPixel(dst[x], ~src[x], scaleR, scaleG, scaleB);
+         }
+         src = (CGRGBPixel*)((char*)src + rowBytes);
+         dst = (CGRGBPixel*)((char*)dst + rowBytes);
+     }
+ }
++#endif
+ 
+ #if 1
+ static inline int r32_to_16(int x) { return SkR32ToR16(x); }
+ static inline int g32_to_16(int x) { return SkG32ToG16(x); }
+ static inline int b32_to_16(int x) { return SkB32ToB16(x); }
+ #else
+ static inline int round8to5(int x) {
+     return (x + 3 - (x >> 5) + (x >> 7)) >> 3;
+@@ -1212,22 +1202,21 @@ static inline uint32_t rgb_to_lcd32(CGRG
+     return SkPackARGB32(0xFF, r, g, b);
+ }
+ 
+ #define BLACK_LUMINANCE_LIMIT   0x40
+ #define WHITE_LUMINANCE_LIMIT   0xA0
+ 
+ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
+     CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
+-
+     const bool isLCD = isLCDFormat(glyph.fMaskFormat);
++#ifdef SK_USE_COLOR_LUMINANCE
+     const bool isBW = SkMask::kBW_Format == glyph.fMaskFormat;
+     const bool isA8 = !isLCD && !isBW;
+-    
+-#ifdef SK_USE_COLOR_LUMINANCE
++
+     unsigned lumBits = fRec.getLuminanceColor();
+     uint32_t xorMask = 0;
+ 
+     if (isA8) {
+         // for A8, we just want a component (they're all the same)
+         lumBits = SkColorGetR(lumBits);
+     }
+ #else
+diff --git a/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp b/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
+--- a/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
++++ b/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
+@@ -163,59 +163,8 @@ private:
+     CGPDFDocumentRef fDoc;
+ };
+ 
+ static void CGDataProviderReleaseData_FromMalloc(void*, const void* data,
+                                                  size_t size) {
+     sk_free((void*)data);
+ }
+ 
+-bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
+-    size_t size = stream->getLength();
+-    void* ptr = sk_malloc_throw(size);
+-    stream->read(ptr, size);
+-    CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size,
+-                                          CGDataProviderReleaseData_FromMalloc);
+-    if (NULL == data) {
+-        return false;
+-    }
+-    
+-    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
+-    CGDataProviderRelease(data);
+-    if (NULL == pdf) {
+-        return false;
+-    }
+-    SkAutoPDFRelease releaseMe(pdf);
+-
+-    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
+-    if (NULL == page) {
+-        return false;
+-    }
+-    
+-    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
+-    
+-    int w = (int)CGRectGetWidth(bounds);
+-    int h = (int)CGRectGetHeight(bounds);
+-        
+-    SkBitmap bitmap;
+-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
+-    bitmap.allocPixels();
+-    bitmap.eraseColor(SK_ColorWHITE);
+-
+-    size_t bitsPerComponent;
+-    CGBitmapInfo info;
+-    getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL); 
+-
+-    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
+-    CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h,
+-                                             bitsPerComponent, bitmap.rowBytes(),
+-                                             cs, info);
+-    CGColorSpaceRelease(cs);
+-
+-    if (ctx) {
+-        CGContextDrawPDFPage(ctx, page);
+-        CGContextRelease(ctx);
+-    }
+-
+-    output->swap(bitmap);
+-    return true;
+-}
+-
--- a/gfx/skia/patches/README
+++ b/gfx/skia/patches/README
@@ -12,8 +12,9 @@ 0006-Bug-751814-ARM-EDSP-ARMv6-Skia-fixe
 0007-Bug-719872-Old-Android-FontHost.patch
 0008-Bug-687188-Skia-radial-gradients.patch
 0009-Bug-755869-FreeBSD-Hurd.patch
 0010-Bug-689069-ARM-Opts.patch
 0011-Bug-719575-Fix-clang-build.patch
 0012-Bug-759683-make-ssse3-conditional.patch
 0013-Bug-761890-fonts.patch
 0014-Bug-765038-Fix-clang-build.patch
+0015-Bug-766017-warnings.patch
--- a/gfx/skia/src/core/SkAAClip.cpp
+++ b/gfx/skia/src/core/SkAAClip.cpp
@@ -246,17 +246,17 @@ static void count_left_right_zeros(const
             zeros = 0;
         }
         row += 2;
         width -= n;
     }
     *riteZ = zeros;
 }
 
-#ifdef SK_DEBUG
+#if 0
 static void test_count_left_right_zeros() {
     static bool gOnce;
     if (gOnce) {
         return;
     }
     gOnce = true;
 
     const uint8_t data0[] = {  0, 0,     10, 0xFF };
@@ -1319,22 +1319,16 @@ bool SkAAClip::setPath(const SkPath& pat
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 typedef void (*RowProc)(SkAAClip::Builder&, int bottom,
                         const uint8_t* rowA, const SkIRect& rectA,
                         const uint8_t* rowB, const SkIRect& rectB);
 
-static void sectRowProc(SkAAClip::Builder& builder, int bottom,
-                        const uint8_t* rowA, const SkIRect& rectA,
-                        const uint8_t* rowB, const SkIRect& rectB) {
-    
-}
-
 typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
 
 static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
     // Multiply
     return SkMulDiv255Round(alphaA, alphaB);
 }
 
 static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
@@ -1429,31 +1423,16 @@ private:
 static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
     if (rite == riteA) {
         iter.next();
         leftA = iter.left();
         riteA = iter.right();
     }
 }
 
-static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
-    SkASSERT(min < max);
-    SkASSERT(boundsMin < boundsMax);
-    if (min >= boundsMax || max <= boundsMin) {
-        return false;
-    }
-    if (min < boundsMin) {
-        min = boundsMin;
-    }
-    if (max > boundsMax) {
-        max = boundsMax;
-    }
-    return true;
-}
-
 static void operatorX(SkAAClip::Builder& builder, int lastY,
                       RowIter& iterA, RowIter& iterB,
                       AlphaProc proc, const SkIRect& bounds) {
     int leftA = iterA.left();
     int riteA = iterA.right();
     int leftB = iterB.left();
     int riteB = iterB.right();
 
@@ -1970,34 +1949,33 @@ static void small_bzero(void* dst, size_
 static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
     return SkMulDiv255Round(value, alpha);
 }
 static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
     unsigned r = SkGetPackedR16(value);
     unsigned g = SkGetPackedG16(value);
     unsigned b = SkGetPackedB16(value);
     return SkPackRGB16(SkMulDiv255Round(r, alpha),
-                       SkMulDiv255Round(r, alpha),
-                       SkMulDiv255Round(r, alpha));
+                       SkMulDiv255Round(g, alpha),
+                       SkMulDiv255Round(b, alpha));
 }
 static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
     unsigned a = SkGetPackedA32(value);
     unsigned r = SkGetPackedR32(value);
     unsigned g = SkGetPackedG32(value);
     unsigned b = SkGetPackedB32(value);
     return SkPackARGB32(SkMulDiv255Round(a, alpha),
                         SkMulDiv255Round(r, alpha),
                         SkMulDiv255Round(g, alpha),
                         SkMulDiv255Round(b, alpha));
 }
 
 template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
                                  const uint8_t* SK_RESTRICT row, int rowN,
                                  T* SK_RESTRICT dst) {
-    SkDEBUGCODE(int accumulated = 0;)
     for (;;) {
         SkASSERT(rowN > 0);
         SkASSERT(srcN > 0);
         
         int n = SkMin32(rowN, srcN);
         unsigned rowA = row[1];
         if (0xFF == rowA) {
             small_memcpy(dst, src, n * sizeof(T));
--- a/gfx/skia/src/core/SkBlitMask_D32.cpp
+++ b/gfx/skia/src/core/SkBlitMask_D32.cpp
@@ -268,107 +268,49 @@ bool SkBlitMask::BlitColor(const SkBitma
         return true;
     }
     return false;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
-static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
-                             const uint8_t* SK_RESTRICT mask,
-                             const SkPMColor* SK_RESTRICT src, int count) {
-    int i, octuple = (count + 7) >> 3;
-    for (i = 0; i < octuple; ++i) {
-        int m = *mask++;
-        if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
-        if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
-        if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
-        if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
-        if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
-        if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
-        if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
-        if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
-        src += 8;
-        dst += 8;
-    }
-    count &= 7;
-    if (count > 0) {
-        int m = *mask;
-        do {
-            if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
-            m <<= 1;
-            src += 1;
-            dst += 1;
-        } while (--count > 0);
-    }
-}
-
-static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
-                              const uint8_t* SK_RESTRICT mask,
-                              const SkPMColor* SK_RESTRICT src, int count) {
-    int i, octuple = (count + 7) >> 3;
-    for (i = 0; i < octuple; ++i) {
-        int m = *mask++;
-        if (m & 0x80) { dst[0] = src[0]; }
-        if (m & 0x40) { dst[1] = src[1]; }
-        if (m & 0x20) { dst[2] = src[2]; }
-        if (m & 0x10) { dst[3] = src[3]; }
-        if (m & 0x08) { dst[4] = src[4]; }
-        if (m & 0x04) { dst[5] = src[5]; }
-        if (m & 0x02) { dst[6] = src[6]; }
-        if (m & 0x01) { dst[7] = src[7]; }
-        src += 8;
-        dst += 8;
-    }
-    count &= 7;
-    if (count > 0) {
-        int m = *mask;
-        do {
-            if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
-            m <<= 1;
-            src += 1;
-            dst += 1;
-        } while (--count > 0);
-    }
-}
-
 static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
                              const uint8_t* SK_RESTRICT mask,
                              const SkPMColor* SK_RESTRICT src, int count) {
     for (int i = 0; i < count; ++i) {
         if (mask[i]) {
             dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
         }
     }
 }
 
 // expand the steps that SkAlphaMulQ performs, but this way we can
-//  exand.. add.. combine
+//  expand.. add.. combine
 // instead of
 // expand..combine add expand..combine
 //
 #define EXPAND0(v, m, s)    ((v) & (m)) * (s)
 #define EXPAND1(v, m, s)    (((v) >> 8) & (m)) * (s)
 #define COMBINE(e0, e1, m)  ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
 
 static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
                               const uint8_t* SK_RESTRICT mask,
                               const SkPMColor* SK_RESTRICT src, int count) {
-    const uint32_t rbmask = gMask_00FF00FF;
     for (int i = 0; i < count; ++i) {
         int m = mask[i];
         if (m) {
             m += (m >> 7);
 #if 1
             // this is slightly slower than the expand/combine version, but it
             // is much closer to the old results, so we use it for now to reduce
             // rebaselining.
             dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
 #else
+            const uint32_t rbmask = gMask_00FF00FF;
             uint32_t v = src[i];
             uint32_t s0 = EXPAND0(v, rbmask, m);
             uint32_t s1 = EXPAND1(v, rbmask, m);
             v = dst[i];
             uint32_t d0 = EXPAND0(v, rbmask, m);
             uint32_t d1 = EXPAND1(v, rbmask, m);
             dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
 #endif
@@ -559,17 +501,17 @@ SkBlitMask::RowProc SkBlitMask::RowFacto
 // make this opt-in until chrome can rebaseline
     RowProc proc = PlatformRowProcs(config, format, flags);
     if (proc) {
         return proc;
     }
 
     static const RowProc gProcs[] = {
         // need X coordinate to handle BW
-        NULL, NULL, //(RowProc)BW_RowProc_Blend,      (RowProc)BW_RowProc_Opaque,
+        NULL, NULL,
         (RowProc)A8_RowProc_Blend,      (RowProc)A8_RowProc_Opaque,
         (RowProc)LCD16_RowProc_Blend,   (RowProc)LCD16_RowProc_Opaque,
         (RowProc)LCD32_RowProc_Blend,   (RowProc)LCD32_RowProc_Opaque,
     };
 
     int index;
     switch (config) {
         case SkBitmap::kARGB_8888_Config:
--- a/gfx/skia/src/core/SkConcaveToTriangles.cpp
+++ b/gfx/skia/src/core/SkConcaveToTriangles.cpp
@@ -37,17 +37,16 @@
 #include "SkTDArray.h"
 #include "SkGeometry.h"
 #include "SkTSort.h"
 
 // This is used to prevent runaway code bugs, and can probably be removed after
 // the code has been proven robust.
 #define kMaxCount 1000
 
-#define DEBUG
 #ifdef DEBUG
 //------------------------------------------------------------------------------
 // Debugging support
 //------------------------------------------------------------------------------
 
 #include <cstdio>
 #include <stdarg.h>
 
--- a/gfx/skia/src/core/SkPath.cpp
+++ b/gfx/skia/src/core/SkPath.cpp
@@ -469,17 +469,16 @@ void SkPath::incReserve(U16CPU inc) {
     fPts.setReserve(fPts.count() + inc);
 
     SkDEBUGCODE(this->validate();)
 }
 
 void SkPath::moveTo(SkScalar x, SkScalar y) {
     SkDEBUGCODE(this->validate();)
 
-    int      vc = fVerbs.count();
     SkPoint* pt;
 
     // remember our index
     fLastMoveToIndex = fPts.count();
 
     pt = fPts.append();
     *fVerbs.append() = kMove_Verb;
     pt->set(x, y);
@@ -1163,17 +1162,16 @@ void SkPath::reversePathTo(const SkPath&
         }
         pts -= gPtsInVerb[verbs[i]];
     }
 }
 
 void SkPath::reverseAddPath(const SkPath& src) {
     this->incReserve(src.fPts.count());
 
-    const SkPoint* startPts = src.fPts.begin();
     const SkPoint* pts = src.fPts.end();
     const uint8_t* startVerbs = src.fVerbs.begin();
     const uint8_t* verbs = src.fVerbs.end();
 
     fIsOval = false;
 
     bool needMove = true;
     bool needClose = false;
--- a/gfx/skia/src/core/SkRegion.cpp
+++ b/gfx/skia/src/core/SkRegion.cpp
@@ -920,20 +920,16 @@ static int operate(const SkRegion::RunTy
 /*  Given count RunTypes in a complex region, return the worst case number of
     logical intervals that represents (i.e. number of rects that would be
     returned from the iterator).
  
     We could just return count/2, since there must be at least 2 values per
     interval, but we can first trim off the const overhead of the initial TOP
     value, plus the final BOTTOM + 2 sentinels.
  */
-static int count_to_intervals(int count) {
-    SkASSERT(count >= 6);   // a single rect is 6 values
-    return (count - 4) >> 1;
-}
 
 /*  Given a number of intervals, what is the worst case representation of that
     many intervals?
  
     Worst case (from a storage perspective), is a vertical stack of single
     intervals:  TOP + N * (BOTTOM INTERVALCOUNT LEFT RIGHT SENTINEL) + SENTINEL
  */
 static int intervals_to_count(int intervals) {
--- a/gfx/skia/src/core/SkScalerContext.cpp
+++ b/gfx/skia/src/core/SkScalerContext.cpp
@@ -336,44 +336,16 @@ SK_ERROR:
     glyph->fTop     = 0;
     glyph->fWidth   = 0;
     glyph->fHeight  = 0;
     // put a valid value here, in case it was earlier set to
     // MASK_FORMAT_JUST_ADVANCE
     glyph->fMaskFormat = fRec.fMaskFormat;
 }
 
-static bool isLCD(const SkScalerContext::Rec& rec) {
-    return SkMask::kLCD16_Format == rec.fMaskFormat ||
-           SkMask::kLCD32_Format == rec.fMaskFormat;
-}
-
-static uint16_t a8_to_rgb565(unsigned a8) {
-    return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
-}
-
-static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
-    SkASSERT(SkBitmap::kA8_Config == src.config());
-    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
-
-    const int width = dst.fBounds.width();
-    const int height = dst.fBounds.height();
-    const uint8_t* srcP = src.getAddr8(0, 0);
-    size_t srcRB = src.rowBytes();
-    uint16_t* dstP = (uint16_t*)dst.fImage;
-    size_t dstRB = dst.fRowBytes;
-    for (int y = 0; y < height; ++y) {
-        for (int x = 0; x < width; ++x) {
-            dstP[x] = a8_to_rgb565(srcP[x]);
-        }
-        srcP += srcRB;
-        dstP = (uint16_t*)((char*)dstP + dstRB);
-    }
-}
-
 #define SK_FREETYPE_LCD_LERP    160
 
 static int lerp(int start, int end) {
     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
 }
 
 static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
--- a/gfx/skia/src/core/SkScan_AntiPath.cpp
+++ b/gfx/skia/src/core/SkScan_AntiPath.cpp
@@ -230,52 +230,16 @@ void SuperBlitter::blitH(int x, int y, i
                          fOffsetX);
 
 #ifdef SK_DEBUG
     fRuns.assertValid(y & MASK, (1 << (8 - SHIFT)));
     fCurrX = x + width;
 #endif
 }
 
-static void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA,
-                               int n, U8CPU riteA) {
-    SkASSERT(leftA <= 0xFF);
-    SkASSERT(riteA <= 0xFF);
-
-    int16_t* run = runs.fRuns;
-    uint8_t* aa = runs.fAlpha;
-
-    if (ileft > 0) {
-        run[0] = ileft;
-        aa[0] = 0;
-        run += ileft;
-        aa += ileft;
-    }
-
-    SkASSERT(leftA < 0xFF);
-    if (leftA > 0) {
-        *run++ = 1;
-        *aa++ = leftA;
-    }
-
-    if (n > 0) {
-        run[0] = n;
-        aa[0] = 0xFF;
-        run += n;
-        aa += n;
-    }
-
-    SkASSERT(riteA < 0xFF);
-    if (riteA > 0) {
-        *run++ = 1;
-        *aa++ = riteA;
-    }
-    run[0] = 0;
-}
-
 void SuperBlitter::blitRect(int x, int y, int width, int height) {
     SkASSERT(width > 0);
     SkASSERT(height > 0);
 
     // blit leading rows
     while ((y & MASK)) {
         this->blitH(x, y++, width);
         if (--height <= 0) {
--- a/gfx/skia/src/effects/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/SkGradientShader.cpp
@@ -865,45 +865,16 @@ bool Linear_Gradient::setContext(const S
     } while (0)
 
 namespace {
 
 typedef void (*LinearShadeProc)(TileProc proc, SkFixed dx, SkFixed fx,
                                 SkPMColor* dstC, const SkPMColor* cache,
                                 int toggle, int count);
 
-// This function is deprecated, and will be replaced by 
-// shadeSpan_linear_vertical_lerp() once Chrome has been weaned off of it.
-void shadeSpan_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx,
-                               SkPMColor* SK_RESTRICT dstC,
-                               const SkPMColor* SK_RESTRICT cache,
-                               int toggle, int count) {
-    if (proc == clamp_tileproc) {
-        // Read out clamp values from beginning/end of the cache. No need to lerp
-        // or dither
-        if (fx < 0) {
-            sk_memset32(dstC, cache[-1], count);
-            return;
-        } else if (fx > 0xFFFF) {
-            sk_memset32(dstC, cache[Gradient_Shader::kCache32Count * 2], count);
-            return;
-        }
-    }
-
-    // We're a vertical gradient, so no change in a span.
-    // If colors change sharply across the gradient, dithering is
-    // insufficient (it subsamples the color space) and we need to lerp.
-    unsigned fullIndex = proc(fx);
-    unsigned fi = fullIndex >> (16 - Gradient_Shader::kCache32Bits);
-    sk_memset32_dither(dstC,
-            cache[toggle + fi],
-            cache[(toggle ^ Gradient_Shader::kDitherStride32) + fi],
-            count);
-}
-
 // Linear interpolation (lerp) is unnecessary if there are no sharp
 // discontinuities in the gradient - which must be true if there are
 // only 2 colors - but it's cheap.
 void shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx,
                                     SkPMColor* SK_RESTRICT dstC,
                                     const SkPMColor* SK_RESTRICT cache,
                                     int toggle, int count) {
     if (proc == clamp_tileproc) {
@@ -2131,16 +2102,18 @@ protected:
         buffer.writePoint(fCenter);
     }
 
 private:
     typedef Gradient_Shader INHERITED;
     const SkPoint fCenter;
 };
 
+#ifndef SK_SCALAR_IS_FLOAT 
+
 #ifdef COMPUTE_SWEEP_TABLE
 #define PI  3.14159265
 static bool gSweepTableReady;
 static uint8_t gSweepTable[65];
 
 /*  Our table stores precomputed values for atan: [0...1] -> [0..PI/4]
     We scale the results to [0..32]
 */
@@ -2168,20 +2141,23 @@ static const uint8_t gSweepTable[] = {
     10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18,
     19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26,
     26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
     32
 };
 static const uint8_t* build_sweep_table() { return gSweepTable; }
 #endif
 
+#endif
+
 // divide numer/denom, with a bias of 6bits. Assumes numer <= denom
 // and denom != 0. Since our table is 6bits big (+1), this is a nice fit.
 // Same as (but faster than) SkFixedDiv(numer, denom) >> 10
 
+#ifndef SK_SCALAR_IS_FLOAT
 //unsigned div_64(int numer, int denom);
 static unsigned div_64(int numer, int denom) {
     SkASSERT(numer <= denom);
     SkASSERT(numer > 0);
     SkASSERT(denom > 0);
 
     int nbits = SkCLZ(numer);
     int dbits = SkCLZ(denom);
@@ -2294,16 +2270,17 @@ static unsigned atan_0_90(SkFixed y, SkF
         result = 64 - result;
         // pin to 63
         result -= result >> 6;
     }
 
     SkASSERT(result <= 63);
     return result;
 }
+#endif
 
 //  returns angle in a circle [0..2PI) -> [0..255]
 #ifdef SK_SCALAR_IS_FLOAT
 static unsigned SkATan2_255(float y, float x) {
     //    static const float g255Over2PI = 255 / (2 * SK_ScalarPI);
     static const float g255Over2PI = 40.584510488433314f;
     
     float result = sk_float_atan2(y, x);
--- a/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
+++ b/gfx/skia/src/opts/SkBlitRect_opts_SSE2.cpp
@@ -112,17 +112,17 @@ void BlitRect32_OpaqueWide_SSE2(SkPMColo
 }
 
 void ColorRect32_SSE2(SkPMColor* destination,
                       int width, int height,
                       size_t rowBytes, uint32_t color) {
     if (0 == height || 0 == width || 0 == color) {
         return;
     }
-    unsigned colorA = SkGetPackedA32(color);
+    //unsigned colorA = SkGetPackedA32(color);
     //if (255 == colorA) {
         //if (width < 31) {
             //BlitRect32_OpaqueNarrow_SSE2(destination, width, height,
                                          //rowBytes, color);
         //} else {
             //BlitRect32_OpaqueWide_SSE2(destination, width, height,
                                        //rowBytes, color);
         //}
--- a/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
+++ b/gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
@@ -75,20 +75,16 @@ static CGFloat CGRectGetMinY_inline(cons
 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
     return rect.origin.y + rect.size.height;
 }
 
 static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
     return rect.size.width;
 }
 
-static CGFloat CGRectGetHeight(const CGRect& rect) {
-    return rect.size.height;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static void sk_memset_rect32(uint32_t* ptr, uint32_t value, size_t width,
                              size_t height, size_t rowBytes) {
     SkASSERT(width);
     SkASSERT(width * sizeof(uint32_t) <= rowBytes);
 
     if (width >= 32) {
@@ -125,28 +121,30 @@ static void sk_memset_rect32(uint32_t* p
                 *ptr++ = value;
             } while (--w > 0);
             ptr = (uint32_t*)((char*)ptr + rowBytes);
             height -= 1;
         }
     }
 }
 
+#if 0
 // Potentially this should be made (1) public (2) optimized when width is small.
 // Also might want 16 and 32 bit version
 //
 static void sk_memset_rect(void* ptr, U8CPU byte, size_t width, size_t height,
                            size_t rowBytes) {
     uint8_t* dst = (uint8_t*)ptr;
     while (height) {
         memset(dst, byte, width);
         dst += rowBytes;
         height -= 1;
     }
 }
+#endif
 
 #include <sys/utsname.h>
 
 typedef uint32_t CGRGBPixel;
 
 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
     return pixel & 0xFF;
 }
@@ -250,23 +248,16 @@ static CGAffineTransform MatrixToCGAffin
     return CGAffineTransformMake(ScalarToCG(matrix[SkMatrix::kMScaleX]) * sx,
                                  -ScalarToCG(matrix[SkMatrix::kMSkewY]) * sy,
                                  -ScalarToCG(matrix[SkMatrix::kMSkewX]) * sx,
                                  ScalarToCG(matrix[SkMatrix::kMScaleY]) * sy,
                                  ScalarToCG(matrix[SkMatrix::kMTransX]) * sx,
                                  ScalarToCG(matrix[SkMatrix::kMTransY]) * sy);
 }
 
-static void CGAffineTransformToMatrix(const CGAffineTransform& xform, SkMatrix* matrix) {
-    matrix->setAll(
-                   CGToScalar(xform.a), CGToScalar(xform.c), CGToScalar(xform.tx),
-                   CGToScalar(xform.b), CGToScalar(xform.d), CGToScalar(xform.ty),
-                   0, 0, SK_Scalar1);
-}
-
 static SkScalar getFontScale(CGFontRef cgFont) {
     int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
     return SkScalarInvert(SkIntToScalar(unitsPerEm));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #define BITMAP_INFO_RGB     (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
@@ -1075,16 +1066,17 @@ static const uint8_t* getInverseTable(bo
     if (!gInited) {
         build_power_table(gWhiteTable, 1.5f);
         build_power_table(gTable, 2.2f);
         gInited = true;
     }
     return isWhite ? gWhiteTable : gTable;
 }
 
+#ifdef SK_USE_COLOR_LUMINANCE
 static const uint8_t* getGammaTable(U8CPU luminance) {
     static uint8_t gGammaTables[4][256];
     static bool gInited;
     if (!gInited) {
 #if 1
         float start = 1.1;
         float stop = 2.1;
         for (int i = 0; i < 4; ++i) {
@@ -1097,45 +1089,49 @@ static const uint8_t* getGammaTable(U8CP
         build_power_table(gGammaTables[2], 1);
         build_power_table(gGammaTables[3], 1);
 #endif
         gInited = true;
     }
     SkASSERT(0 == (luminance >> 8));
     return gGammaTables[luminance >> 6];
 }
+#endif
 
+#ifndef SK_USE_COLOR_LUMINANCE
 static void invertGammaMask(bool isWhite, CGRGBPixel rgb[], int width,
                             int height, size_t rb) {
     const uint8_t* table = getInverseTable(isWhite);
     for (int y = 0; y < height; ++y) {
         for (int x = 0; x < width; ++x) {
             uint32_t c = rgb[x];
             int r = (c >> 16) & 0xFF;
             int g = (c >>  8) & 0xFF;
             int b = (c >>  0) & 0xFF;
             rgb[x] = (table[r] << 16) | (table[g] << 8) | table[b];
         }
         rgb = (CGRGBPixel*)((char*)rgb + rb);
     }
 }
+#endif
 
 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
     while (count > 0) {
         uint8_t mask = 0;
         for (int i = 7; i >= 0; --i) {
             mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i;
             if (0 == --count) {
                 break;
             }
         }
         *dst++ = mask;
     }
 }
 
+#ifdef SK_USE_COLOR_LUMINANCE
 static int lerpScale(int dst, int src, int scale) {
     return dst + (scale * (src - dst) >> 23);
 }
 
 static CGRGBPixel lerpPixel(CGRGBPixel dst, CGRGBPixel src,
                             int scaleR, int scaleG, int scaleB) {
     int sr = (src >> 16) & 0xFF;
     int sg = (src >>  8) & 0xFF;
@@ -1147,37 +1143,31 @@ static CGRGBPixel lerpPixel(CGRGBPixel d
     int rr = lerpScale(dr, sr, scaleR);
     int rg = lerpScale(dg, sg, scaleG);
     int rb = lerpScale(db, sb, scaleB);
     return (rr << 16) | (rg << 8) | rb;
 }
 
 static void lerpPixels(CGRGBPixel dst[], const CGRGBPixel src[], int width,
                        int height, int rowBytes, int lumBits) {
-#ifdef SK_USE_COLOR_LUMINANCE
     int scaleR = (1 << 23) * SkColorGetR(lumBits) / 0xFF;
     int scaleG = (1 << 23) * SkColorGetG(lumBits) / 0xFF;
     int scaleB = (1 << 23) * SkColorGetB(lumBits) / 0xFF;
-#else
-    int scale = (1 << 23) * lumBits / SkScalerContext::kLuminance_Max;
-    int scaleR = scale;
-    int scaleG = scale;
-    int scaleB = scale;
-#endif
 
     for (int y = 0; y < height; ++y) {
         for (int x = 0; x < width; ++x) {
             // bit-not the src, since it was drawn from black, so we need the
             // compliment of those bits
             dst[x] = lerpPixel(dst[x], ~src[x], scaleR, scaleG, scaleB);
         }
         src = (CGRGBPixel*)((char*)src + rowBytes);
         dst = (CGRGBPixel*)((char*)dst + rowBytes);
     }
 }
+#endif
 
 #if 1
 static inline int r32_to_16(int x) { return SkR32ToR16(x); }
 static inline int g32_to_16(int x) { return SkG32ToG16(x); }
 static inline int b32_to_16(int x) { return SkB32ToB16(x); }
 #else
 static inline int round8to5(int x) {
     return (x + 3 - (x >> 5) + (x >> 7)) >> 3;
@@ -1212,22 +1202,21 @@ static inline uint32_t rgb_to_lcd32(CGRG
     return SkPackARGB32(0xFF, r, g, b);
 }
 
 #define BLACK_LUMINANCE_LIMIT   0x40
 #define WHITE_LUMINANCE_LIMIT   0xA0
 
 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
     CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
-
     const bool isLCD = isLCDFormat(glyph.fMaskFormat);
+#ifdef SK_USE_COLOR_LUMINANCE
     const bool isBW = SkMask::kBW_Format == glyph.fMaskFormat;
     const bool isA8 = !isLCD && !isBW;
-    
-#ifdef SK_USE_COLOR_LUMINANCE
+
     unsigned lumBits = fRec.getLuminanceColor();
     uint32_t xorMask = 0;
 
     if (isA8) {
         // for A8, we just want a component (they're all the same)
         lumBits = SkColorGetR(lumBits);
     }
 #else
--- a/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/gfx/skia/src/utils/mac/SkCreateCGImageRef.cpp
@@ -163,59 +163,8 @@ private:
     CGPDFDocumentRef fDoc;
 };
 
 static void CGDataProviderReleaseData_FromMalloc(void*, const void* data,
                                                  size_t size) {
     sk_free((void*)data);
 }
 
-bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
-    size_t size = stream->getLength();
-    void* ptr = sk_malloc_throw(size);
-    stream->read(ptr, size);
-    CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size,
-                                          CGDataProviderReleaseData_FromMalloc);
-    if (NULL == data) {
-        return false;
-    }
-    
-    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
-    CGDataProviderRelease(data);
-    if (NULL == pdf) {
-        return false;
-    }
-    SkAutoPDFRelease releaseMe(pdf);
-
-    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
-    if (NULL == page) {
-        return false;
-    }
-    
-    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
-    
-    int w = (int)CGRectGetWidth(bounds);
-    int h = (int)CGRectGetHeight(bounds);
-        
-    SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
-    bitmap.allocPixels();
-    bitmap.eraseColor(SK_ColorWHITE);
-
-    size_t bitsPerComponent;
-    CGBitmapInfo info;
-    getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL); 
-
-    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
-    CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h,
-                                             bitsPerComponent, bitmap.rowBytes(),
-                                             cs, info);
-    CGColorSpaceRelease(cs);
-
-    if (ctx) {
-        CGContextDrawPDFPage(ctx, page);
-        CGContextRelease(ctx);
-    }
-
-    output->swap(bitmap);
-    return true;
-}
-
--- a/js/ductwork/debugger/JSDebugger.h
+++ b/js/ductwork/debugger/JSDebugger.h
@@ -2,21 +2,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef COMPONENTS_JSDEBUGGER_H
 #define COMPONENTS_JSDEBUGGER_H
 
 #include "IJSDebugger.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace jsdebugger {
 
-class JSDebugger : public IJSDebugger
+class JSDebugger MOZ_FINAL : public IJSDebugger
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IJSDEBUGGER
 
   JSDebugger();
 
 private:
--- a/js/jsd/jsd_high.c
+++ b/js/jsd/jsd_high.c
@@ -103,17 +103,17 @@ static JSDContext*
 
     jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
     if( ! jsdc->dumbContext )
         goto label_newJSDContext_failure;
 
     JS_BeginRequest(jsdc->dumbContext);
     JS_SetOptions(jsdc->dumbContext, JS_GetOptions(jsdc->dumbContext));
 
-    jsdc->glob = JS_NewCompartmentAndGlobalObject(jsdc->dumbContext, &global_class, NULL);
+    jsdc->glob = JS_NewGlobalObject(jsdc->dumbContext, &global_class, NULL);
 
     if( ! jsdc->glob )
         goto label_newJSDContext_failure;
 
     call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
     if( ! call )
         goto label_newJSDContext_failure;
 
--- a/js/src/build/autoconf/android.m4
+++ b/js/src/build/autoconf/android.m4
@@ -93,16 +93,17 @@ case "$target" in
         if test -d "$android_platform" ; then
             AC_MSG_RESULT([$android_platform])
         else
             AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.])
         fi
     fi
 
     dnl set up compilers
+    TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-"
     AS="$android_toolchain"/bin/"$android_tool_prefix"-as
     CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc
     CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++
     CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp
     LD="$android_toolchain"/bin/"$android_tool_prefix"-ld
     AR="$android_toolchain"/bin/"$android_tool_prefix"-ar
     RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib
     STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -731,18 +731,18 @@ ifdef TIERS
 DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_dirs))
 STATIC_DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_staticdirs))
 endif
 
 OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
 
 CREATE_PRECOMPLETE_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/createprecomplete.py)
 
-EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py $(if $@,--depend $(MDDEPDIR)/$(basename $(@F)).pp --target $@)
-EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py $(if $@,--depend $(MDDEPDIR)/$(basename $(@F)).pp)
+EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp --target $@)
+EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp)
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -281,17 +281,17 @@ HOST_CMOBJS = $(addprefix host_,$(HOST_C
 HOST_CMMOBJS = $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
 ifndef HOST_OBJS
 _HOST_OBJS = $(HOST_COBJS) $(HOST_CCOBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
 HOST_OBJS = $(strip $(_HOST_OBJS))
 endif
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
-MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
+MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
 ifndef NO_GEN_XPT
 MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
 endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4203,17 +4203,17 @@ MOZ_ARG_DISABLE_BOOL(md,
      _cpp_md_flag=1
    fi
   dnl Default is to use -xM if using Sun Studio on Solaris
    if test "$SOLARIS_SUNPRO_CC"; then
      _cpp_md_flag=1
    fi])
 if test "$_cpp_md_flag"; then
   COMPILER_DEPEND=1
-  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(basename $(@F)).pp)'
+  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(@F).pp)'
   dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
   if test "$SOLARIS_SUNPRO_CC"; then
     _DEPEND_CFLAGS=
   fi
 else
   COMPILER_DEPEND=
   dnl Don't override this for MSVC
   if test -z "$_WIN32_MSVC"; then
@@ -4534,18 +4534,20 @@ if test "$OS_ARCH" = "Darwin"; then
   AC_DEFINE(XP_UNIX)
   AC_DEFINE(UNIX_ASYNC_DNS)
 elif test "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2"; then
   AC_DEFINE(XP_UNIX)
   AC_DEFINE(UNIX_ASYNC_DNS)
 fi
 
 AC_ARG_ENABLE(threadsafe,
-              [  --enable-threadsafe     Enable support for multiple threads.],
-              [AC_DEFINE(JS_THREADSAFE)],)
+    [  --enable-threadsafe     Enable support for multiple threads.],
+    [if test "x$enableval" = "xyes"; then
+        AC_DEFINE(JS_THREADSAFE)
+    fi],)
 
 if test "$MOZ_DEBUG"; then
     AC_DEFINE(MOZ_REFLOW_PERF)
     AC_DEFINE(MOZ_REFLOW_PERF_DSP)
 fi
 
 if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK2" ; then
     AC_DEFINE(MOZ_ACCESSIBILITY_ATK)
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -817,17 +817,16 @@ EmitAliasedVarOp(JSContext *cx, JSOp op,
      * the needsClone-subset of the block chain. Use this to determine the
      * number of ClonedBlockObjects on fp->scopeChain to skip to find the scope
      * object containing the var to which pn is bound. ALIASEDVAR ops cannot
      * reach across with scopes so ClonedBlockObjects is the only NestedScope
      * on the scope chain.
      */
     ScopeCoordinate sc;
     if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) {
-        JS_ASSERT(bce->sc->funIsHeavyweight());
         sc.hops = ClonedBlockDepth(bce);
         sc.slot = bce->sc->bindings.argToSlot(pn->pn_cookie.slot());
     } else {
         JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION));
         unsigned local = pn->pn_cookie.slot();
         if (local < bce->sc->bindings.numVars()) {
             sc.hops = ClonedBlockDepth(bce);
             sc.slot = bce->sc->bindings.localToSlot(local);
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1244,17 +1244,18 @@ GCMarker::processMarkStackTop(SliceBudge
         Class *clasp = shape->getObjectClass();
         if (clasp->trace) {
             if (clasp == &ArrayClass) {
                 JS_ASSERT(!shape->isNative());
                 vp = obj->getDenseArrayElements();
                 end = vp + obj->getDenseArrayInitializedLength();
                 goto scan_value_array;
             } else {
-                JS_ASSERT_IF(runtime->gcIncrementalState != NO_INCREMENTAL,
+                JS_ASSERT_IF(runtime->gcMode == JSGC_MODE_INCREMENTAL &&
+                             runtime->gcIncrementalEnabled,
                              clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS);
             }
             clasp->trace(this, obj);
         }
 
         if (!shape->isNative())
             return;
 
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -231,16 +231,23 @@ class StatisticsSerializer
             else if (*c != '(' && *c != ')')
                 p(*c);
             c++;
         }
         p("\"");
     }
 };
 
+/*
+ * If this fails, then you can either delete this assertion and allow all
+ * larger-numbered reasons to pile up in the last telemetry bucket, or switch
+ * to GC_REASON_3 and bump the max value.
+ */
+JS_STATIC_ASSERT(gcreason::NUM_TELEMETRY_REASONS >= gcreason::NUM_REASONS);
+
 static const char *
 ExplainReason(gcreason::Reason reason)
 {
     switch (reason) {
 #define SWITCH_REASON(name)                     \
         case gcreason::name:                    \
           return #name;
         GCREASONS(SWITCH_REASON)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug719750.js
@@ -0,0 +1,12 @@
+function f( )  {
+  var [ [x], e ]  = ["*", "/", "%"];
+    function h() {
+      for (var i = 0; i < 5; ++i) {
+        x = i * 2;
+      }
+    }
+    h();
+  assertEq(x, 8);
+} 
+f();
+
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug767234.js
@@ -0,0 +1,14 @@
+function gen()
+{
+    var local = new Date();
+    yield 1;
+    local = null;
+    gc();
+    gcslice(0);
+    yield 2;
+}
+
+var g = gen();
+g.next();
+g.next();
+gcslice();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug766064.js
@@ -0,0 +1,7 @@
+function loop(actual = 0)  {
+  if (function() { actual++ })
+  {}
+  return actual;
+}
+
+assertEq(loop(), 0);
--- a/js/src/jit-test/tests/debug/Debugger-debuggees-11.js
+++ b/js/src/jit-test/tests/debug/Debugger-debuggees-11.js
@@ -2,19 +2,16 @@
 // Don't allow cycles in the graph of the compartment "debugs" relation.
 
 load(libdir + "asserts.js");
 
 // trivial cycles
 var dbg = new Debugger;
 assertThrowsInstanceOf(function () { dbg.addDebuggee(this); }, TypeError);
 assertThrowsInstanceOf(function () { new Debugger(this); }, TypeError);
-var g = newGlobal('same-compartment');
-assertThrowsInstanceOf(function () { dbg.addDebuggee(g); }, TypeError);
-assertThrowsInstanceOf(function () { new Debugger(g); }, TypeError);
 
 // cycles of length 2
 var d1 = newGlobal('new-compartment');
 d1.top = this;
 d1.eval("var dbg = new Debugger(top)");
 assertThrowsInstanceOf(function () { dbg.addDebuggee(d1); }, TypeError);
 assertThrowsInstanceOf(function () { new Debugger(d1); }, TypeError);
 
--- a/js/src/jit-test/tests/debug/Object-seal-01.js
+++ b/js/src/jit-test/tests/debug/Object-seal-01.js
@@ -56,9 +56,8 @@ function test(code) {
 }
 
 test("{}");
 test("{a: [1], get b() { return -1; }}");
 test("Object.create(null, {x: {value: 3}, y: {get: Math.min}})");
 test("[]");
 test("[,,,,,]");
 test("[0, 1, 2]");
-test("newGlobal('same-compartment')");
--- a/js/src/jit-test/tests/debug/gc-05.js
+++ b/js/src/jit-test/tests/debug/gc-05.js
@@ -27,15 +27,15 @@ assertEq(xarr.length, N);
 // Try to make g2arr[i].eval eventually allocate a new object in the same
 // location as a previously gc'd object. If the object caches are not being
 // swept, the pointer coincidence will cause a Debugger.Object to be erroneously
 // reused.
 for (var i = 0; i < N; i++) {
     var obj = xarr[i];
     for (j = 0; j < M; j++) {
         assertEq(obj instanceof Debugger.Object, true);
-        g2arr[i].eval("x = x.__proto__ = {};");
-        obj = obj.proto;
+        g2arr[i].eval("x = x.prop = {};");
+        obj = obj.getOwnPropertyDescriptor("prop").value;;
         assertEq("seen" in obj, false);
         obj.seen = true;
         gc();
     }
 }
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -58,19 +58,19 @@ Wrap(JSContext *cx, JSObject *obj, JSObj
 {
     return js::Wrapper::New(cx, obj, proto, parent, &js::CrossCompartmentWrapper::singleton);
 }
 
 BEGIN_TEST(testBug604087)
 {
     JSObject *outerObj = js::Wrapper::New(cx, global, global->getProto(), global,
                                           &OuterWrapper::singleton);
-    JSObject *compartment2 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
-    JSObject *compartment3 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
-    JSObject *compartment4 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
+    JSObject *compartment2 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JSObject *compartment3 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JSObject *compartment4 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
 
     JSObject *c2wrapper = wrap(cx, outerObj, compartment2);
     CHECK(c2wrapper);
     js::SetProxyExtra(c2wrapper, 0, js::Int32Value(2));
 
     JSObject *c3wrapper = wrap(cx, outerObj, compartment3);
     CHECK(c3wrapper);
     js::SetProxyExtra(c3wrapper, 0, js::Int32Value(3));
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -30,33 +30,33 @@ CustomMethod(JSContext *cx, unsigned arg
 
   JS_SET_RVAL(cx, vp, JS_GetReservedSlot(thisObj, CUSTOM_SLOT));
   return true;
 }
 
 BEGIN_TEST(test_CallNonGenericMethodOnProxy)
 {
   // Create the first global object and compartment
-  JSObject *globalA = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
+  JSObject *globalA = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
   CHECK(globalA);
 
   JSObject *customA = JS_NewObject(cx, &CustomClass, NULL, NULL);
   CHECK(customA);
   JS_SetReservedSlot(customA, CUSTOM_SLOT, Int32Value(17));
 
   JSFunction *customMethodA = JS_NewFunction(cx, CustomMethod, 0, 0, customA, "customMethodA");
   CHECK(customMethodA);
 
   jsval rval;
   CHECK(JS_CallFunction(cx, customA, customMethodA, 0, NULL, &rval));
   CHECK_SAME(rval, Int32Value(17));
 
   // Now create the second global object and compartment...
   {
-    JSObject *globalB = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
+    JSObject *globalB = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
     CHECK(globalB);
 
     // ...and enter it.
     JSAutoEnterCompartment enter;
     CHECK(enter.enter(cx, globalB));
 
     JSObject *customB = JS_NewObject(cx, &CustomClass, NULL, NULL);
     CHECK(customB);
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -44,17 +44,17 @@ CallTrusted(JSContext *cx, unsigned argc
 
 BEGIN_TEST(testChromeBuffer)
 {
     JS_SetTrustedPrincipals(rt, &system_principals);
 
     JSFunction *fun;
     JSObject *o;
 
-    CHECK(o = JS_NewCompartmentAndGlobalObject(cx, &global_class, &system_principals));
+    CHECK(o = JS_NewGlobalObject(cx, &global_class, &system_principals));
     trusted_glob.set(o);
 
     /*
      * Check that, even after untrusted content has exhausted the stack, code
      * compiled with "trusted principals" can run using reserved trusted-only
      * buffer space.
      */
     {
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -145,17 +145,17 @@ BEGIN_TEST(testDebugger_throwHook)
     JS_SetOptions(cx, oldopts);
     return true;
 }
 END_TEST(testDebugger_throwHook)
 
 BEGIN_TEST(testDebugger_debuggerObjectVsDebugMode)
 {
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JSObject *debuggee = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
+    JSObject *debuggee = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
     CHECK(debuggee);
 
     {
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, debuggee));
         CHECK(JS_SetDebugMode(cx, true));
         CHECK(JS_InitStandardClasses(cx, debuggee));
     }
@@ -187,77 +187,62 @@ BEGIN_TEST(testDebugger_debuggerObjectVs
     return true;
 }
 END_TEST(testDebugger_debuggerObjectVsDebugMode)
 
 BEGIN_TEST(testDebugger_newScriptHook)
 {
     // Test that top-level indirect eval fires the newScript hook.
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JSObject *g1, *g2;
-    g1 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
-    CHECK(g1);
+    JSObject *g;
+    g = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    CHECK(g);
     {
         JSAutoEnterCompartment ae;
-        CHECK(ae.enter(cx, g1));
-        CHECK(JS_InitStandardClasses(cx, g1));
-        g2 = JS_NewGlobalObject(cx, getGlobalClass());
-        CHECK(g2);
-        CHECK(JS_InitStandardClasses(cx, g2));
+        CHECK(ae.enter(cx, g));
+        CHECK(JS_InitStandardClasses(cx, g));
     }
 
-    JSObject *g1Wrapper = g1;
-    CHECK(JS_WrapObject(cx, &g1Wrapper));
-    jsval v = OBJECT_TO_JSVAL(g1Wrapper);
-    CHECK(JS_SetProperty(cx, global, "g1", &v));
+    JSObject *gWrapper = g;
+    CHECK(JS_WrapObject(cx, &gWrapper));
+    jsval v = OBJECT_TO_JSVAL(gWrapper);
+    CHECK(JS_SetProperty(cx, global, "g", &v));
 
-    JSObject *g2Wrapper = g2;
-    CHECK(JS_WrapObject(cx, &g2Wrapper));
-    v = OBJECT_TO_JSVAL(g2Wrapper);
-    CHECK(JS_SetProperty(cx, global, "g2", &v));
-
-    EXEC("var dbg = Debugger(g1);\n"
+    EXEC("var dbg = Debugger(g);\n"
          "var hits = 0;\n"
          "dbg.onNewScript = function (s) {\n"
          "    hits += Number(s instanceof Debugger.Script);\n"
          "};\n");
 
-    // Since g1 is a debuggee and g2 is not, g1.eval should trigger newScript
-    // and g2.eval should not, regardless of what scope object we use to enter
-    // the compartment.
+    // Since g is a debuggee, g.eval should trigger newScript, regardless of
+    // what scope object we use to enter the compartment.
     //
-    // (Not all scripts are permanently associated with specific global
-    // objects, but eval scripts are, so we deliver them only to debuggers that
-    // are watching that particular global.)
+    // Scripts are associated with the global where they're compiled, so we
+    // deliver them only to debuggers that are watching that particular global.
     //
-    bool ok = true;
-    ok = ok && testIndirectEval(g1, g1, "Math.abs(0)", 1);
-    ok = ok && testIndirectEval(g2, g1, "Math.abs(1)", 1);
-    ok = ok && testIndirectEval(g1, g2, "Math.abs(-1)", 0);
-    ok = ok && testIndirectEval(g2, g2, "Math.abs(-2)", 0);
-    return ok;
+    return testIndirectEval(g, "Math.abs(0)");
 }
 
-bool testIndirectEval(JSObject *scope, JSObject *g, const char *code, int expectedHits)
+bool testIndirectEval(JSObject *scope, const char *code)
 {
     EXEC("hits = 0;");
 
     {
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, scope));
         JSString *codestr = JS_NewStringCopyZ(cx, code);
         CHECK(codestr);
         jsval argv[1] = { STRING_TO_JSVAL(codestr) };
         jsval v;
-        CHECK(JS_CallFunctionName(cx, g, "eval", 1, argv, &v));
+        CHECK(JS_CallFunctionName(cx, scope, "eval", 1, argv, &v));
     }
 
     jsval hitsv;
     EVAL("hits", &hitsv);
-    CHECK_SAME(hitsv, INT_TO_JSVAL(expectedHits));
+    CHECK_SAME(hitsv, INT_TO_JSVAL(1));
     return true;
 }
 END_TEST(testDebugger_newScriptHook)
 
 BEGIN_TEST(testDebugger_singleStepThrow)
     {
         CHECK(JS_SetDebugModeForCompartment(cx, cx->compartment, true));
         CHECK(JS_SetInterrupt(rt, onStep, NULL));
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -349,17 +349,17 @@ class JSAPITest
     }
 
     virtual JSClass * getGlobalClass() {
         return basicGlobalClass();
     }
 
     virtual JSObject * createGlobal(JSPrincipals *principals = NULL) {
         /* Create the global object. */
-        JSObject *global = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), principals);
+        JSObject *global = JS_NewGlobalObject(cx, getGlobalClass(), principals);
         if (!global)
             return NULL;
 
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, global))
             return NULL;
 
         /* Populate the global object with the standard globals,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -746,16 +746,17 @@ JSRuntime::JSRuntime()
     gcExactScanningEnabled(true),
     gcPoke(false),
     gcRunning(false),
 #ifdef JS_GC_ZEAL
     gcZeal_(0),
     gcZealFrequency(0),
     gcNextScheduled(0),
     gcDeterministicOnly(false),
+    gcIncrementalLimit(0),
 #endif
     gcCallback(NULL),
     gcSliceCallback(NULL),
     gcFinalizeCallback(NULL),
     gcMallocBytes(0),
     gcBlackRootsTraceOp(NULL),
     gcBlackRootsData(NULL),
     gcGrayRootsTraceOp(NULL),
@@ -1399,24 +1400,18 @@ Class dummy_class = {
 
 } /*namespace js */
 
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
-    GlobalObject *global = target->getGlobalObjectOrNull();
-    if (!global) {
-        SwitchToCompartment sc(cx, target->compartment());
-        global = GlobalObject::create(cx, &dummy_class);
-        if (!global)
-            return NULL;
-    }
-    return JS_EnterCrossCompartmentCall(cx, global);
+    GlobalObject &global = target->compartment()->global();
+    return JS_EnterCrossCompartmentCall(cx, &global);
 }
 
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
 
@@ -3312,26 +3307,16 @@ JS_PUBLIC_API(JSBool)
 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
 {
     AssertNoGC(cx);
     assertSameCompartment(cx, obj);
     *idp = OBJECT_TO_JSID(obj);
     return JS_TRUE;
 }
 
-JS_PUBLIC_API(JSObject *)
-JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
-{
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
-    AssertNoGC(cx);
-    CHECK_REQUEST(cx);
-
-    return GlobalObject::create(cx, Valueify(clasp));
-}
-
 class AutoHoldCompartment {
   public:
     explicit AutoHoldCompartment(JSCompartment *compartment JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : holdp(&compartment->hold)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
         *holdp = true;
     }
@@ -3340,32 +3325,34 @@ class AutoHoldCompartment {
         *holdp = false;
     }
   private:
     bool *holdp;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 JS_PUBLIC_API(JSObject *)
-JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
-{
-    AssertNoGC(cx);
-    CHECK_REQUEST(cx);
+JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
+{
+    AssertNoGC(cx);
+    CHECK_REQUEST(cx);
+    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+
     JSCompartment *compartment = NewCompartment(cx, principals);
     if (!compartment)
         return NULL;
 
     AutoHoldCompartment hold(compartment);
 
     JSCompartment *saved = cx->compartment;
     cx->setCompartment(compartment);
-    JSObject *obj = JS_NewGlobalObject(cx, clasp);
+    GlobalObject *global = GlobalObject::create(cx, Valueify(clasp));
     cx->setCompartment(saved);
 
-    return obj;
+    return global;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
@@ -6688,17 +6675,20 @@ JS_SetGCZeal(JSContext *cx, uint8_t zeal
                    "N indicates \"zealousness\":\n"
                    "  0: no additional GCs\n"
                    "  1: additional GCs at common danger points\n"
                    "  2: GC every F allocations (default: 100)\n"
                    "  3: GC when the window paints (browser only)\n"
                    "  4: Verify write barriers between instructions\n"
                    "  5: Verify write barriers between paints\n"
                    "  6: Verify stack rooting (ignoring XML and Reflect)\n"
-                   "  7: Verify stack rooting (all roots)\n");
+                   "  7: Verify stack rooting (all roots)\n"
+                   "  8: Incremental GC in two slices: 1) mark roots 2) finish collection\n"
+                   "  9: Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
+                   " 10: Incremental GC in multiple slices\n");
         }
         const char *p = strchr(env, ',');
         zeal = atoi(env);
         frequency = p ? atoi(p + 1) : JS_DEFAULT_ZEAL_FREQ;
     }
 
     if (zeal == 0 && cx->runtime->gcVerifyData)
         VerifyBarriers(cx->runtime);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3930,20 +3930,17 @@ JS_GetConstructor(JSContext *cx, JSObjec
  * Get a unique identifier for obj, good for the lifetime of obj (even if it
  * is moved by a copying GC).  Return false on failure (likely out of memory),
  * and true with *idp containing the unique id on success.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_NewGlobalObject(JSContext *cx, JSClass *clasp);
-
-extern JS_PUBLIC_API(JSObject *)
-JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals);
+JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
 
 /* Queries the [[Extensible]] property of the object. */
 extern JS_PUBLIC_API(JSBool)
 JS_IsExtensible(JSObject *obj);
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -586,44 +586,53 @@ struct JSRuntime : js::RuntimeFriendFiel
     bool                gcRunning;
 
     /*
      * These options control the zealousness of the GC. The fundamental values
      * are gcNextScheduled and gcDebugCompartmentGC. At every allocation,
      * gcNextScheduled is decremented. When it reaches zero, we do either a
      * full or a compartmental GC, based on gcDebugCompartmentGC.
      *
-     * At this point, if gcZeal_ == 2 then gcNextScheduled is reset to the
-     * value of gcZealFrequency. Otherwise, no additional GCs take place.
+     * At this point, if gcZeal_ is one of the types that trigger periodic
+     * collection, then gcNextScheduled is reset to the value of
+     * gcZealFrequency. Otherwise, no additional GCs take place.
      *
      * You can control these values in several ways:
      *   - Pass the -Z flag to the shell (see the usage info for details)
      *   - Call gczeal() or schedulegc() from inside shell-executed JS code
      *     (see the help for details)
      *
      * If gzZeal_ == 1 then we perform GCs in select places (during MaybeGC and
      * whenever a GC poke happens). This option is mainly useful to embedders.
      *
      * We use gcZeal_ == 4 to enable write barrier verification. See the comment
      * in jsgc.cpp for more information about this.
+     *
+     * gcZeal_ values from 8 to 10 periodically run different types of
+     * incremental GC.
      */
 #ifdef JS_GC_ZEAL
     int                 gcZeal_;
     int                 gcZealFrequency;
     int                 gcNextScheduled;
     bool                gcDeterministicOnly;
+    int                 gcIncrementalLimit;
 
     js::Vector<JSObject *, 0, js::SystemAllocPolicy> gcSelectedForMarking;
 
     int gcZeal() { return gcZeal_; }
 
     bool needZealousGC() {
         if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
-            if (gcZeal() == js::gc::ZealAllocValue)
+            if (gcZeal() == js::gc::ZealAllocValue ||
+                (gcZeal() >= js::gc::ZealIncrementalRootsThenFinish &&
+                 gcZeal() <= js::gc::ZealIncrementalMultipleSlices))
+            {
                 gcNextScheduled = gcZealFrequency;
+            }
             return true;
         }
         return false;
     }
 #else
     int gcZeal() { return 0; }
     bool needZealousGC() { return false; }
 #endif
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -219,18 +219,23 @@ class AutoPtr
 
 #ifdef DEBUG
 class CompartmentChecker
 {
     JSContext *context;
     JSCompartment *compartment;
 
   public:
-    explicit CompartmentChecker(JSContext *cx) : context(cx), compartment(cx->compartment) {
-        check(cx->hasfp() ? JS_GetGlobalForScopeChain(cx) : cx->globalObject);
+    explicit CompartmentChecker(JSContext *cx)
+      : context(cx), compartment(cx->compartment)
+    {
+        if (cx->compartment) {
+            GlobalObject *global = GetGlobalForScopeChain(cx);
+            JS_ASSERT(cx->compartment->global() == *global);
+        }
     }
 
     /*
      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      * compartment mismatches.
      */
     static void fail(JSCompartment *c1, JSCompartment *c2) {
         printf("*** Compartment mismatch %p vs. %p\n", (void *) c1, (void *) c2);
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -37,22 +37,24 @@
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
 JSCompartment::JSCompartment(JSRuntime *rt)
   : rt(rt),
     principals(NULL),
+    global_(NULL),
     needsBarrier_(false),
     gcState(NoGCScheduled),
     gcPreserveCode(false),
     gcBytes(0),
     gcTriggerBytes(0),
     hold(false),
+    isSystemCompartment(false),
     lastCodeRelease(0),
     typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     data(NULL),
     active(false),
     lastAnimationTime(0),
     regExps(rt),
     propertyTree(thisForCtor()),
     emptyTypeObject(NULL),
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -117,16 +117,30 @@ namespace js {
 class AutoDebugModeGC;
 }
 
 struct JSCompartment
 {
     JSRuntime                    *rt;
     JSPrincipals                 *principals;
 
+  private:
+    js::GlobalObject             *global_;
+  public:
+    js::GlobalObject &global() const {
+        JS_ASSERT(global_->compartment() == this);
+        return *global_;
+    }
+
+    void initGlobal(js::GlobalObject &global) {
+        JS_ASSERT(!global_);
+        global_ = &global;
+    }
+
+  public:
     js::gc::ArenaLists           arenas;
 
   private:
     bool                         needsBarrier_;
   public:
 
     bool needsBarrier() const {
         return needsBarrier_;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -598,17 +598,25 @@ SizeOfJSContext();
 namespace gcreason {
 
 /* GCReasons will end up looking like JSGC_MAYBEGC */
 enum Reason {
 #define MAKE_REASON(name) name,
     GCREASONS(MAKE_REASON)
 #undef MAKE_REASON
     NO_REASON,
-    NUM_REASONS
+    NUM_REASONS,
+
+    /*
+     * For telemetry, we want to keep a fixed max bucket size over time so we
+     * don't have to switch histograms. 100 is conservative; as of this writing
+     * there are 26. But the cost of extra buckets seems to be low while the
+     * cost of switching histograms is high.
+     */
+    NUM_TELEMETRY_REASONS = 100
 };
 
 } /* namespace gcreason */
 
 extern JS_FRIEND_API(void)
 PrepareCompartmentForGC(JSCompartment *comp);
 
 extern JS_FRIEND_API(void)
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3482,29 +3482,16 @@ SweepPhase(JSRuntime *rt, JSGCInvocation
         if (rt->gcFinalizeCallback)
             rt->gcFinalizeCallback(&fop, JSFINALIZE_END, !isFull);
     }
 
     for (CompartmentsIter c(rt); !c.done(); c.next())
         c->setGCLastBytes(c->gcBytes, c->gcMallocAndFreeBytes, gckind);
 }
 
-static void
-NonIncrementalMark(JSRuntime *rt, JSGCInvocationKind gckind)
-{
-    JS_ASSERT(rt->gcIncrementalState == NO_INCREMENTAL);
-    BeginMarkPhase(rt);
-    {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
-        SliceBudget budget;
-        rt->gcMarker.drainMarkStack(budget);
-    }
-    EndMarkPhase(rt);
-}
-
 /*
  * This class should be used by any code that needs to exclusive access to the
  * heap in order to trace through it...
  */
 class AutoHeapSession {
   public:
     explicit AutoHeapSession(JSRuntime *rt);
     ~AutoHeapSession();
@@ -3649,33 +3636,46 @@ class AutoCopyFreeListToArenas {
 
     ~AutoCopyFreeListToArenas() {
         for (CompartmentsIter c(rt); !c.done(); c.next())
             c->arenas.clearFreeListsInArenas();
     }
 };
 
 static void
-IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, bool *shouldSweep)
+IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, bool *shouldSweep)
 {
     AutoGCSlice slice(rt);
 
     gc::State initialState = rt->gcIncrementalState;
 
+    *shouldSweep = false;
+
+    int zeal = 0;
+#ifdef JS_GC_ZEAL
+    if (reason == gcreason::DEBUG_GC) {
+        // Do the collection type specified by zeal mode only if the collection
+        // was triggered by RunDebugGC().
+        zeal = rt->gcZeal();
+    }
+#endif
+
     if (rt->gcIncrementalState == NO_INCREMENTAL) {
         rt->gcIncrementalState = MARK_ROOTS;
         rt->gcLastMarkSlice = false;
     }
 
     if (rt->gcIncrementalState == MARK_ROOTS) {
         BeginMarkPhase(rt);
         rt->gcIncrementalState = MARK;
+
+        if (zeal == ZealIncrementalRootsThenFinish)
+            return;
     }
 
-    *shouldSweep = false;
     if (rt->gcIncrementalState == MARK) {
         SliceBudget sliceBudget(budget);
 
         /* If we needed delayed marking for gray roots, then collect until done. */
         if (!rt->gcMarker.hasBufferedGrayRoots())
             sliceBudget.reset();
 
 #ifdef JS_GC_ZEAL
@@ -3690,17 +3690,21 @@ IncrementalMarkSlice(JSRuntime *rt, int6
 
         bool finished;
         {
             gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
             finished = rt->gcMarker.drainMarkStack(sliceBudget);
         }
         if (finished) {
             JS_ASSERT(rt->gcMarker.isDrained());
-            if (initialState == MARK && !rt->gcLastMarkSlice && budget != SliceBudget::Unlimited) {
+
+            if (!rt->gcLastMarkSlice &&
+                ((initialState == MARK && budget != SliceBudget::Unlimited) ||
+                 zeal == ZealIncrementalMarkAllThenFinish))
+            {
                 rt->gcLastMarkSlice = true;
             } else {
                 EndMarkPhase(rt);
                 rt->gcIncrementalState = NO_INCREMENTAL;
                 *shouldSweep = true;
             }
         }
     }
@@ -3791,17 +3795,17 @@ BudgetIncrementalGC(JSRuntime *rt, int64
 
 /*
  * GC, repeatedly if necessary, until we think we have not created any new
  * garbage. We disable inlining to ensure that the bottom of the stack with
  * possible GC roots recorded in MarkRuntime excludes any pointers we use during
  * the marking implementation.
  */
 static JS_NEVER_INLINE void
-GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind)
+GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind, gcreason::Reason reason)
 {
 #ifdef DEBUG
     for (CompartmentsIter c(rt); !c.done(); c.next())
         JS_ASSERT_IF(rt->gcMode == JSGC_MODE_GLOBAL, c->isGCScheduled());
 #endif
 
     /* Recursive GC is no-op. */
     if (rt->gcRunning)
@@ -3829,27 +3833,23 @@ GCCycle(JSRuntime *rt, bool incremental,
     {
         AutoUnlockGC unlock(rt);
         AutoCopyFreeListToArenas copy(rt);
 
         if (!incremental) {
             /* If non-incremental GC was requested, reset incremental GC. */
             ResetIncrementalGC(rt, "requested");
             rt->gcStats.nonincremental("requested");
+            budget = SliceBudget::Unlimited;
         } else {
             BudgetIncrementalGC(rt, &budget);
         }
 
         bool shouldSweep;
-        if (budget == SliceBudget::Unlimited && rt->gcIncrementalState == NO_INCREMENTAL) {
-            NonIncrementalMark(rt, gckind);
-            shouldSweep = true;
-        } else {
-            IncrementalMarkSlice(rt, budget, gckind, &shouldSweep);
-        }
+        IncrementalMarkSlice(rt, budget, reason, &shouldSweep);
 
 #ifdef DEBUG
         if (rt->gcIncrementalState == NO_INCREMENTAL) {
             for (CompartmentsIter c(rt); !c.done(); c.next())
                 JS_ASSERT(!c->needsBarrier());
         }
 #endif
         if (shouldSweep)
@@ -3898,17 +3898,18 @@ Collect(JSRuntime *rt, bool incremental,
         return;
 #endif
 
     JS_ASSERT_IF(!incremental || budget != SliceBudget::Unlimited, JSGC_INCREMENTAL);
 
 #ifdef JS_GC_ZEAL
     bool restartVerify = rt->gcVerifyData &&
                          rt->gcZeal() == ZealVerifierValue &&
-                         reason != gcreason::CC_FORCED;
+                         reason != gcreason::CC_FORCED &&
+                         rt->hasContexts();
 
     struct AutoVerifyBarriers {
         JSRuntime *runtime;
         bool restart;
         AutoVerifyBarriers(JSRuntime *rt, bool restart)
           : runtime(rt), restart(restart)
         {
             if (rt->gcVerifyData)
@@ -3949,17 +3950,17 @@ Collect(JSRuntime *rt, bool incremental,
          */
         if (rt->gcIncrementalState == NO_INCREMENTAL) {
             gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_GC_BEGIN);
             if (JSGCCallback callback = rt->gcCallback)
                 callback(rt, JSGC_BEGIN);
         }
 
         rt->gcPoke = false;
-        GCCycle(rt, incremental, budget, gckind);
+        GCCycle(rt, incremental, budget, gckind, reason);
 
         if (rt->gcIncrementalState == NO_INCREMENTAL) {
             gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_GC_END);
             if (JSGCCallback callback = rt->gcCallback)
                 callback(rt, JSGC_END);
         }
 
         /* Need to re-schedule all compartments for GC. */
@@ -4181,18 +4182,42 @@ NewCompartment(JSContext *cx, JSPrincipa
     Foreground::delete_(compartment);
     return NULL;
 }
 
 void
 RunDebugGC(JSContext *cx)
 {
 #ifdef JS_GC_ZEAL
+    JSRuntime *rt = cx->runtime;
     PrepareForDebugGC(cx->runtime);
-    RunLastDitchGC(cx, gcreason::DEBUG_GC);
+
+    int type = rt->gcZeal();
+    if (type == ZealIncrementalRootsThenFinish ||
+        type == ZealIncrementalMarkAllThenFinish ||
+        type == ZealIncrementalMultipleSlices)
+    {
+        int64_t budget;
+        if (type == ZealIncrementalMultipleSlices) {
+            // Start with a small slice limit and double it every slice. This ensure that we get
+            // multiple slices, and collection runs to completion.
+            if (rt->gcIncrementalState == NO_INCREMENTAL)
+                rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
+            else
+                rt->gcIncrementalLimit *= 2;
+            budget = SliceBudget::WorkBudget(rt->gcIncrementalLimit);
+        } else {
+            // This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
+            budget = SliceBudget::Unlimited;
+        }
+        Collect(rt, true, budget, GC_NORMAL, gcreason::DEBUG_GC);
+    } else {
+        Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
+    }
+
 #endif
 }
 
 void
 SetDeterministicGC(JSContext *cx, bool enabled)
 {
 #ifdef JS_GC_ZEAL
     JSRuntime *rt = cx->runtime;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1076,16 +1076,19 @@ SetDeterministicGC(JSContext *cx, bool e
 
 const int ZealPokeValue = 1;
 const int ZealAllocValue = 2;
 const int ZealFrameGCValue = 3;
 const int ZealVerifierValue = 4;
 const int ZealFrameVerifierValue = 5;
 const int ZealStackRootingSafeValue = 6;
 const int ZealStackRootingValue = 7;
+const int ZealIncrementalRootsThenFinish = 8;
+const int ZealIncrementalMarkAllThenFinish = 9;
+const int ZealIncrementalMultipleSlices = 10;
 
 #ifdef JS_GC_ZEAL
 
 /* Check that write barriers have been used correctly. See jsgc.cpp. */
 void
 VerifyBarriers(JSRuntime *rt);
 
 void
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1429,16 +1429,17 @@ inline bool
 JSScript::ensureHasTypes(JSContext *cx)
 {
     return types || makeTypes(cx);
 }
 
 inline bool
 JSScript::ensureRanAnalysis(JSContext *cx, JSObject *scope)
 {
+    js::analyze::AutoEnterAnalysis aea(cx->compartment);
     JSScript *self = this;
     JS::SkipRoot root(cx, &self);
 
     if (!self->ensureHasTypes(cx))
         return false;
     if (!self->types->hasScope()) {
         js::RootedObject scopeRoot(cx, scope);
         if (!js::types::TypeScript::SetScope(cx, self, scope))
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1361,18 +1361,18 @@ GeneratorWriteBarrierPre(JSContext *cx, 
         MarkGeneratorFrame(comp->barrierTracer(), gen);
 }
 
 /*
  * Only mark generator frames/slots when the generator is not active on the
  * stack or closed. Barriers when copying onto the stack or closing preserve
  * gc invariants.
  */
-static bool
-GeneratorHasMarkableFrame(JSGenerator *gen)
+bool
+js::GeneratorHasMarkableFrame(JSGenerator *gen)
 {
     return gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN;
 }
 
 /*
  * When a generator is closed, the GC things reachable from the contained frame
  * and slots become unreachable and thus require a write barrier.
  */
@@ -1471,18 +1471,18 @@ js_NewGenerator(JSContext *cx)
     gen->obj.init(obj);
     gen->state = JSGEN_NEWBORN;
     gen->enumerators = NULL;
     gen->fp = genfp;
     gen->prevGenerator = NULL;
 
     /* Copy from the stack to the generator's floating frame. */
     gen->regs.rebaseFromTo(stackRegs, *genfp);
-    genfp->copyFrameAndValues<HeapValue, Value, StackFrame::DoPostBarrier>(
-                              cx, genvp, stackfp, stackvp, stackRegs.sp);
+    genfp->copyFrameAndValues<StackFrame::DoPostBarrier>(cx, (Value *)genvp, stackfp,
+                                                         stackvp, stackRegs.sp);
 
     obj->setPrivate(gen);
     return obj;
 }
 
 static void
 SetGeneratorClosed(JSContext *cx, JSGenerator *gen);
 
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=78:
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsiter_h___
 #define jsiter_h___
@@ -311,14 +311,21 @@ struct JSGenerator
     JSObject            *enumerators;
     JSGenerator         *prevGenerator;
     js::StackFrame      *fp;
     js::HeapValue       stackSnapshot[1];
 };
 
 extern JSObject *
 js_NewGenerator(JSContext *cx);
+
+namespace js {
+
+bool
+GeneratorHasMarkableFrame(JSGenerator *gen);
+
+} /* namespace js */
 #endif
 
 extern JSObject *
 js_InitIteratorClasses(JSContext *cx, JSObject *obj);
 
 #endif /* jsiter_h___ */
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2797,31 +2797,34 @@ js_Object(JSContext *cx, unsigned argc, 
 
 static inline JSObject *
 NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
           gc::AllocKind kind)
 {
     JS_ASSERT(clasp != &ArrayClass);
     JS_ASSERT_IF(clasp == &FunctionClass,
                  kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
+    JS_ASSERT_IF(parent, parent->global() == cx->compartment->global());
 
     RootedTypeObject type(cx, type_);
 
     RootedShape shape(cx);
     shape = EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind);
     if (!shape)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
-    if (!obj)
+    if (!obj) {
+        cx->free_(slots);
         return NULL;
+    }
 
     /*
      * This will cancel an already-running incremental GC from doing any more
      * slices, and it will prevent any future incremental GCs.
      */
     if (clasp->trace && !(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS))
         cx->runtime->gcIncrementalEnabled = false;
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1218,16 +1218,17 @@ JSObject::isWrapper() const
 }
 
 inline js::GlobalObject &
 JSObject::global() const
 {
     JSObject *obj = const_cast<JSObject *>(this);
     while (JSObject *parent = obj->getParent())
         obj = parent;
+    JS_ASSERT(obj->asGlobal() == compartment()->global());
     return obj->asGlobal();
 }
 
 static inline bool
 js_IsCallable(const js::Value &v)
 {
     return v.isObject() && v.toObject().isCallable();
 }
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2554,17 +2554,17 @@ static JSClass sandbox_class = {
     JS_PropertyStub,   JS_StrictPropertyStub,
     sandbox_enumerate, (JSResolveOp)sandbox_resolve,
     JS_ConvertStub
 };
 
 static JSObject *
 NewSandbox(JSContext *cx, bool lazy)
 {
-    RootedObject obj(cx, JS_NewCompartmentAndGlobalObject(cx, &sandbox_class, NULL));
+    RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, NULL));
     if (!obj)
         return NULL;
 
     {
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, obj))
             return NULL;
 
@@ -3225,34 +3225,21 @@ Compile(JSContext *cx, unsigned argc, js
     }
     jsval arg0 = JS_ARGV(cx, vp)[0];
     if (!JSVAL_IS_STRING(arg0)) {
         const char *typeName = JS_GetTypeName(cx, JS_TypeOfValue(cx, arg0));
         JS_ReportError(cx, "expected string to compile, got %s", typeName);
         return false;
     }
 
-    static JSClass dummy_class = {
-        "jdummy",
-        JSCLASS_GLOBAL_FLAGS,
-        JS_PropertyStub,  JS_PropertyStub,
-        JS_PropertyStub,  JS_StrictPropertyStub,
-        JS_EnumerateStub, JS_ResolveStub,
-        JS_ConvertStub
-    };
-
-    JSObject *fakeGlobal = JS_NewGlobalObject(cx, &dummy_class);
-    if (!fakeGlobal)
-        return false;
-
+    JSObject *global = JS_GetGlobalForScopeChain(cx);
     JSString *scriptContents = JSVAL_TO_STRING(arg0);
-
     unsigned oldopts = JS_GetOptions(cx);
     JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    bool ok = JS_CompileUCScript(cx, fakeGlobal, JS_GetStringCharsZ(cx, scriptContents),
+    bool ok = JS_CompileUCScript(cx, global, JS_GetStringCharsZ(cx, scriptContents),
                                  JS_GetStringLength(scriptContents), "<string>", 1);
     JS_SetOptions(cx, oldopts);
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return ok;
 }
 
 static JSBool
@@ -3420,43 +3407,23 @@ Deserialize(JSContext *cx, unsigned argc
     if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArray::getDataOffset(obj), TypedArray::getByteLength(obj),
                                 JS_STRUCTURED_CLONE_VERSION, v.address(), NULL, NULL)) {
         return false;
     }
     JS_SET_RVAL(cx, vp, v);
     return true;
 }
 
-enum CompartmentKind { SAME_COMPARTMENT, NEW_COMPARTMENT };
-
 static JSObject *
-NewGlobalObject(JSContext *cx, CompartmentKind compartment);
+NewGlobalObject(JSContext *cx);
 
 static JSBool
 NewGlobal(JSContext *cx, unsigned argc, jsval *vp)
 {
-    if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
-        return false;
-    }
-
-    JSString *str = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]);
-
-    JSBool equalSame = false, equalNew = false;
-    if (!JS_StringEqualsAscii(cx, str, "same-compartment", &equalSame) ||
-        !JS_StringEqualsAscii(cx, str, "new-compartment", &equalNew)) {
-        return false;
-    }
-
-    if (!equalSame && !equalNew) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
-        return false;
-    }
-
-    JSObject *global = NewGlobalObject(cx, equalSame ? SAME_COMPARTMENT : NEW_COMPARTMENT);
+    JSObject *global = NewGlobalObject(cx);
     if (!global)
         return false;
 
     JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(global));
     return true;
 }
 
 static JSBool
@@ -4584,23 +4551,19 @@ DestroyContext(JSContext *cx, bool withG
 {
     JSShellContextData *data = GetContextData(cx);
     JS_SetContextPrivate(cx, NULL);
     free(data);
     WITH_SIGNALS_DISABLED(withGC ? JS_DestroyContext(cx) : JS_DestroyContextNoGC(cx));
 }
 
 static JSObject *
-NewGlobalObject(JSContext *cx, CompartmentKind compartment)
+NewGlobalObject(JSContext *cx)
 {
-    RootedObject glob(cx);
-
-    glob = (compartment == NEW_COMPARTMENT)
-           ? JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL)
-           : JS_NewGlobalObject(cx, &global_class);
+    RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL));
     if (!glob)
         return NULL;
 
     {
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, glob))
             return NULL;
 
@@ -4635,17 +4598,17 @@ NewGlobalObject(JSContext *cx, Compartme
         if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
                                its_setter, 0))
             return NULL;
         if (!JS_DefineProperty(cx, glob, "customRdOnly", JSVAL_VOID, its_getter,
                                its_setter, JSPROP_READONLY))
             return NULL;
     }
 
-    if (compartment == NEW_COMPARTMENT && !JS_WrapObject(cx, glob.address()))
+    if (!JS_WrapObject(cx, glob.address()))
         return NULL;
 
     return glob;
 }
 
 static bool
 BindScriptArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
 {
@@ -4841,17 +4804,17 @@ Shell(JSContext *cx, OptionParser *op, c
      * on the compartment when it is constructed.
      */
     if (op->getBoolOption("no-ti")) {
         enableTypeInference = false;
         JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
     }
 
     RootedObject glob(cx);
-    glob = NewGlobalObject(cx, NEW_COMPARTMENT);
+    glob = NewGlobalObject(cx);
     if (!glob)
         return 1;
 
     JSAutoEnterCompartment ac;
     if (!ac.enter(cx, glob))
         return 1;
 
     JS_SetGlobalObject(cx, glob);
@@ -4860,17 +4823,17 @@ Shell(JSContext *cx, OptionParser *op, c
     if (!envobj)
         return 1;
     JS_SetPrivate(envobj, envp);
 
 #ifdef JS_THREADSAFE
     class ShellWorkerHooks : public js::workers::WorkerHooks {
     public:
         JSObject *newGlobalObject(JSContext *cx) {
-            return NewGlobalObject(cx, NEW_COMPARTMENT);
+            return NewGlobalObject(cx);
         }
     };
     ShellWorkerHooks hooks;
     if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
         (gWorkerThreadPool = js::workers::init(cx, &hooks, glob, &gWorkers)) == NULL) {
         return 1;
     }
 #endif
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -237,36 +237,46 @@ GlobalObject::initFunctionAndObjectClass
     return functionProto;
 }
 
 GlobalObject *
 GlobalObject::create(JSContext *cx, Class *clasp)
 {
     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
+    JSObject *obj = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
+    if (!obj)
+        return NULL;
+
+    Rooted<GlobalObject *> global(cx, &obj->asGlobal());
+
+    cx->compartment->initGlobal(*global);
+
+    if (!global->setSingletonType(cx) || !global->setVarObj(cx))
+        return NULL;
     Rooted<GlobalObject*> obj(cx);
 
     JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     if (!obj_)
         return NULL;
     obj = &obj_->asGlobal();
 
     if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
         return NULL;
     if (!obj->setDelegate(cx))
         return NULL;
 
     /* Construct a regexp statics object for this global object. */
-    JSObject *res = RegExpStatics::create(cx, obj);
+    JSObject *res = RegExpStatics::create(cx, global);
     if (!res)
         return NULL;
-    obj->initSlot(REGEXP_STATICS, ObjectValue(*res));
-    obj->initFlags(0);
+    global->initSlot(REGEXP_STATICS, ObjectValue(*res));
+    global->initFlags(0);
 
-    return obj;
+    return global;
 }
 
 /* static */ bool
 GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
 {
     JSAtomState &state = cx->runtime->atomState;
 
     /* Define a top-level property 'undefined' with the undefined value. */
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -92,52 +92,59 @@ StackFrame::initDummyFrame(JSContext *cx
 {
     PodZero(this);
     flags_ = DUMMY | HAS_PREVPC | HAS_SCOPECHAIN;
     initPrev(cx);
     JS_ASSERT(chain.isGlobal());
     scopeChain_ = &chain;
 }
 
-template <class T, class U, StackFrame::TriggerPostBarriers doPostBarrier>
+template <StackFrame::TriggerPostBarriers doPostBarrier>
 void
-StackFrame::copyFrameAndValues(JSContext *cx, T *vp, StackFrame *otherfp, U *othervp, Value *othersp)
+StackFrame::copyFrameAndValues(JSContext *cx, Value *vp, StackFrame *otherfp,
+                               const Value *othervp, Value *othersp)
 {
-    JS_ASSERT((U *)vp == (U *)this - ((U *)otherfp - othervp));
-    JS_ASSERT((Value *)othervp == otherfp->generatorArgsSnapshotBegin());
+    JS_ASSERT(vp == (Value *)this - ((Value *)otherfp - othervp));
+    JS_ASSERT(othervp == otherfp->generatorArgsSnapshotBegin());
     JS_ASSERT(othersp >= otherfp->slots());
     JS_ASSERT(othersp <= otherfp->generatorSlotsSnapshotBegin() + otherfp->script()->nslots);
-    JS_ASSERT((T *)this - vp == (U *)otherfp - othervp);
+    JS_ASSERT((Value *)this - vp == (Value *)otherfp - othervp);
 
     /* Copy args, StackFrame, and slots. */
-    U *srcend = (U *)otherfp->generatorArgsSnapshotEnd();
-    T *dst = vp;
-    for (U *src = othervp; src < srcend; src++, dst++)
+    const Value *srcend = otherfp->generatorArgsSnapshotEnd();
+    Value *dst = vp;
+    for (const Value *src = othervp; src < srcend; src++, dst++) {
         *dst = *src;
+        if (doPostBarrier)
+            HeapValue::writeBarrierPost(*dst, dst);
+    }
 
     *this = *otherfp;
     if (doPostBarrier)
         writeBarrierPost();
 
-    srcend = (U *)othersp;
-    dst = (T *)slots();
-    for (U *src = (U *)otherfp->slots(); src < srcend; src++, dst++)
+    srcend = othersp;
+    dst = slots();
+    for (const Value *src = otherfp->slots(); src < srcend; src++, dst++) {
         *dst = *src;
+        if (doPostBarrier)
+            HeapValue::writeBarrierPost(*dst, dst);
+    }
 
     if (cx->compartment->debugMode())
         cx->runtime->debugScopes->onGeneratorFrameChange(otherfp, this, cx);
 }
 
 /* Note: explicit instantiation for js_NewGenerator located in jsiter.cpp. */
 template
-void StackFrame::copyFrameAndValues<Value, HeapValue, StackFrame::NoPostBarrier>(
-                                    JSContext *, Value *, StackFrame *, HeapValue *, Value *);
+void StackFrame::copyFrameAndValues<StackFrame::NoPostBarrier>(
+                                    JSContext *, Value *, StackFrame *, const Value *, Value *);
 template
-void StackFrame::copyFrameAndValues<HeapValue, Value, StackFrame::DoPostBarrier>(
-                                    JSContext *, HeapValue *, StackFrame *, Value *, Value *);
+void StackFrame::copyFrameAndValues<StackFrame::DoPostBarrier>(
+                                    JSContext *, Value *, StackFrame *, const Value *, Value *);
 
 void
 StackFrame::writeBarrierPost()
 {
     /* This needs to follow the same rules as in StackFrame::mark. */
     if (scopeChain_)
         JSObject::writeBarrierPost(scopeChain_, (void *)&scopeChain_);
     if (isDummyFrame())
@@ -1135,18 +1142,18 @@ ContextStack::pushGeneratorFrame(JSConte
      * objects, but only when the generator is not actually on the stack.
      * We don't need to worry about generational barriers as the generator
      * object has a trace hook and cannot be nursery allocated.
      */
     JS_ASSERT(gen->obj->getClass()->trace);
     JSObject::writeBarrierPre(gen->obj);
 
     /* Copy from the generator's floating frame to the stack. */
-    stackfp->copyFrameAndValues<Value, HeapValue, StackFrame::NoPostBarrier>(
-                                cx, stackvp, gen->fp, genvp, gen->regs.sp);
+    stackfp->copyFrameAndValues<StackFrame::NoPostBarrier>(cx, stackvp, gen->fp,
+                                                           Valueify(genvp), gen->regs.sp);
     stackfp->resetGeneratorPrev(cx);
     gfg->regs_.rebaseFromTo(gen->regs, *stackfp);
 
     gfg->prevRegs_ = seg_->pushRegs(gfg->regs_);
     JS_ASSERT(space().firstUnused() == gfg->regs_.sp);
     gfg->setPushed(*this);
     return true;
 }
@@ -1159,19 +1166,25 @@ ContextStack::popGeneratorFrame(const Ge
     JS_ASSERT(genvp == HeapValueify(gen->fp->generatorArgsSnapshotBegin()));
 
     const FrameRegs &stackRegs = gfg.regs_;
     StackFrame *stackfp = stackRegs.fp();
     Value *stackvp = gfg.stackvp_;
 
     /* Copy from the stack to the generator's floating frame. */
     if (stackfp->isYielding()) {
+        /*
+         * Assert that the frame is not markable so that we don't need an
+         * incremental write barrier when updating the generator's saved slots.
+         */
+        JS_ASSERT(!GeneratorHasMarkableFrame(gen));
+
         gen->regs.rebaseFromTo(stackRegs, *gen->fp);
-        gen->fp->copyFrameAndValues<HeapValue, Value, StackFrame::DoPostBarrier>(
-                                    cx_, genvp, stackfp, stackvp, stackRegs.sp);
+        gen->fp->copyFrameAndValues<StackFrame::DoPostBarrier>(cx_, (Value *)genvp, stackfp,
+                                                               stackvp, stackRegs.sp);
     }
 
     /* ~FrameGuard/popFrame will finish the popping. */
     JS_ASSERT(ImplicitCast<const FrameGuard>(gfg).pushed());
 }
 
 bool
 ContextStack::saveFrameChain()
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -996,18 +996,19 @@ class StackFrame
         JS_ASSERT(isGeneratorFrame());
         return (Value *)(this + 1);
     }
 
     enum TriggerPostBarriers {
         DoPostBarrier = true,
         NoPostBarrier = false
     };
-    template <class T, class U, TriggerPostBarriers doPostBarrier>
-    void copyFrameAndValues(JSContext *cx, T *vp, StackFrame *otherfp, U *othervp, Value *othersp);
+    template <TriggerPostBarriers doPostBarrier>
+    void copyFrameAndValues(JSContext *cx, Value *vp, StackFrame *otherfp,
+                            const Value *othervp, Value *othersp);
 
     JSGenerator *maybeSuspendedGenerator(JSRuntime *rt);
 
     /*
      * js::Execute pushes both global and function frames (since eval() in a
      * function pushes a frame with isFunctionFrame() && isEvalFrame()). Most
      * code should not care where a frame was pushed, but if it is necessary to
      * pick out frames pushed by js::Execute, this is the right query:
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -1183,30 +1183,16 @@ ProcessArgs(JSContext *cx, JSObject *obj
             JS_ToggleOptions(cx, JSOPTION_STRICT);
             break;
         case 'x':
             JS_ToggleOptions(cx, JSOPTION_MOAR_XML);
             break;
         case 'd':
             xpc_ActivateDebugMode();
             break;
-        case 'P':
-            if (JS_GetClass(JS_GetPrototype(obj)) != &global_class) {
-                JSObject *gobj;
-
-                if (!JS_DeepFreezeObject(cx, obj))
-                    return false;
-                gobj = JS_NewGlobalObject(cx, &global_class);
-                if (!gobj || !JS_SplicePrototype(cx, gobj, obj))
-                    return false;
-                JS_SetParent(cx, gobj, NULL);
-                JS_SetGlobalObject(cx, gobj);
-                obj = gobj;
-            }
-            break;
         case 'f':
             if (++i == argc) {
                 return usage();
             }
             Process(cx, obj, argv[i], false);
             /*
              * XXX: js -f foo.js should interpret foo.js and then
              * drop into interactive mode, but that breaks test
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -362,17 +362,17 @@ void XPCJSRuntime::TraceXPConnectRoots(J
     while (JSContext *acx = JS_ContextIterator(GetJSRuntime(), &iter)) {
         JS_ASSERT(js::HasUnrootedGlobal(acx));
         if (JSObject *global = JS_GetGlobalObject(acx))
             JS_CALL_OBJECT_TRACER(trc, global, "XPC global object");
     }
 
     XPCAutoLock lock(mMapLock);
 
-    XPCWrappedNativeScope::TraceJS(trc, this);
+    XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(trc, this);
 
     for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot())
         static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
 
     for (XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot())
         static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
 
     if (mJSHolders.ops)
@@ -1852,17 +1852,17 @@ DiagnosticMemoryCallback(void *ptr, size
 }
 #endif
 
 static void
 AccumulateTelemetryCallback(int id, uint32_t sample)
 {
     switch (id) {
       case JS_TELEMETRY_GC_REASON:
-        Telemetry::Accumulate(Telemetry::GC_REASON, sample);
+        Telemetry::Accumulate(Telemetry::GC_REASON_2, sample);
         break;
       case JS_TELEMETRY_GC_IS_COMPARTMENTAL:
         Telemetry::Accumulate(Telemetry::GC_IS_COMPARTMENTAL, sample);
         break;
       case JS_TELEMETRY_GC_MS:
         Telemetry::Accumulate(Telemetry::GC_MS, sample);
         break;
       case JS_TELEMETRY_GC_MARK_MS:
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -619,49 +619,28 @@ WrappedNativeFinalize(js::FreeOp *fop, J
 
 static void
 XPC_WN_NoHelper_Finalize(js::FreeOp *fop, JSObject *obj)
 {
     WrappedNativeFinalize(fop, obj, WN_NOHELPER);
 }
 
 static void
-TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
+TraceInsideSlimWrapper(JSTracer *trc, JSObject *obj)
 {
-    scope->TraceSelf(trc);
+    GetSlimWrapperProto(obj)->TraceSelf(trc);
 }
 
-static void
-TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
-{
-    // NOTE: It might be nice to also do the wrapper->Mark() call here too
-    // when we are called during the marking phase of JS GC to mark the
-    // wrapper's and wrapper's proto's interface sets.
-    //
-    // We currently do that in the GC callback code. The reason we don't do that
-    // here is because the bits used in that marking do unpleasant things to the
-    // member counts in the interface and interface set objects. Those counts
-    // are used in the DealWithDyingGCThings calls that are part of this JS GC
-    // marking phase. By doing these calls later during our GC callback we
-    // avoid that problem. Arguably this could be changed. But it ain't broke.
-    //
-    // However, we do need to call the wrapper's TraceJS so that
-    // it can be sure that its (potentially shared) JSClass is traced. The
-    // danger is that a live wrapper might not be in a wrapper map and thus
-    // won't be fully marked in the GC callback. This can happen if there is
-    // a security exception during wrapper creation or if during wrapper
-    // creation it is determined that the wrapper is not needed. In those cases
-    // the wrapper can never actually be used from JS code - so resources like
-    // the interface set will never be accessed. But the JS engine will still
-    // need to use the JSClass. So, some marking is required for protection.
-
-    wrapper->TraceJS(trc);
-
-    TraceScopeJSObjects(trc, wrapper->GetScope());
-}
+/*
+ * General comment about XPConnect tracing: Given a C++ object |wrapper| and its
+ * corresponding JS object |obj|, calling |wrapper->TraceSelf| will ask the JS
+ * engine to mark |obj|. Eventually, this will lead to the trace hook being
+ * called for |obj|. The trace hook should call |wrapper->TraceInside|, which
+ * should mark any JS objects held by |wrapper| as members.
+ */
 
 static void
 MarkWrappedNative(JSTracer *trc, JSObject *obj)
 {
     js::Class* clazz = js::GetObjectClass(obj);
     if (clazz->flags & JSCLASS_DOM_GLOBAL) {
         mozilla::dom::TraceProtoOrIfaceCache(trc, obj);
     }
@@ -670,19 +649,19 @@ MarkWrappedNative(JSTracer *trc, JSObjec
 
     // Pass null for the first JSContext* parameter  to skip any security
     // checks and to avoid potential state change there.
     XPCWrappedNative* wrapper =
         XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
 
     if (wrapper) {
         if (wrapper->IsValid())
-             TraceForValidWrapper(trc, wrapper);
+            wrapper->TraceInside(trc);
     } else if (obj2) {
-        GetSlimWrapperProto(obj2)->TraceJS(trc);
+        TraceInsideSlimWrapper(trc, obj2);
     }
 }
 
 static void
 XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj)
 {
     MarkWrappedNative(trc, obj);
 }
@@ -1597,17 +1576,17 @@ XPC_WN_Shared_Proto_Finalize(js::FreeOp 
 
 static void
 XPC_WN_Shared_Proto_Trace(JSTracer *trc, JSObject *obj)
 {
     // This can be null if xpc shutdown has already happened
     XPCWrappedNativeProto* p =
         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
     if (p)
-        TraceScopeJSObjects(trc, p->GetScope());
+        p->TraceInside(trc);
 }
 
 /*****************************************************/
 
 static JSBool
 XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
--- a/js/xpconnect/src/XPCWrappedNativeProto.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp
@@ -25,16 +25,17 @@ XPCWrappedNativeProto::XPCWrappedNativeP
       mSecurityInfo(nsnull),
       mScriptableInfo(nsnull),
       mOffsets(offsets)
 {
     // This native object lives as long as its associated JSObject - killed
     // by finalization of the JSObject (or explicitly if Init fails).
 
     MOZ_COUNT_CTOR(XPCWrappedNativeProto);
+    MOZ_ASSERT(mScope);
 
 #ifdef DEBUG
     PR_ATOMIC_INCREMENT(&gDEBUG_LiveProtoCount);
 #endif
 }
 
 XPCWrappedNativeProto::~XPCWrappedNativeProto()
 {
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -314,28 +314,25 @@ XPCWrappedNativeScope::GetPrototypeNoHel
     return mPrototypeNoHelper;
 }
 
 static JSDHashOperator
 WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
                              uint32_t number, void *arg)
 {
     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
-    if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired()) {
-        JSTracer* trc = (JSTracer *)arg;
-        JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObjectPreserveColor(),
-                              "XPCWrappedNative::mFlatJSObject");
-    }
+    if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired())
+        wrapper->TraceSelf((JSTracer *)arg);
 
     return JS_DHASH_NEXT;
 }
 
 // static
 void
-XPCWrappedNativeScope::TraceJS(JSTracer* trc, XPCJSRuntime* rt)
+XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt)
 {
     // FIXME The lock may not be necessary during tracing as that serializes
     // access to JS runtime. See bug 380139.
     XPCAutoLock lock(rt->GetMapLock());
 
     // Do JS_CallTracer for all wrapped natives with external references.
     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
         cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingTracer, trc);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1027,26 +1027,26 @@ nsXPConnect::InitClasses(JSContext * aJS
 
     if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     return NS_OK;
 }
 
 static bool
-CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
-                     xpc::CompartmentPrivate *priv, JSObject **global,
-                     JSCompartment **compartment)
+CreateNewGlobal(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
+                xpc::CompartmentPrivate *priv, JSObject **global,
+                JSCompartment **compartment)
 {
     // We take ownership of |priv|. Ensure that either we free it in the case
     // of failure or give ownership to the compartment in case of success (in
     // that case it will be free'd in CompartmentCallback during GC).
     nsAutoPtr<xpc::CompartmentPrivate> priv_holder(priv);
     JSObject *tempGlobal =
-        JS_NewCompartmentAndGlobalObject(cx, clasp, nsJSPrincipals::get(principal));
+        JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal));
 
     if (!tempGlobal)
         return false;
 
     *global = tempGlobal;
     *compartment = js::GetObjectCompartment(tempGlobal);
 
     JS_SetCompartmentPrivate(*compartment, priv_holder.forget());
@@ -1134,17 +1134,17 @@ xpc_CreateGlobalObject(JSContext *cx, JS
 {
     // Make sure that Type Inference is enabled for everything non-chrome.
     // Sandboxes and compilation scopes are exceptions. See bug 744034.
     CheckTypeInference(cx, clasp, principal);
 
     NS_ABORT_IF_FALSE(NS_IsMainThread(), "using a principal off the main thread?");
 
     xpc::CompartmentPrivate *priv = new xpc::CompartmentPrivate(wantXrays);
-    if (!CreateNewCompartment(cx, clasp, principal, priv, global, compartment))
+    if (!CreateNewGlobal(cx, clasp, principal, priv, global, compartment))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     XPCCompartmentSet& set = nsXPConnect::GetRuntimeInstance()->GetCompartmentSet();
     if (!set.put(*compartment))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
 #ifdef DEBUG
     // Verify that the right trace hook is called. Note that this doesn't
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1621,17 +1621,17 @@ public:
         return FindInJSObjectScope(ccx, obj, OKIfNotInitialized,
                                    ccx.GetRuntime());
     }
 
     static void
     SystemIsBeingShutDown();
 
     static void
-    TraceJS(JSTracer* trc, XPCJSRuntime* rt);
+    TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt);
 
     void TraceSelf(JSTracer *trc) {
         JSObject *obj = GetGlobalJSObjectPreserveColor();
         MOZ_ASSERT(obj);
         JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
 
         JSObject *proto = GetPrototypeJSObjectPreserveColor();
         if (proto)
@@ -2440,16 +2440,18 @@ public:
     }
 
     void TraceInside(JSTracer *trc) {
         if (JS_IsGCMarkingTracer(trc)) {
             mSet->Mark();
             if (mScriptableInfo)
                 mScriptableInfo->Mark();
         }
+
+        GetScope()->TraceSelf(trc);
     }
 
     void TraceJS(JSTracer *trc) {
         TraceSelf(trc);
         TraceInside(trc);
     }
 
     void WriteBarrierPre(JSRuntime* rt)
@@ -2830,16 +2832,18 @@ public:
     inline void TraceInside(JSTracer *trc) {
         if (JS_IsGCMarkingTracer(trc)) {
             mSet->Mark();
             if (mScriptableInfo)
                 mScriptableInfo->Mark();
         }
         if (HasProto())
             GetProto()->TraceJS(trc);
+        else
+            GetScope()->TraceSelf(trc);
         JSObject* wrapper = GetWrapperPreserveColor();
         if (wrapper)
             JS_CALL_OBJECT_TRACER(trc, wrapper, "XPCWrappedNative::mWrapper");
         if (mScriptableInfo &&
             (mScriptableInfo->GetJSClass()->flags & JSCLASS_XPCONNECT_GLOBAL))
         {
             TraceXPCGlobal(trc, mFlatJSObject);
         }
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2540,32 +2540,24 @@ nsCSSFrameConstructor::SetUpDocElementCo
   NS_PRECONDITION(!aDocElement->GetParent(), "Not root content?");
   NS_PRECONDITION(aDocElement->GetCurrentDoc(), "Not in a document?");
   NS_PRECONDITION(aDocElement->GetCurrentDoc()->GetRootElement() ==
                   aDocElement, "Not the root of the document?");
 
   /*
     how the root frame hierarchy should look
 
-  Galley presentation, non-XUL, with scrolling (i.e. not a frameset,
-  or framesets with async pan/zoom like on Fennec):
+  Galley presentation, non-XUL, with scrolling:
   
       ViewportFrame [fixed-cb]
         nsHTMLScrollFrame
           nsCanvasFrame [abs-cb]
             root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
                                 nsTableOuterFrame, nsPlaceholderFrame)
 
-  Galley presentation, non-XUL, without scrolling (i.e. a frameset,
-  except when async pan/zoom is enabled):
-  
-      ViewportFrame [fixed-cb]
-        nsCanvasFrame [abs-cb]
-          root element frame (nsBlockFrame)
-
   Galley presentation, XUL
   
       ViewportFrame [fixed-cb]
         nsRootBoxFrame
           root element frame (nsDocElementBoxFrame)
 
   Print presentation, non-XUL
 
@@ -2665,31 +2657,17 @@ nsCSSFrameConstructor::SetUpDocElementCo
   bool isHTML = aDocElement->IsHTML();
   bool isXUL = false;
 
   if (!isHTML) {
     isXUL = aDocElement->IsXUL();
   }
 
   // Never create scrollbars for XUL documents
-  bool isScrollable = !isXUL;
-
-#ifndef MOZ_WIDGET_ANDROID
-  // Never create scrollbars for frameset documents, except on android
-  // where we have async pan/zoom and need a scrollable root frame.
-  if (isHTML) {
-    nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
-    if (htmlDoc && htmlDoc->GetIsFrameset())
-      isScrollable = false;
-  }
-#endif
-
-  if (isPaginated) {
-    isScrollable = presContext->HasPaginatedScrolling();
-  }
+  bool isScrollable = isPaginated ? presContext->HasPaginatedScrolling() : !isXUL;
 
   // We no longer need to do overflow propagation here. It's taken care of
   // when we construct frames for the element whose overflow might be
   // propagated
   NS_ASSERTION(!isScrollable || !isXUL,
                "XUL documents should never be scrollable - see above");
 
   nsIFrame* newFrame = rootFrame;
--- a/layout/base/nsCSSRenderingBorders.cpp
+++ b/layout/base/nsCSSRenderingBorders.cpp
@@ -45,21 +45,19 @@
  *   |- separate corners?
  *   |- dashed side mask
  *   |
  *   -> can border be drawn in 1 pass? (e.g., solid border same color all around)
  *      |- DrawBorderSides with all 4 sides
  *   -> more than 1 pass?
  *      |- for each corner
  *         |- clip to DoCornerClipSubPath
- *         |- PushGroup
  *         |- for each side adjacent to corner
  *            |- clip to DoSideClipSubPath
  *            |- DrawBorderSides with one side
- *         |- PopGroup
  *      |- for each side
  *         |- DoSideClipWithoutCornersSubPath
  *         |- DrawDashedSide || DrawBorderSides with one side
  */
 
 static void ComputeBorderCornerDimensions(const gfxRect& aOuterRect,
                                           const gfxRect& aInnerRect,
                                           const gfxCornerSizes& aRadii,
@@ -1631,28 +1629,26 @@ nsCSSBorderRenderer::DrawBorders()
       DoCornerSubPath(corner);
       mContext->Clip();
 
       if (simpleCornerStyle) {
         // we don't need a group for this corner, the sides are the same,
         // but we weren't able to render just a solid block for the corner.
         DrawBorderSides(sideBits);
       } else {
-        // Sides are different.  We need to draw using OPERATOR_ADD to
-        // get correct color blending behaviour at the seam.  We need
+        // Sides are different.  We could draw using OPERATOR_ADD to
+        // get correct color blending behaviour at the seam.  We'd need
         // to do it in an offscreen surface to ensure that we're
         // always compositing on transparent black.  If the colors
         // don't have transparency and the current destination surface
         // has an alpha channel, we could just clear the region and
         // avoid the temporary, but that situation doesn't happen all
         // that often in practice (we double buffer to no-alpha
-        // surfaces).
-
-        mContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
-        mContext->SetOperator(gfxContext::OPERATOR_ADD);
+        // surfaces). We choose just to seam though, as the performance
+        // advantages outway the modest easthetic improvement.
 
         for (int cornerSide = 0; cornerSide < 2; cornerSide++) {
           mozilla::css::Side side = mozilla::css::Side(sides[cornerSide]);
           PRUint8 style = mBorderStyles[side];
 
           SF("corner: %d cornerSide: %d side: %d style: %d\n", corner, cornerSide, side, style);
 
           mContext->Save();
@@ -1660,20 +1656,16 @@ nsCSSBorderRenderer::DrawBorders()
           mContext->NewPath();
           DoSideClipSubPath(side);
           mContext->Clip();
 
           DrawBorderSides(1 << side);
 
           mContext->Restore();
         }
-
-        mContext->PopGroupToSource();
-        mContext->SetOperator(gfxContext::OPERATOR_OVER);
-        mContext->Paint();
       }
 
       mContext->Restore();
 
       SN();
     }
 
     // in the case of a single-unit border, we already munged the
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -110,17 +110,17 @@ public:
 
   nsComboboxControlFrame* mComboBox;
 };
 
 NS_IMPL_ISUPPORTS1(nsComboButtonListener,
                    nsIDOMEventListener)
 
 // static class data member for Bug 32920
-nsComboboxControlFrame * nsComboboxControlFrame::mFocused = nsnull;
+nsComboboxControlFrame* nsComboboxControlFrame::sFocused = nsnull;
 
 nsIFrame*
 NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aStateFlags)
 {
   nsComboboxControlFrame* it = new (aPresShell) nsComboboxControlFrame(aContext);
 
   if (it) {
     // set the state flags (if any are provided)
@@ -273,29 +273,28 @@ static PRInt32 gReflowInx = -1;
 #define PX(__v) __v 
 #endif
 
 //------------------------------------------------------
 //-- Done with macros
 //------------------------------------------------------
 
 nsComboboxControlFrame::nsComboboxControlFrame(nsStyleContext* aContext)
-  : nsBlockFrame(aContext),
-    mDisplayWidth(0)
+  : nsBlockFrame(aContext)
+  , mDisplayFrame(nsnull)
+  , mButtonFrame(nsnull)
+  , mDropdownFrame(nsnull)
+  , mListControlFrame(nsnull)
+  , mDisplayWidth(0)
+  , mRecentSelectedIndex(NS_SKIP_NOTIFY_INDEX)
+  , mDisplayedIndex(-1)
+  , mDroppedDown(false)
+  , mInRedisplayText(false)
+  , mDelayedShowDropDown(false)
 {
-  mListControlFrame            = nsnull;
-  mDroppedDown                 = false;
-  mDisplayFrame                = nsnull;
-  mButtonFrame                 = nsnull;
-  mDropdownFrame               = nsnull;
-
-  mInRedisplayText = false;
-
-  mRecentSelectedIndex = NS_SKIP_NOTIFY_INDEX;
-
   REFLOW_COUNTER_INIT()
 }
 
 //--------------------------------------------------------------
 nsComboboxControlFrame::~nsComboboxControlFrame()
 {
   REFLOW_COUNTER_DUMP("nsCCF");
 }
@@ -319,25 +318,32 @@ nsComboboxControlFrame::CreateAccessible
     return accService->CreateHTMLComboboxAccessible(mContent,
                                                     PresContext()->PresShell());
   }
 
   return nsnull;
 }
 #endif
 
-void 
+void
 nsComboboxControlFrame::SetFocus(bool aOn, bool aRepaint)
 {
   nsWeakFrame weakFrame(this);
   if (aOn) {
     nsListControlFrame::ComboboxFocusSet();
-    mFocused = this;
+    sFocused = this;
+    if (mDelayedShowDropDown) {
+      ShowDropDown(true); // might destroy us
+      if (!weakFrame.IsAlive()) {
+        return;
+      }
+    }
   } else {
-    mFocused = nsnull;
+    sFocused = nsnull;
+    mDelayedShowDropDown = false;
     if (mDroppedDown) {
       mListControlFrame->ComboboxFinish(mDisplayedIndex); // might destroy us
       if (!weakFrame.IsAlive()) {
         return;
       }
     }
     // May delete |this|.
     mListControlFrame->FireOnChange();
@@ -437,16 +443,54 @@ nsComboboxControlFrame::ShowList(bool aS
         }
       }
     }
   }
 
   return weakFrame.IsAlive();
 }
 
+class nsResizeDropdownAtFinalPosition
+  : public nsIReflowCallback, public nsRunnable
+{
+public:
+  nsResizeDropdownAtFinalPosition(nsComboboxControlFrame* aFrame)
+    : mFrame(aFrame)
+  {
+    MOZ_COUNT_CTOR(nsResizeDropdownAtFinalPosition);
+  }
+  ~nsResizeDropdownAtFinalPosition()
+  {
+    MOZ_COUNT_DTOR(nsResizeDropdownAtFinalPosition);
+  }
+
+  virtual bool ReflowFinished()
+  {
+    Run();
+    NS_RELEASE_THIS();
+    return false;
+  }
+
+  virtual void ReflowCallbackCanceled()
+  {
+    NS_RELEASE_THIS();
+  }
+
+  NS_IMETHODIMP Run()
+  {
+    if (mFrame.IsAlive()) {
+      static_cast<nsComboboxControlFrame*>(mFrame.GetFrame())->
+        AbsolutelyPositionDropDown();
+    }
+    return NS_OK;
+  }
+
+  nsWeakFrame mFrame;
+};
+
 nsresult
 nsComboboxControlFrame::ReflowDropdown(nsPresContext*  aPresContext, 
                                        const nsHTMLReflowState& aReflowState)
 {
   // All we want out of it later on, really, is the height of a row, so we
   // don't even need to cache mDropdownFrame's ascent or anything.  If we don't
   // need to reflow it, just bail out here.
   if (!aReflowState.ShouldReflowAllKids() &&
@@ -530,59 +574,176 @@ nsComboboxControlFrame::GetCSSTransformT
       translation -= GetOffsetToCrossDoc(rootPC->PresShell()->GetRootFrame());
     } else {
       translation.x = translation.y = 0;
     }
   }
   return translation;
 }
 
-void
-nsComboboxControlFrame::AbsolutelyPositionDropDown()
+class nsAsyncRollup : public nsRunnable
 {
-   // Position the dropdown list. It is positioned below the display frame if there is enough
-   // room on the screen to display the entire list. Otherwise it is placed above the display
-   // frame.
+public:
+  nsAsyncRollup(nsComboboxControlFrame* aFrame) : mFrame(aFrame) {}
+  NS_IMETHODIMP Run()
+  {
+    if (mFrame.IsAlive()) {
+      static_cast<nsComboboxControlFrame*>(mFrame.GetFrame())
+        ->RollupFromList();
+    }
+    return NS_OK;
+  }
+  nsWeakFrame mFrame;
+};
 
-   // Note: As first glance, it appears that you could simply get the absolute bounding box for the
-   // dropdown list by first getting its view, then getting the view's nsIWidget, then asking the nsIWidget
-   // for it's AbsoluteBounds. The problem with this approach, is that the dropdown lists y location can
-   // change based on whether the dropdown is placed below or above the display frame.
-   // The approach, taken here is to get use the absolute position of the display frame and use it's location
-   // to determine if the dropdown will go offscreen.
+class nsAsyncResize : public nsRunnable
+{
+public:
+  nsAsyncResize(nsComboboxControlFrame* aFrame) : mFrame(aFrame) {}
+  NS_IMETHODIMP Run()
+  {
+    if (mFrame.IsAlive()) {
+      nsComboboxControlFrame* combo =
+        static_cast<nsComboboxControlFrame*>(mFrame.GetFrame());
+      static_cast<nsListControlFrame*>(combo->mDropdownFrame)->
+        SetSuppressScrollbarUpdate(true);
+      nsCOMPtr<nsIPresShell> shell = mFrame->PresContext()->PresShell();
+      shell->FrameNeedsReflow(combo->mDropdownFrame, nsIPresShell::eResize,
+                              NS_FRAME_IS_DIRTY);
+      shell->FlushPendingNotifications(Flush_Layout);
+      if (mFrame.IsAlive()) {
+        combo = static_cast<nsComboboxControlFrame*>(mFrame.GetFrame());
+        static_cast<nsListControlFrame*>(combo->mDropdownFrame)->
+          SetSuppressScrollbarUpdate(false);
+        if (combo->mDelayedShowDropDown) {
+          combo->ShowDropDown(true);
+        }
+      }
+    }
+    return NS_OK;
+  }
+  nsWeakFrame mFrame;
+};
+
+void
+nsComboboxControlFrame::GetAvailableDropdownSpace(nscoord* aAbove,
+                                                  nscoord* aBelow,
+                                                  nsPoint* aTranslation)
+{
+  // Note: At first glance, it appears that you could simply get the absolute
+  // bounding box for the dropdown list by first getting its view, then getting
+  // the view's nsIWidget, then asking the nsIWidget for its AbsoluteBounds.
+  // The problem with this approach, is that the dropdown lists y location can
+  // change based on whether the dropdown is placed below or above the display
+  // frame.  The approach, taken here is to get the absolute position of the
+  // display frame and use its location to determine if the dropdown will go
+  // offscreen.
 
   // Normal frame geometry (eg GetOffsetTo, mRect) doesn't include transforms.
   // In the special case that our transform is only a 2D translation we
   // introduce this hack so that the dropdown will show up in the right place.
-  nsPoint translation = GetCSSTransformTranslation();
-
-   // Use the height calculated for the area frame so it includes both
-   // the display and button heights.
-  nscoord dropdownYOffset = GetRect().height;
-  nsSize dropdownSize = mDropdownFrame->GetSize();
+  *aTranslation = GetCSSTransformTranslation();
+  *aAbove = 0;
+  *aBelow = 0;
+  
+  nsRect thisScreenRect = GetScreenRectInAppUnits();
+  nsRect screen = nsFormControlFrame::GetUsableScreenRect(PresContext());
+  nscoord dropdownY = thisScreenRect.YMost() + aTranslation->y;
 
-  nsRect screen = nsFormControlFrame::GetUsableScreenRect(PresContext());
+  nscoord minY;
+  if (!PresContext()->IsChrome()) {
+    nsIFrame* root = PresContext()->PresShell()->GetRootFrame();
+    minY = root->GetScreenRectInAppUnits().y;
+    if (dropdownY < root->GetScreenRectInAppUnits().y) {
+      // Don't allow the drop-down to be placed above the top of the root frame.
+      return;
+    }
+  } else {
+    minY = screen.y;
+  }
+  
+  nscoord below = screen.YMost() - dropdownY;
+  nscoord above = thisScreenRect.y + aTranslation->y - minY;
 
-  // Check to see if the drop-down list will go offscreen
-  if ((GetScreenRectInAppUnits() + translation).YMost() + dropdownSize.height > screen.YMost()) {
-    // move the dropdown list up
-    dropdownYOffset = - (dropdownSize.height);
+  // If the difference between the space above and below is less
+  // than a row-height, then we favor the space below.
+  if (above >= below) {
+    nsListControlFrame* lcf = static_cast<nsListControlFrame*>(mDropdownFrame);
+    nscoord rowHeight = lcf->GetHeightOfARow();
+    if (above < below + rowHeight) {
+      above -= rowHeight;
+    }
   }
 
-  nsPoint dropdownPosition;
-  const nsStyleVisibility* vis = GetStyleVisibility();
-  if (vis->mDirection == NS_STYLE_DIRECTION_RTL) {
+  *aBelow = below;
+  *aAbove = above;
+}
+
+nsComboboxControlFrame::DropDownPositionState
+nsComboboxControlFrame::AbsolutelyPositionDropDown()
+{
+  nsPoint translation;
+  nscoord above, below;
+  GetAvailableDropdownSpace(&above, &below, &translation);
+  if (above <= 0 && below <= 0) {
+    // Hide the view immediately to minimize flicker.
+    nsIView* view = mDropdownFrame->GetView();
+    view->GetViewManager()->SetViewVisibility(view, nsViewVisibility_kHide);
+    NS_DispatchToCurrentThread(new nsAsyncRollup(this));
+    return eDropDownPositionSuppressed;
+  }
+
+  nsSize dropdownSize = mDropdownFrame->GetSize();
+  nscoord height = NS_MAX(above, below);
+  nsListControlFrame* lcf = static_cast<nsListControlFrame*>(mDropdownFrame);
+  if (height < dropdownSize.height) {
+    if (lcf->GetNumDisplayRows() > 1) {
+      // The drop-down doesn't fit and currently shows more than 1 row -
+      // schedule a resize to show fewer rows.
+      NS_DispatchToCurrentThread(new nsAsyncResize(this));
+      return eDropDownPositionPendingResize;
+    }
+  } else if (height > (dropdownSize.height + lcf->GetHeightOfARow() * 1.5) &&
+             lcf->GetDropdownCanGrow()) {
+    // The drop-down fits but there is room for at least 1.5 more rows -
+    // schedule a resize to show more rows if it has more rows to show.
+    // (1.5 rows for good measure to avoid any rounding issues that would
+    // lead to a loop of reflow requests)
+    NS_DispatchToCurrentThread(new nsAsyncResize(this));
+    return eDropDownPositionPendingResize;
+  }
+
+  // Position the drop-down below if there is room, otherwise place it
+  // on the side that has more room.
+  bool b = dropdownSize.height <= below || below >= above;
+  nsPoint dropdownPosition(0, b ? GetRect().height : -dropdownSize.height);
+  if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     // Align the right edge of the drop-down with the right edge of the control.
     dropdownPosition.x = GetRect().width - dropdownSize.width;
-  } else {
-    dropdownPosition.x = 0;
   }
-  dropdownPosition.y = dropdownYOffset; 
+  mDropdownFrame->SetPosition(dropdownPosition + translation);
+  nsContainerFrame::PositionFrameView(mDropdownFrame);
+  return eDropDownPositionFinal;
+}
 
-  mDropdownFrame->SetPosition(dropdownPosition + translation);
+void
+nsComboboxControlFrame::NotifyGeometryChange()
+{
+  // We don't need to resize if we're not dropped down since ShowDropDown
+  // does that, or if we're dirty then the reflow callback does it,
+  // or if we have a delayed ShowDropDown pending.
+  if (IsDroppedDown() &&
+      !(GetStateBits() & NS_FRAME_IS_DIRTY) &&
+      !mDelayedShowDropDown) {
+    // Async because we're likely in a middle of a scroll here so
+    // frame/view positions are in flux.
+    nsRefPtr<nsResizeDropdownAtFinalPosition> resize =
+      new nsResizeDropdownAtFinalPosition(this);
+    NS_DispatchToCurrentThread(resize);
+  }
 }
 
 //----------------------------------------------------------
 // 
 //----------------------------------------------------------
 #ifdef DO_REFLOW_DEBUG
 static int myCounter = 0;
 
@@ -700,16 +861,23 @@ nsComboboxControlFrame::Reflow(nsPresCon
     mListControlFrame->GetOptionText(selectedIndex, selectedOptionText);
   }
   if (mDisplayedOptionText != selectedOptionText) {
     RedisplayText(selectedIndex);
   }
 
   // First reflow our dropdown so that we know how tall we should be.
   ReflowDropdown(aPresContext, aReflowState);
+  nsRefPtr<nsResizeDropdownAtFinalPosition> resize =
+    new nsResizeDropdownAtFinalPosition(this);
+  if (NS_SUCCEEDED(aPresContext->PresShell()->PostReflowCallback(resize))) {
+    // The reflow callback queue doesn't AddRef so we keep it alive until
+    // it's released in its ReflowFinished / ReflowCallbackCanceled.
+    resize.forget();
+  }
 
   // Get the width of the vertical scrollbar.  That will be the width of the
   // dropdown button.
   nscoord buttonWidth;
   const nsStyleDisplay *disp = GetStyleDisplay();
   if (IsThemed(disp) && !aPresContext->GetTheme()->ThemeNeedsComboboxDropmarker()) {
     buttonWidth = 0;
   }
@@ -788,26 +956,35 @@ nsComboboxControlFrame::GetFrameName(nsA
 
 
 //----------------------------------------------------------------------
 // nsIComboboxControlFrame
 //----------------------------------------------------------------------
 void
 nsComboboxControlFrame::ShowDropDown(bool aDoDropDown) 
 {
+  mDelayedShowDropDown = false;
   nsEventStates eventStates = mContent->AsElement()->State();
-  if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
+  if (aDoDropDown && eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return;
   }
 
   if (!mDroppedDown && aDoDropDown) {
-    if (mListControlFrame) {
-      mListControlFrame->SyncViewWithFrame();
+    if (sFocused == this) {
+      DropDownPositionState state = AbsolutelyPositionDropDown();
+      if (state == eDropDownPositionFinal) {
+        ShowList(aDoDropDown); // might destroy us
+      } else if (state == eDropDownPositionPendingResize) {
+        // Delay until after the resize reflow, see nsAsyncResize.
+        mDelayedShowDropDown = true;
+      }
+    } else {
+      // Delay until we get focus, see SetFocus().
+      mDelayedShowDropDown = true;
     }
-    ShowList(aDoDropDown); // might destroy us
   } else if (mDroppedDown && !aDoDropDown) {
     ShowList(aDoDropDown); // might destroy us
   }
 }
 
 void
 nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame)
 {
@@ -1430,17 +1607,17 @@ nsComboboxControlFrame::BuildDisplayList
   return DisplaySelectionOverlay(aBuilder, aLists.Content());
 }
 
 void nsComboboxControlFrame::PaintFocus(nsRenderingContext& aRenderingContext,
                                         nsPoint aPt)
 {
   /* Do we need to do anything? */
   nsEventStates eventStates = mContent->AsElement()->State();
-  if (eventStates.HasState(NS_EVENT_STATE_DISABLED) || mFocused != this)
+  if (eventStates.HasState(NS_EVENT_STATE_DISABLED) || sFocused != this)
     return;
 
   aRenderingContext.PushState();
   nsRect clipRect = mDisplayFrame->GetRect() + aPt;
   aRenderingContext.IntersectClip(clipRect);
 
   // REVIEW: Why does the old code paint mDisplayFrame again? We've
   // already painted it in the children above. So clipping it here won't do
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -132,17 +132,26 @@ public:
    */
   virtual void ShowDropDown(bool aDoDropDown);
   virtual nsIFrame* GetDropDown();
   virtual void SetDropDown(nsIFrame* aDropDownFrame);
   /**
    * @note This method might destroy |this|.
    */
   virtual void RollupFromList();
-  virtual void AbsolutelyPositionDropDown();
+
+  /**
+   * Return the available space above and below this frame for
+   * placing the drop-down list, and the current 2D translation.
+   * Note that either or both can be less than or equal to zero,
+   * if both are then the drop-down should be closed.
+   */
+  void GetAvailableDropdownSpace(nscoord* aAbove,
+                                 nscoord* aBelow,
+                                 nsPoint* aTranslation);
   virtual PRInt32 GetIndexOfDisplayArea();
   /**
    * @note This method might destroy |this|.
    */
   NS_IMETHOD RedisplaySelectedText();
   virtual PRInt32 UpdateRecentIndex(PRInt32 aIndex);
   virtual void OnContentReset();
 
@@ -154,16 +163,17 @@ public:
   NS_IMETHOD OnSetSelectedIndex(PRInt32 aOldIndex, PRInt32 aNewIndex);
 
   //nsIRollupListener
   /**
    * Hide the dropdown menu and stop capturing mouse events.
    * @note This method might destroy |this|.
    */
   virtual nsIContent* Rollup(PRUint32 aCount, bool aGetLastRolledUp = false);
+  virtual void NotifyGeometryChange();
 
   /**
    * A combobox should roll up if a mousewheel event happens outside of
    * the popup area.
    */
   virtual bool ShouldRollupOnMouseWheelEvent()
     { return true; }
 
@@ -179,27 +189,37 @@ public:
 
   //nsIStatefulFrame
   NS_IMETHOD SaveState(SpecialStateID aStateID, nsPresState** aState);
   NS_IMETHOD RestoreState(nsPresState* aState);
 
   static bool ToolkitHasNativePopup();
 
 protected:
+  friend class RedisplayTextEvent;
+  friend class nsAsyncResize;
+  friend class nsResizeDropdownAtFinalPosition;
 
   // Utilities
   nsresult ReflowDropdown(nsPresContext*          aPresContext, 
                           const nsHTMLReflowState& aReflowState);
 
+  enum DropDownPositionState {
+    // can't show the dropdown at its current position
+    eDropDownPositionSuppressed,
+    // a resize reflow is pending, don't show it yet
+    eDropDownPositionPendingResize,
+    // the dropdown has its final size and position and can be displayed here
+    eDropDownPositionFinal
+  };
+  DropDownPositionState AbsolutelyPositionDropDown();
+
   // Helper for GetMinWidth/GetPrefWidth
   nscoord GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
                             nsLayoutUtils::IntrinsicWidthType aType);
-protected:
-  class RedisplayTextEvent;
-  friend class RedisplayTextEvent;
 
   class RedisplayTextEvent : public nsRunnable {
   public:
     NS_DECL_NSIRUNNABLE
     RedisplayTextEvent(nsComboboxControlFrame *c) : mControlFrame(c) {}
     void Revoke() { mControlFrame = nsnull; }
   private:
     nsComboboxControlFrame *mControlFrame;
@@ -237,31 +257,35 @@ protected:
   nsIFrame*                mButtonFrame;             // button frame
   nsIFrame*                mDropdownFrame;           // dropdown list frame
   nsIListControlFrame *    mListControlFrame;        // ListControl Interface for the dropdown frame
 
   // The width of our display area.  Used by that frame's reflow to
   // size to the full width except the drop-marker.
   nscoord mDisplayWidth;
   
-  bool                  mDroppedDown;             // Current state of the dropdown list, true is dropped down
-  bool                  mInRedisplayText;
-
   nsRevocableEventPtr<RedisplayTextEvent> mRedisplayTextEvent;
 
   PRInt32               mRecentSelectedIndex;
   PRInt32               mDisplayedIndex;
   nsString              mDisplayedOptionText;
 
   // make someone to listen to the button. If its programmatically pressed by someone like Accessibility
   // then open or close the combo box.
   nsCOMPtr<nsIDOMEventListener> mButtonListener;
 
+  // Current state of the dropdown list, true is dropped down.
+  bool                  mDroppedDown;
+  // See comment in HandleRedisplayTextEvent().
+  bool                  mInRedisplayText;
+  // Acting on ShowDropDown(true) is delayed until we're focused.
+  bool                  mDelayedShowDropDown;
+
   // static class data member for Bug 32920
   // only one control can be focused at a time
-  static nsComboboxControlFrame * mFocused;
+  static nsComboboxControlFrame* sFocused;
 
 #ifdef DO_REFLOW_COUNTER
   PRInt32 mReflowId;
 #endif
 };
 
 #endif
--- a/layout/forms/nsIComboboxControlFrame.h
+++ b/layout/forms/nsIComboboxControlFrame.h
@@ -56,21 +56,16 @@ public:
   NS_IMETHOD RedisplaySelectedText() = 0;
 
   /**
    * Method for the listbox to set and get the recent index
    */
   virtual PRInt32 UpdateRecentIndex(PRInt32 aIndex) = 0;
 
   /**
-   *
-   */
-  virtual void AbsolutelyPositionDropDown() = 0;
-
-  /**
    * Notification that the content has been reset
    */
   virtual void OnContentReset() = 0;
   
   /**
    * This returns the index of the item that is currently being displayed
    * in the display area. It may differ from what the currently Selected index
    * is in in the dropdown.
--- a/layout/forms/nsIListControlFrame.h
+++ b/layout/forms/nsIListControlFrame.h
@@ -57,21 +57,16 @@ public:
 
   /**
    * Returns the number of options in the listbox
    */
 
   virtual PRInt32 GetNumberOfOptions() = 0; 
 
   /**
-   * 
-   */
-  virtual void SyncViewWithFrame() = 0;
-
-  /**
    * Called by combobox when it's about to drop down
    */
   virtual void AboutToDropDown() = 0;
 
   /**
    * Called by combobox when it's about to roll up
    */
   virtual void AboutToRollup() = 0;
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -48,17 +48,17 @@
 #include "nsDisplayList.h"
 #include "nsContentUtils.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 // Constants
-const nscoord kMaxDropDownRows          = 20; // This matches the setting for 4.x browsers
+const PRInt32 kMaxDropDownRows          = 20; // This matches the setting for 4.x browsers
 const PRInt32 kNothingSelected          = -1;
 
 // Static members
 nsListControlFrame * nsListControlFrame::mFocused = nsnull;
 nsString * nsListControlFrame::sIncrementalString = nsnull;
 
 // Using for incremental typing navigation
 #define INCREMENTAL_SEARCH_KEYPRESS_TIME 1000
@@ -107,16 +107,17 @@ NS_NewListControlFrame(nsIPresShell* aPr
 NS_IMPL_FRAMEARENA_HELPERS(nsListControlFrame)
 
 //---------------------------------------------------------
 nsListControlFrame::nsListControlFrame(
   nsIPresShell* aShell, nsIDocument* aDocument, nsStyleContext* aContext)
   : nsHTMLScrollFrame(aShell, aContext, false),
     mMightNeedSecondPass(false),
     mHasPendingInterruptAtStartOfReflow(false),
+    mDropdownCanGrow(false),
     mLastDropdownComputedHeight(NS_UNCONSTRAINEDSIZE)
 {
   mComboboxFrame      = nsnull;
   mChangesSinceDragStart = false;
   mButtonDown         = false;
 
   mIsAllContentHere   = false;
   mIsAllFramesHere    = false;
@@ -504,33 +505,29 @@ nsListControlFrame::ReflowAsDropdown(nsP
   NS_PRECONDITION(aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE,
                   "We should not have a computed height here!");
   
   mMightNeedSecondPass = NS_SUBTREE_DIRTY(this) ||
     aReflowState.ShouldReflowAllKids();
 
 #ifdef DEBUG
   nscoord oldHeightOfARow = HeightOfARow();
+  nscoord oldVisibleHeight = (GetStateBits() & NS_FRAME_FIRST_REFLOW) ?
+    NS_UNCONSTRAINEDSIZE : GetScrolledFrame()->GetSize().height;
 #endif
 
   nsHTMLReflowState state(aReflowState);
 
-  nscoord oldVisibleHeight;
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     // When not doing an initial reflow, and when the height is auto, start off
     // with our computed height set to what we'd expect our height to be.
     // Note: At this point, mLastDropdownComputedHeight can be
     // NS_UNCONSTRAINEDSIZE in cases when last time we didn't have to constrain
     // the height.  That's fine; just do the same thing as last time.
     state.SetComputedHeight(mLastDropdownComputedHeight);
-    oldVisibleHeight = GetScrolledFrame()->GetSize().height;
-  } else {
-    // Set oldVisibleHeight to something that will never test true against a
-    // real height.
-    oldVisibleHeight = NS_UNCONSTRAINEDSIZE;
   }
 
   nsresult rv = nsHTMLScrollFrame::Reflow(aPresContext, aDesiredSize,
                                           state, aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!mMightNeedSecondPass) {
     NS_ASSERTION(oldVisibleHeight == GetScrolledFrame()->GetSize().height,
@@ -562,63 +559,58 @@ nsListControlFrame::ReflowAsDropdown(nsP
 
   // Gotta reflow again.
   // XXXbz We're just changing the height here; do we need to dirty ourselves
   // or anything like that?  We might need to, per the letter of the reflow
   // protocol, but things seem to work fine without it...  Is that just an
   // implementation detail of nsHTMLScrollFrame that we're depending on?
   nsHTMLScrollFrame::DidReflow(aPresContext, &state, aStatus);
 
-  // Now compute the height we want to have
-  mNumDisplayRows = kMaxDropDownRows;
-  if (visibleHeight > nscoord(mNumDisplayRows * heightOfARow)) {
-    visibleHeight = mNumDisplayRows * heightOfARow;
-    // This is an adaptive algorithm for figuring out how many rows 
-    // should be displayed in the drop down. The standard size is 20 rows, 
-    // but on 640x480 it is typically too big.
-    // This takes the height of the screen divides it by two and then subtracts off 
-    // an estimated height of the combobox. I estimate it by taking the max element size
-    // of the drop down and multiplying it by 2 (this is arbitrary) then subtract off
-    // the border and padding of the drop down (again rather arbitrary)
-    // This all breaks down if the font of the combobox is a lot larger then the option items
-    // or CSS style has set the height of the combobox to be rather large.
-    // We can fix these cases later if they actually happen.
-    nsRect screen = nsFormControlFrame::GetUsableScreenRect(aPresContext);
-    nscoord screenHeight = screen.height;
+  // Now compute the height we want to have.
+  // Note: no need to apply min/max constraints, since we have no such
+  // rules applied to the combobox dropdown.
 
-    nscoord availDropHgt = (screenHeight / 2) - (heightOfARow*2); // approx half screen minus combo size
-    availDropHgt -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
-
-    nscoord hgt = visibleHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
-    if (heightOfARow > 0) {
-      if (hgt > availDropHgt) {
-        visibleHeight = (availDropHgt / heightOfARow) * heightOfARow;
-      }
-      mNumDisplayRows = visibleHeight / heightOfARow;
-    } else {
-      // Hmmm, not sure what to do here. Punt, and make both of them one
-      visibleHeight   = 1;
-      mNumDisplayRows = 1;
-    }
-
-    state.SetComputedHeight(mNumDisplayRows * heightOfARow);
-    // Note: no need to apply min/max constraints, since we have no such
-    // rules applied to the combobox dropdown.
-    // XXXbz this is ending up too big!!  Figure out why.
-  } else if (visibleHeight == 0) {
+  mDropdownCanGrow = false;
+  if (visibleHeight <= 0 || heightOfARow <= 0) {
     // Looks like we have no options.  Just size us to a single row height.
     state.SetComputedHeight(heightOfARow);
+    mNumDisplayRows = 1;
   } else {
-    // Not too big, not too small.  Just use it!
-    state.SetComputedHeight(NS_UNCONSTRAINEDSIZE);
+    nsComboboxControlFrame* combobox = static_cast<nsComboboxControlFrame*>(mComboboxFrame);
+    nsPoint translation;
+    nscoord above, below;
+    combobox->GetAvailableDropdownSpace(&above, &below, &translation);
+    if (above <= 0 && below <= 0) {
+      state.SetComputedHeight(heightOfARow);
+      mNumDisplayRows = 1;
+    } else {
+      nscoord bp = aReflowState.mComputedBorderPadding.TopBottom();
+      nscoord availableHeight = NS_MAX(above, below) - bp;
+      nscoord newHeight;
+      PRInt32 rows;
+      if (visibleHeight <= availableHeight) {
+        // The dropdown fits in the available height.
+        rows = GetNumberOfOptions();
+        mNumDisplayRows = clamped(rows, 1, kMaxDropDownRows);
+        if (mNumDisplayRows == rows) {
+          newHeight = visibleHeight;  // use the exact height
+        } else {
+          newHeight = mNumDisplayRows * heightOfARow; // approximate
+        }
+      } else {
+        rows = availableHeight / heightOfARow;
+        mNumDisplayRows = clamped(rows, 1, kMaxDropDownRows);
+        newHeight = mNumDisplayRows * heightOfARow; // approximate
+      }
+      state.SetComputedHeight(newHeight);
+      mDropdownCanGrow = visibleHeight - newHeight >= heightOfARow &&
+                         mNumDisplayRows != kMaxDropDownRows;
+    }
   }
 
-  // Note: At this point, state.mComputedHeight can be NS_UNCONSTRAINEDSIZE in
-  // cases when there were some options, but not too many (so no scrollbar was
-  // needed).  That's fine; just store that.
   mLastDropdownComputedHeight = state.ComputedHeight();
 
   nsHTMLScrollFrame::WillReflow(aPresContext);
   return nsHTMLScrollFrame::Reflow(aPresContext, aDesiredSize, state, aStatus);
 }
 
 nsGfxScrollFrameInner::ScrollbarStyles
 nsListControlFrame::GetScrollbarStyles() const
@@ -1593,28 +1585,16 @@ nsListControlFrame::GetFormProperty(nsIA
     // You shouldn't be calling me for this!!!
     return NS_ERROR_INVALID_ARG;
   }
 
   return NS_OK;
 }
 
 void
-nsListControlFrame::SyncViewWithFrame()
-{
-    // Resync the view's position with the frame.
-    // The problem is the dropdown's view is attached directly under
-    // the root view. This means its view needs to have its coordinates calculated
-    // as if it were in it's normal position in the view hierarchy.
-  mComboboxFrame->AbsolutelyPositionDropDown();
-
-  nsContainerFrame::PositionFrameView(this);
-}
-
-void
 nsListControlFrame::AboutToDropDown()
 {
   NS_ASSERTION(IsInDropDownMode(),
     "AboutToDropDown called without being in dropdown mode");
 
   // Our widget doesn't get invalidated on changes to the rest of the document,
   // so compute and store this color at the start of a dropdown so we don't
   // get weird painting behaviour.
@@ -1668,24 +1648,17 @@ NS_IMETHODIMP
 nsListControlFrame::DidReflow(nsPresContext*           aPresContext,
                               const nsHTMLReflowState* aReflowState,
                               nsDidReflowStatus        aStatus)
 {
   nsresult rv;
   bool wasInterrupted = !mHasPendingInterruptAtStartOfReflow &&
                           aPresContext->HasPendingInterrupt();
 
-  if (IsInDropDownMode()) 
-  {
-    //SyncViewWithFrame();
-    rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
-    SyncViewWithFrame();
-  } else {
-    rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
-  }
+  rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
 
   if (mNeedToReset && !wasInterrupted) {
     mNeedToReset = false;
     // Suppress scrolling to the selected element if we restored
     // scroll history state AND the list contents have not changed
     // since we loaded all the children AND nothing else forced us
     // to scroll by calling ResetList(true). The latter two conditions
     // are folded into mPostChildrenLoadedReset.
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -125,17 +125,16 @@ public:
    * If the there are zero items then an empty string is returned
    * If there is nothing selected, then the 0th item's text is returned.
    */
   virtual void GetOptionText(PRInt32 aIndex, nsAString & aStr);
 
   virtual void CaptureMouseEvents(bool aGrabMouseEvents);
   virtual nscoord GetHeightOfARow();
   virtual PRInt32 GetNumberOfOptions();  
-  virtual void SyncViewWithFrame();
   virtual void AboutToDropDown();
 
   /**
    * @note This method might destroy |this|.
    */
   virtual void AboutToRollup();
 
   /**
@@ -228,16 +227,27 @@ public:
   }
 
   /**
    * Return whether the list is in dropdown mode.
    */
   bool IsInDropDownMode() const;
 
   /**
+   * Return the number of displayed rows in the list.
+   */
+  PRUint32 GetNumDisplayRows() const { return mNumDisplayRows; }
+
+  /**
+   * Return true if the drop-down list can display more rows.
+   * (always false if not in drop-down mode)
+   */
+  bool GetDropdownCanGrow() const { return mDropdownCanGrow; }
+
+  /**
    * Dropdowns need views
    */
   virtual bool NeedsView() { return IsInDropDownMode(); }
 
   /**
    * Frees statics owned by this class.
    */
   static void Shutdown();
@@ -409,16 +419,20 @@ protected:
   bool mMightNeedSecondPass:1;
 
   /**
    * Set to aPresContext->HasPendingInterrupt() at the start of Reflow.
    * Set to false at the end of DidReflow.
    */
   bool mHasPendingInterruptAtStartOfReflow:1;
 
+  // True if the drop-down can show more rows.  Always false if this list
+  // is not in drop-down mode.
+  bool mDropdownCanGrow:1;
+  
   // The last computed height we reflowed at if we're a combobox dropdown.
   // XXXbz should we be using a subclass here?  Or just not worry
   // about the extra member on listboxes?
   nscoord mLastDropdownComputedHeight;
 
   // At the time of our last dropdown, the backstop color to draw in case we
   // are translucent.
   nscolor mLastDropdownBackstopColor;
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1659,16 +1659,19 @@ nsGfxScrollFrameInner::AsyncScrollCallba
                          (unlimitedRange + destination).UnionEdges(range));
       return;
     }
   }
 
   // Apply desired destination range since this is the last step of scrolling.
   self->mAsyncScroll = nsnull;
   self->ScrollToImpl(self->mDestination, range);
+  // We are done scrolling, set our destination to wherever we actually ended
+  // up scrolling to.
+  self->mDestination = self->GetScrollPosition();
 }
 
 void
 nsGfxScrollFrameInner::ScrollToCSSPixels(nsIntPoint aScrollPosition)
 {
   nsPoint current = GetScrollPosition();
   nsPoint pt(nsPresContext::CSSPixelsToAppUnits(aScrollPosition.x),
              nsPresContext::CSSPixelsToAppUnits(aScrollPosition.y));
@@ -1706,16 +1709,19 @@ nsGfxScrollFrameInner::ScrollToWithOrigi
 
   nsRect range = aRange ? *aRange : nsRect(aScrollPosition, nsSize(0, 0));
 
   if (aMode == nsIScrollableFrame::INSTANT) {
     // Asynchronous scrolling is not allowed, so we'll kill any existing
     // async-scrolling process and do an instant scroll.
     mAsyncScroll = nsnull;
     ScrollToImpl(mDestination, range);
+    // We are done scrolling, set our destination to wherever we actually ended
+    // up scrolling to.
+    mDestination = GetScrollPosition();
     return;
   }
 
   TimeStamp now = TimeStamp::Now();
   nsPoint currentPosition = GetScrollPosition();
   nsSize currentVelocity(0, 0);
   bool isSmoothScroll = (aMode == nsIScrollableFrame::SMOOTH) &&
                           IsSmoothScrollingEnabled();
@@ -1726,16 +1732,19 @@ nsGfxScrollFrameInner::ScrollToWithOrigi
       currentVelocity = mAsyncScroll->VelocityAt(now);
     }
   } else {
     mAsyncScroll = new AsyncScroll;
     if (!mAsyncScroll->SetRefreshObserver(this)) {
       mAsyncScroll = nsnull;
       // Observer setup failed. Scroll the normal way.
       ScrollToImpl(mDestination, range);
+      // We are done scrolling, set our destination to wherever we actually
+      // ended up scrolling to.
+      mDestination = GetScrollPosition();
       return;
     }
   }
 
   mAsyncScroll->mIsSmoothScroll = isSmoothScroll;
 
   if (isSmoothScroll) {
     mAsyncScroll->InitSmoothScroll(now, currentPosition, currentVelocity,
--- a/layout/reftests/bugs/621253-1-ref.html
+++ b/layout/reftests/bugs/621253-1-ref.html
@@ -1,9 +1,6 @@
 <html>
 <body style="margin: 0">
   <div style="background: black;
-              width: 25px; height: 25px"></div>
-  <!-- XXXdholbert The above div should actually be 50x50 instead of 25x25, but
-       bug 541270 makes our testcases render smaller than they should. Once
-       that bug is fixed, we need a s/25px/50px/ in this file. -->
+              width: 50px; height: 50px"></div>
 </body>
 </html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1617,18 +1617,18 @@ needs-focus == 613433-3.html 613433-1-re
 needs-focus == 613433-3.html 613433-2-ref.html
 needs-focus == 613433-3.html 613433-3-ref.html
 == 614272-1.svg  614272-1-ref.svg
 HTTP(..) == 615121-1.html 615121-1-ref.html
 HTTP(..) != 615121-2.html 615121-2-notref.html
 == 617242-1.html 617242-1-ref.html
 != 618071.html 618071-notref.html
 == 619117-1.html 619117-1-ref.html
-skip-if(Android) HTTP(..) == 621253-1-externalFilter.html 621253-1-ref.html # XXX update reference case after bug 541270 is fixed
-skip-if(Android) == 621253-1-internalFilter.html 621253-1-ref.html # XXX update reference case after bug 541270 is fixed
+skip-if(Android) HTTP(..) == 621253-1-externalFilter.html 621253-1-ref.html
+skip-if(Android) == 621253-1-internalFilter.html 621253-1-ref.html
 HTTP(..) == 621253-2-externalFilter.html 621253-2-ref.html
 == 621253-2-internalFilter.html 621253-2-ref.html
 fails-if(Android) HTTP(..) == 619511-1.html 619511-1-ref.html
 random-if(winWidget) == 621918-1.svg 621918-1-ref.svg # 1-pixel diacritic positioning discrepancy in rotated text (may depend on platform fonts)
 random-if(winWidget) HTTP(..) == 621918-2.svg 621918-2-ref.svg # same 1px issue as above, and HTTP(..) for filters.svg, used to mask antialiasing issues where glyphs touch
 == 622585-1.html 622585-1-ref.html
 fails-if(Android) == 625409-1.html 625409-1-ref.html
 == 627393-1.html about:blank
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -299,10 +299,10 @@ random-if(/^Windows\x20NT\x205\.1/.test(
 == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
 == viewBox-and-pattern-01.svg pass.svg
 == viewBox-invalid-01.svg pass.svg
 == viewBox-valid-01.svg pass.svg
 == viewport-percent-graphic-user-01.svg pass.svg
 
 == svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
 == svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
-fails == svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml # Bug 541270
+== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
 == href-attr-change-restyles.svg href-attr-change-restyles-ref.svg
--- a/layout/reftests/transform/reftest.list
+++ b/layout/reftests/transform/reftest.list
@@ -88,17 +88,17 @@ random == rotate-1f.html rotate-1-ref.ht
 == matrix-3a.html matrix-3-ref.html
 == matrix-4a.html matrix-4-ref.html
 == matrix-5a.html matrix-5-ref.html
 == matrix-6a.html matrix-6-ref.html
 == matrix-7a.html matrix-7-ref.html
 # ensure matrix 3d does not break us - should do nothing
 == matrix3d-1.html matrix3d-1-ref.html
 # Test that complex transform can be reversed
-fails-if(Android) == stresstest-1.html stresstest-1-ref.html
+fails-if(Android) fuzzy-if(cocoaWidget,1,2) == stresstest-1.html stresstest-1-ref.html
 # Test scale transforms
 == scalex-1.html scalex-1-ref.html
 == scaley-1.html scaley-1-ref.html
 == scale-1a.html scale-1-ref.html
 == scale-1b.html scale-1-ref.html
 == scale-percent-1.html scale-percent-1-ref.html
 # Some simple checks that it obeys selector operations
 == descendant-1.html descendant-1-ref.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -587,17 +587,17 @@ protected:
                                 PRUint16 aMaxElems,
                                 InfallibleTArray<nsCSSValue>& aOutput);
 
   /* Functions for transform-origin/perspective-origin Parsing */
   bool ParseTransformOrigin(bool aPerspective);
 
   /* Find and return the namespace ID associated with aPrefix.
      If aPrefix has not been declared in an @namespace rule, returns
-     kNameSpaceID_Unknown and sets mFoundUnresolvablePrefix to true. */
+     kNameSpaceID_Unknown. */
   PRInt32 GetNamespaceIdForPrefix(const nsString& aPrefix);
 
   /* Find the correct default namespace, and set it on aSelector. */
   void SetDefaultNamespaceOnSelector(nsCSSSelector& aSelector);
 
   // Current token. The value is valid after calling GetToken and invalidated
   // by UngetToken.
   nsCSSToken mToken;
@@ -647,20 +647,16 @@ protected:
   // True for parsing media lists for HTML attributes, where we have to
   // ignore CSS comments.
   bool mHTMLMediaMode : 1;
 
   // This flag is set when parsing a non-box shorthand; it's used to not apply
   // some quirks during shorthand parsing
   bool          mParsingCompoundProperty : 1;
 
-  // GetNamespaceIdForPrefix will set mFoundUnresolvablePrefix to true
-  // when it encounters a prefix that is not mapped to a namespace.
-  bool          mFoundUnresolvablePrefix : 1;
-
 #ifdef DEBUG
   bool mScannerInited : 1;
 #endif
 
   // Stack of rule groups; used for @media and such.
   InfallibleTArray<nsRefPtr<css::GroupRule> > mGroupStack;
 
   // During the parsing of a property (which may be a shorthand), the data
@@ -735,18 +731,17 @@ CSSParserImpl::CSSParserImpl()
     mScanner(),
     mChildLoader(nsnull),
     mSection(eCSSSection_Charset),
     mNameSpaceMap(nsnull),
     mHavePushBack(false),
     mNavQuirkMode(false),
     mUnsafeRulesEnabled(false),
     mHTMLMediaMode(false),
-    mParsingCompoundProperty(false),
-    mFoundUnresolvablePrefix(false)
+    mParsingCompoundProperty(false)
 #ifdef DEBUG
     , mScannerInited(false)
 #endif
     , mNextFree(nsnull)
 {
 }
 
 CSSParserImpl::~CSSParserImpl()
@@ -1188,22 +1183,17 @@ CSSParserImpl::ParseSelectorString(const
                                    nsIURI* aURI, // for error reporting
                                    PRUint32 aLineNumber, // for error reporting
                                    nsCSSSelectorList **aSelectorList)
 {
   InitScanner(aSelectorString, aURI, aLineNumber, aURI, nsnull);
 
   AssertInitialState();
 
-  // This is the only place that cares about mFoundUnresolvablePrefix,
-  // so this is the only place that bothers clearing it.
-  mFoundUnresolvablePrefix = false;
-
   bool success = ParseSelectorList(*aSelectorList, PRUnichar(0));
-  bool prefixErr = mFoundUnresolvablePrefix;
 
   // We deliberately do not call OUTPUT_ERROR here, because all our
   // callers map a failure return to a JS exception, and if that JS
   // exception is caught, people don't want to see parser diagnostics;
   // see e.g. http://bugs.jquery.com/ticket/7535
   // It would be nice to be able to save the parser diagnostics into
   // the exception, so that if it _isn't_ caught we can report them
   // along with the usual uncaught-exception message, but we don't
@@ -1212,18 +1202,16 @@ CSSParserImpl::ParseSelectorString(const
   ReleaseScanner();
 
   if (success) {
     NS_ASSERTION(*aSelectorList, "Should have list!");
     return NS_OK;
   }
 
   NS_ASSERTION(!*aSelectorList, "Shouldn't have list!");
-  if (prefixErr)
-    return NS_ERROR_DOM_NAMESPACE_ERR;
 
   return NS_ERROR_DOM_SYNTAX_ERR;
 }
 
 
 already_AddRefed<nsCSSKeyframeRule>
 CSSParserImpl::ParseKeyframeRule(const nsSubstring&  aBuffer,
                                  nsIURI*             aURI,
@@ -9245,17 +9233,16 @@ CSSParserImpl::GetNamespaceIdForPrefix(c
   }
   // else no declared namespaces
 
   if (nameSpaceID == kNameSpaceID_Unknown) {   // unknown prefix, dump it
     const PRUnichar *params[] = {
       aPrefix.get()
     };
     REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
-    mFoundUnresolvablePrefix = true;
   }
 
   return nameSpaceID;
 }
 
 void
 CSSParserImpl::SetDefaultNamespaceOnSelector(nsCSSSelector& aSelector)
 {
--- a/layout/svg/base/src/nsSVGEffects.cpp
+++ b/layout/svg/base/src/nsSVGEffects.cpp
@@ -230,17 +230,18 @@ nsSVGFilterProperty::GetFilterFrame()
 {
   return static_cast<nsSVGFilterFrame *>
     (GetReferencedFrame(nsGkAtoms::svgFilterFrame, nsnull));
 }
 
 static void
 InvalidateAllContinuations(nsIFrame* aFrame)
 {
-  for (nsIFrame* f = aFrame; f; f = f->GetNextContinuation()) {
+  for (nsIFrame* f = aFrame; f;
+       f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(f)) {
     f->InvalidateOverflowRect();
   }
 }
 
 void
 nsSVGFilterProperty::DoUpdate()
 {
   nsSVGIDRenderingObserver::DoUpdate();
--- a/layout/svg/base/src/nsSVGFilterFrame.cpp
+++ b/layout/svg/base/src/nsSVGFilterFrame.cpp
@@ -63,50 +63,44 @@ private:
 
 class NS_STACK_CLASS nsAutoFilterInstance {
 public:
   nsAutoFilterInstance(nsIFrame *aTarget,
                        nsSVGFilterFrame *aFilterFrame,
                        nsSVGFilterPaintCallback *aPaint,
                        const nsIntRect *aPostFilterDirtyRect,
                        const nsIntRect *aPreFilterDirtyRect,
-                       const nsIntRect *aOverrideSourceBBox,
+                       const gfxRect *aOverrideBBox,
                        const gfxMatrix *aOverrideUserToDeviceSpace = nsnull);
   ~nsAutoFilterInstance() {}
 
   // If this returns null, then draw nothing. Either the filter draws
   // nothing or it is "in error".
   nsSVGFilterInstance* get() { return mInstance; }
 
 private:
   nsAutoPtr<nsSVGFilterInstance> mInstance;
 };
 
 nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
                                            nsSVGFilterFrame *aFilterFrame,
                                            nsSVGFilterPaintCallback *aPaint,
                                            const nsIntRect *aPostFilterDirtyRect,
                                            const nsIntRect *aPreFilterDirtyRect,
-                                           const nsIntRect *aOverrideSourceBBox,
+                                           const gfxRect *aOverrideBBox,
                                            const gfxMatrix *aOverrideUserToDeviceSpace)
 {
   const nsSVGFilterElement *filter = aFilterFrame->GetFilterContent();
 
   PRUint16 filterUnits =
     aFilterFrame->GetEnumValue(nsSVGFilterElement::FILTERUNITS);
   PRUint16 primitiveUnits =
     aFilterFrame->GetEnumValue(nsSVGFilterElement::PRIMITIVEUNITS);
 
-  gfxRect bbox;
-  if (aOverrideSourceBBox) {
-    bbox = gfxRect(aOverrideSourceBBox->x, aOverrideSourceBBox->y,
-                   aOverrideSourceBBox->width, aOverrideSourceBBox->height);
-  } else {
-    bbox = nsSVGUtils::GetBBox(aTarget);
-  }
+  gfxRect bbox = aOverrideBBox ? *aOverrideBBox : nsSVGUtils::GetBBox(aTarget);
 
   // Get the filter region (in the filtered element's user space):
 
   // XXX if filterUnits is set (or has defaulted) to objectBoundingBox, we
   // should send a warning to the error console if the author has used lengths
   // with units. This is a common mistake and can result in filterRes being
   // *massive* below (because we ignore the units and interpret the number as
   // a factor of the bbox width/height). We should also send a warning if the
@@ -202,21 +196,22 @@ nsAutoFilterInstance::nsAutoFilterInstan
     MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aPostFilterDirtyRect);
   nsIntRect preFilterDirtyRect =
     MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aPreFilterDirtyRect);
   nsIntRect targetBoundsDeviceSpace;
   nsISVGChildFrame* svgTarget = do_QueryFrame(aTarget);
   if (svgTarget) {
     if (aOverrideUserToDeviceSpace) {
       // If aOverrideUserToDeviceSpace is specified, it is a simple
-      // CSS-px-to-dev-px transform passed by nsSVGFilterFrame::GetFilterBBox()
-      // when requesting the filter expansion of the overflow rects in frame
-      // space. In this case GetCoveredRegion() is not what we want since it is
-      // in outer-<svg> space, GetFilterBBox passes in the pre-filter bounds of
-      // the frame in frame space for us to use instead.
+      // CSS-px-to-dev-px transform passed by nsSVGFilterFrame::
+      // GetPostFilterBounds() when requesting the filter expansion of the
+      // overflow rects in frame space. In this case GetCoveredRegion() is not
+      // what we want since it is in outer-<svg> space, so GetPostFilterBounds
+      // passes in the pre-filter bounds of the frame in frame space for us to
+      // use instead.
       NS_ASSERTION(aPreFilterDirtyRect, "Who passed aOverrideUserToDeviceSpace?");
       targetBoundsDeviceSpace = *aPreFilterDirtyRect;
     } else {
       targetBoundsDeviceSpace =
         svgTarget->GetCoveredRegion().ToOutsidePixels(aTarget->
           PresContext()->AppUnitsPerDevPixel());
     }
   }
@@ -461,17 +456,17 @@ nsSVGFilterFrame::GetPreFilterNeededArea
       return neededRect;
   }
 
   return nsIntRect();
 }
 
 nsIntRect
 nsSVGFilterFrame::GetPostFilterBounds(nsIFrame *aFilteredFrame,
-                                      const nsIntRect *aOverrideBBox,
+                                      const gfxRect *aOverrideBBox,
                                       const nsIntRect *aPreFilterBounds)
 {
   bool overrideCTM = false;
   gfxMatrix ctm;
 
   if (aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
     // For most filter operations on SVG frames we want information in
     // outer-<svg> device space, but in this case we want the visual overflow
--- a/layout/svg/base/src/nsSVGFilterFrame.h
+++ b/layout/svg/base/src/nsSVGFilterFrame.h
@@ -64,23 +64,26 @@ public:
    * given post-filter area needs to be repainted. The rects are in device
    * pixels, relative to the origin of the outer-<svg> if aFilteredFrame is
    * SVG, or else relative to aFilteredFrame itself.
    */
   nsIntRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
                                    const nsIntRect& aPostFilterDirtyRect);
 
   /**
-   * Returns the post-filter paint bounds of aFilteredFrame. The rects are in
-   * device pixels, relative to the origin of the outer-<svg> if aFilteredFrame
-   * is SVG, or else relative to aFilteredFrame itself.
-   * @param aOverrideBBox overrides the normal bbox for the source, if non-null
+   * Returns the post-filter paint bounds of aFilteredFrame. The rects are
+   * relative to the origin of the outer-<svg> if aFilteredFrame is SVG, or
+   * else relative to aFilteredFrame itself.
+   * @param aOverrideBBox A user space rect that should be used as
+   *   aFilteredFrame's bbox, if non-null.
+   * @param aPreFilterBounds The pre-filter visual overflow rect of
+   *   aFilteredFrame in device pixels, if non-null.
    */
   nsIntRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
-                                const nsIntRect *aOverrideBBox = nsnull,
+                                const gfxRect *aOverrideBBox = nsnull,
                                 const nsIntRect *aPreFilterBounds = nsnull);
 
 #ifdef DEBUG
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 #endif
 
--- a/layout/svg/base/src/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/base/src/nsSVGIntegrationUtils.cpp
@@ -192,16 +192,48 @@ nsSVGIntegrationUtils::GetSVGBBoxForNonS
     nsLayoutUtils::GetFirstContinuationOrSpecialSibling(aNonSVGFrame);
   // 'r' is in "user space":
   nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nsnull, nsRect(),
                                               GetOffsetToUserSpace(firstFrame));
   return nsLayoutUtils::RectToGfxRect(r,
            aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
 }
 
+// XXX Since we're called during reflow, this method is broken for frames with
+// continuations. When we're called for a frame with continuations, we're
+// called for each continuation in turn as it's reflowed. However, it isn't
+// until the last continuation is reflowed that this method's
+// GetOffsetToUserSpace() and GetPreEffectsVisualOverflowUnion() calls will
+// obtain valid border boxes for all the continuations. As a result, we'll
+// end up returning bogus post-filter visual overflow rects for all the prior
+// continuations. Unfortunately, by the time the last continuation is
+// reflowed, it's too late to go back and set and propagate the overflow
+// rects on the previous continuations.
+//
+// The reason that we need to pass an override bbox to
+// GetPreEffectsVisualOverflowUnion rather than just letting it call into our
+// GetSVGBBoxForNonSVGFrame method is because we get called by
+// ComputeOutlineAndEffectsRect when it has been called with
+// aStoreRectProperties set to false. In this case the pre-effects visual
+// overflow rect that it has been passed may be different to that stored on
+// aFrame, resulting in a different bbox.
+//
+// XXXjwatt The pre-effects visual overflow rect passed to
+// ComputeOutlineAndEffectsRect won't include continuation overflows, so
+// for frames with continuation the following filter analysis will likely end
+// up being carried out with a bbox created as if the frame didn't have
+// continuations.
+//
+// XXXjwatt Using aPreEffectsOverflowRect to create the bbox isn't really right
+// for SVG frames, since for SVG frames the SVG spec defines the bbox to be
+// something quite different to the pre-effects visual overflow rect. However,
+// we're essentially calculating an invalidation area here, and using the
+// pre-effects overflow rect will actually overestimate that area which, while
+// being a bit wasteful, isn't otherwise a problem.
+//
 nsRect
   nsSVGIntegrationUtils::
     ComputePostEffectsVisualOverflowRect(nsIFrame* aFrame,
                                          const nsRect& aPreEffectsOverflowRect)
 {
   NS_ASSERTION(!(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
                  "Don't call this on SVG child frames");
 
@@ -209,49 +241,32 @@ nsRect
     nsLayoutUtils::GetFirstContinuationOrSpecialSibling(aFrame);
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(firstFrame);
   nsSVGFilterFrame *filterFrame = effectProperties.mFilter ?
     effectProperties.mFilter->GetFilterFrame() : nsnull;
   if (!filterFrame)
     return aPreEffectsOverflowRect;
 
-  // XXX Since we're called during reflow, this is broken for frames with
-  // continuations. When we're called for a frame with continuations, we're
-  // called for each continuation in turn as they're reflowed. However, it
-  // isn't until the last continuation is reflowed that the following
-  // GetOffsetToUserSpace() and GetPreEffectsVisualOverflowUnion() calls will
-  // obtain valid border boxes for all the continuations. As a result, we'll
-  // end up returning bogus post-filter visual overflow rects for all the prior
-  // continuations. Unfortunately, by the time the last continuation is
-  // reflowed, it's too late to go back and set and propagate the overflow
-  // rects on the previous continuations.
-  //
-  // XXXjwatt It seems like the only reason we pass an override bbox to
-  // GetPostFilterBounds instead of just letting the filter code call into our
-  // GetSVGBBoxForNonSVGFrame method is as a slight optimization so
-  // GetPreEffectsVisualOverflowUnion won't have to look up the
-  // aPreEffectsOverflowRect that we have to hand. The bbox we provide is
-  // the same as the bbox it would otherwise get - well, almost. We do round it
-  // out to pixel boundaries, but does that matter? If so, it would have been
-  // nice to have a comment here explaining why (and should
-  // GetSVGBBoxForNonSVGFrame also round out?). If not, it doesn't look like
-  // the extra code complexity is worth it to me.
-  PRUint32 appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
+  // Create an override bbox - see comment above:
   nsPoint firstFrameToUserSpace = GetOffsetToUserSpace(firstFrame);
-  // overrideBBox is in "user space", in dev pixels:
-  nsIntRect overrideBBox =
-    GetPreEffectsVisualOverflowUnion(firstFrame, aFrame,
-                                     aPreEffectsOverflowRect,
-                                     firstFrameToUserSpace).
-      ToOutsidePixels(appUnitsPerDevPixel);
+  // overrideBBox is in "user space", in _CSS_ pixels:
+  // XXX Why are we rounding out to pixel boundaries? We don't do that in
+  // GetSVGBBoxForNonSVGFrame, and it doesn't appear to be necessary.
+  gfxRect overrideBBox =
+    nsLayoutUtils::RectToGfxRect(
+      GetPreEffectsVisualOverflowUnion(firstFrame, aFrame,
+                                       aPreEffectsOverflowRect,
+                                       firstFrameToUserSpace),
+      aFrame->PresContext()->AppUnitsPerCSSPixel());
+  overrideBBox.RoundOut();
 
   nsRect overflowRect =
     filterFrame->GetPostFilterBounds(firstFrame, &overrideBBox).
-                   ToAppUnits(appUnitsPerDevPixel);
+                   ToAppUnits(aFrame->PresContext()->AppUnitsPerDevPixel());
 
   // Return overflowRect relative to aFrame, rather than "user space":
   return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
 }
 
 nsRect
 nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
                                                       const nsRect& aInvalidRect)
--- a/layout/xul/base/public/nsXULPopupManager.h
+++ b/layout/xul/base/public/nsXULPopupManager.h
@@ -285,16 +285,17 @@ public:
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIDOMEVENTLISTENER
 
   // nsIRollupListener
   virtual nsIContent* Rollup(PRUint32 aCount, bool aGetLastRolledUp = false);
   virtual bool ShouldRollupOnMouseWheelEvent();
   virtual bool ShouldRollupOnMouseActivate();
   virtual PRUint32 GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain);
+  virtual void NotifyGeometryChange() {}
 
   static nsXULPopupManager* sInstance;
 
   // initialize and shutdown methods called by nsLayoutStatics
   static nsresult Init();
   static void Shutdown();
 
   // returns a weak reference to the popup manager instance, could return null
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -1377,16 +1377,23 @@ void nsMenuPopupFrame::CanAdjustEdges(PR
 }
 
 bool nsMenuPopupFrame::ConsumeOutsideClicks()
 {
   // If the popup has explicitly set a consume mode, honor that.
   if (mConsumeRollupEvent != nsIPopupBoxObject::ROLLUP_DEFAULT)
     return (mConsumeRollupEvent == nsIPopupBoxObject::ROLLUP_CONSUME);
 
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
+                            nsGkAtoms::_true, eCaseMatters))
+    return true;
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
+                            nsGkAtoms::_false, eCaseMatters))
+    return false;
+
   nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
   if (parentContent) {
     nsINodeInfo *ni = parentContent->NodeInfo();
     if (ni->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL))
       return true;  // Consume outside clicks for combo boxes on all platforms
 #if defined(XP_WIN) || defined(XP_OS2)
     // Don't consume outside clicks for menus in Windows
     if (ni->Equals(nsGkAtoms::menu, kNameSpaceID_XUL) ||
new file mode 100644
--- /dev/null
+++ b/media/webrtc/Android.mk
@@ -0,0 +1,5 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# empty file to block B2G/Gonk from trying to build anything inside media/webrtc
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -167,23 +167,20 @@ public class AwesomeBar extends GeckoAct
 
         mText.addTextChangedListener(new TextWatcher() {
             public void afterTextChanged(Editable s) {
                 String text = s.toString();
                 mAwesomeTabs.filter(text);
 
                 // If the AwesomeBar has a composition string, don't call updateGoButton().
                 // That method resets IME and composition state will be broken.
-                if (hasCompositionString(s)) {
-                    return;
+                if (!hasCompositionString(s)) {
+                    updateGoButton(text);
                 }
 
-                // no composition string. It is safe to update IME flags.
-                updateGoButton(text);
-
                 // cancel previous query
                 if (mSuggestTask != null) {
                     mSuggestTask.cancel(true);
                 }
 
                 if (mSuggestClient != null) {
                     mSuggestTask = new AsyncTask<String, Void, ArrayList<String>>() {
                          protected ArrayList<String> doInBackground(String... query) {
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -569,16 +569,17 @@ abstract public class BrowserApp extends
         Tab tab = Tabs.getInstance().getSelectedTab();
         MenuItem bookmark = aMenu.findItem(R.id.bookmark);
         MenuItem forward = aMenu.findItem(R.id.forward);
         MenuItem share = aMenu.findItem(R.id.share);
         MenuItem readingList = aMenu.findItem(R.id.reading_list);
         MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
         MenuItem charEncoding = aMenu.findItem(R.id.char_encoding);
         MenuItem findInPage = aMenu.findItem(R.id.find_in_page);
+        MenuItem desktopMode = aMenu.findItem(R.id.desktop_mode);
 
         if (tab == null || tab.getURL() == null) {
             bookmark.setEnabled(false);
             forward.setEnabled(false);
             share.setEnabled(false);
             readingList.setEnabled(false);
             saveAsPDF.setEnabled(false);
             findInPage.setEnabled(false);
@@ -603,16 +604,17 @@ abstract public class BrowserApp extends
             readingList.setChecked(true);
             readingList.setIcon(R.drawable.ic_menu_reading_list_remove);
         } else {
             readingList.setChecked(false);
             readingList.setIcon(R.drawable.ic_menu_reading_list_add);
         }
 
         forward.setEnabled(tab.canDoForward());
+        desktopMode.setChecked(tab.getDesktopMode());
 
         // Disable share menuitem for about:, chrome:, file:, and resource: URIs
         String scheme = Uri.parse(tab.getURL()).getScheme();
         share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") ||
                            scheme.equals("file") || scheme.equals("resource")));
 
         // Disable save as PDF for about:home and xul pages
         saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -693,16 +693,29 @@ abstract public class GeckoApp
                 loadUrlInTab("about:downloads");
                 return true;
             case R.id.char_encoding:
                 GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("CharEncoding:Get", null));
                 return true;
             case R.id.find_in_page:
                 mFindInPageBar.show();
                 return true;
+            case R.id.desktop_mode:
+                Tab selectedTab = Tabs.getInstance().getSelectedTab();
+                if (selectedTab == null)
+                    return true;
+                JSONObject args = new JSONObject();
+                try {
+                    args.put("desktopMode", !item.isChecked());
+                    args.put("tabId", selectedTab.getId());
+                } catch (JSONException e) {
+                    Log.e(LOGTAG, "error building json arguments");
+                }
+                GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("DesktopMode:Change", args.toString()));
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
     }
 
     private void shareCurrentUrl() {
       Tab tab = Tabs.getInstance().getSelectedTab();
       if (tab == null)
@@ -1210,16 +1223,30 @@ abstract public class GeckoApp
                 String name = message.getString("name");
                 String launchPath = message.getString("launchPath");
                 String iconURL = message.getString("iconURL");
                 String uniqueURI = message.getString("uniqueURI");
                 GeckoAppShell.createShortcut(name, launchPath, uniqueURI, iconURL, "webapp");
             } else if (event.equals("WebApps:Uninstall")) {
                 String uniqueURI = message.getString("uniqueURI");
                 GeckoAppShell.uninstallWebApp(uniqueURI);
+            } else if (event.equals("DesktopMode:Changed")) {
+                int tabId = message.getInt("tabId");
+                boolean desktopMode = message.getBoolean("desktopMode");
+                final Tab tab = Tabs.getInstance().getTab(tabId);
+                if (tab == null)
+                    return;
+
+                tab.setDesktopMode(desktopMode);
+                mMainHandler.post(new Runnable() {
+                    public void run() {
+                        if (tab == Tabs.getInstance().getSelectedTab())
+                            invalidateOptionsMenu();
+                    }
+                });
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     void onStatePurged() { }
 
@@ -1885,16 +1912,17 @@ abstract public class GeckoApp
         GeckoAppShell.registerGeckoEventListener("Session:StatePurged", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Bookmark:Insert", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Accessibility:Event", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Accessibility:Ready", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Shortcut:Remove", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("WebApps:Open", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("WebApps:Install", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("WebApps:Uninstall", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("DesktopMode:Changed", GeckoApp.mAppContext);
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
         }
 
         mBatteryReceiver = new GeckoBatteryManager();
         mBatteryReceiver.registerFor(mAppContext);
 
@@ -2227,16 +2255,17 @@ abstract public class GeckoApp
         GeckoAppShell.unregisterGeckoEventListener("Session:StatePurged", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Bookmark:Insert", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Accessibility:Event", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Accessibility:Ready", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Shortcut:Remove", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("WebApps:Open", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("WebApps:Install", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("WebApps:Uninstall", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("DesktopMode:Changed", GeckoApp.mAppContext);
 
         if (mFavicons != null)
             mFavicons.close();
 
         if (SmsManager.getInstance() != null) {
             SmsManager.getInstance().stop();
             if (isFinishing())
                 SmsManager.getInstance().shutdown();
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -2234,18 +2234,18 @@ class ScreenshotHandler {
             Tab tab = Tabs.getInstance().getSelectedTab();
             ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
             
             if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) {
                 float width = right - left;
                 float height = bottom - top;
                 scheduleCheckerboardScreenshotEvent(tab.getId(), 
                                                     (int)left, (int)top, (int)width, (int)height, 
-                                                    (int)(sLastCheckerboardWidthRatio * left), 
-                                                    (int)(sLastCheckerboardHeightRatio * top),
+                                                    (int)(sLastCheckerboardWidthRatio * (left - viewport.cssPageRectLeft)),
+                                                    (int)(sLastCheckerboardHeightRatio * (top - viewport.cssPageRectTop)),
                                                     (int)(sLastCheckerboardWidthRatio * width),
                                                     (int)(sLastCheckerboardHeightRatio * height),
                                                     sCheckerboardBufferWidth, sCheckerboardBufferHeight);
             } else {
                 GeckoAppShell.screenshotWholePage(tab);
             }
         }
 
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -64,16 +64,17 @@ public final class Tab {
     private ArrayList<View> mPluginViews;
     private HashMap<Object, Layer> mPluginLayers;
     private ContentResolver mContentResolver;
     private ContentObserver mContentObserver;
     private int mCheckerboardColor = Color.WHITE;
     private int mState;
     private ByteBuffer mThumbnailBuffer;
     private Bitmap mThumbnailBitmap;
+    private boolean mDesktopMode;
 
     public static final int STATE_DELAYED = 0;
     public static final int STATE_LOADING = 1;
     public static final int STATE_SUCCESS = 2;
     public static final int STATE_ERROR = 3;
 
     public Tab(int id, String url, boolean external, int parentId, String title) {
         mId = id;
@@ -656,9 +657,17 @@ public final class Tab {
             return Color.WHITE;
         }
 
         int r = Integer.parseInt(matcher.group(1));
         int g = Integer.parseInt(matcher.group(2));
         int b = Integer.parseInt(matcher.group(3));
         return Color.rgb(r, g, b);
     }
+
+    public void setDesktopMode(boolean enabled) {
+        mDesktopMode = enabled;
+    }
+
+    public boolean getDesktopMode() {
+        return mDesktopMode;
+    }
 }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -91,16 +91,17 @@
 <!ENTITY addons "Add-ons">
 <!ENTITY downloads "Downloads">
 <!ENTITY char_encoding "Character Encoding">
 
 <!ENTITY share "Share">
 <!ENTITY share_title "Share via">
 <!ENTITY save_as_pdf "Save as PDF">
 <!ENTITY find_in_page "Find in Page">
+<!ENTITY desktop_mode "Request Desktop Site">
 
 <!-- Localization note (find_text, find_prev, find_next, find_close) : These strings are used
      as alternate text for accessibility. They are not visible in the UI. -->
 <!ENTITY find_text "Find in Page">
 <!ENTITY find_prev "Previous">
 <!ENTITY find_next "Next">
 <!ENTITY find_close "Close">
 
--- a/mobile/android/base/resources/menu-sw600dp/gecko_menu.xml.in
+++ b/mobile/android/base/resources/menu-sw600dp/gecko_menu.xml.in
@@ -31,16 +31,20 @@
 
     <item gecko:id="@+id/save_as_pdf"
           gecko:icon="@drawable/ic_menu_save_as_pdf"
           gecko:title="@string/save_as_pdf" />
 
     <item gecko:id="@+id/find_in_page"
           gecko:title="@string/find_in_page" />
 
+    <item gecko:id="@+id/desktop_mode"
+          gecko:title="@string/desktop_mode"
+          gecko:checkable="true" />
+    
     <item gecko:id="@+id/site_settings"
           gecko:icon="@drawable/ic_menu_clear_site_settings"
           gecko:title="@string/site_settings_title" />
 
     <item gecko:id="@+id/addons"
           gecko:title="@string/addons"/>
 
     <item gecko:id="@+id/downloads"
--- a/mobile/android/base/resources/menu-v11/gecko_menu.xml.in
+++ b/mobile/android/base/resources/menu-v11/gecko_menu.xml.in
@@ -28,16 +28,20 @@
 
     <item gecko:id="@+id/save_as_pdf"
           gecko:icon="@drawable/ic_menu_save_as_pdf"
           gecko:title="@string/save_as_pdf" />
 
     <item gecko:id="@+id/find_in_page"
           gecko:title="@string/find_in_page" />
 
+    <item gecko:id="@+id/desktop_mode"
+          gecko:title="@string/desktop_mode"
+          gecko:checkable="true" />
+
     <item gecko:id="@+id/site_settings"
           gecko:icon="@drawable/ic_menu_clear_site_settings"
           gecko:title="@string/site_settings_title" />
 
     <item gecko:id="@+id/addons"
           gecko:title="@string/addons"/>
 
     <item gecko:id="@+id/downloads"
--- a/mobile/android/base/resources/menu-xlarge/gecko_menu.xml.in
+++ b/mobile/android/base/resources/menu-xlarge/gecko_menu.xml.in
@@ -31,16 +31,20 @@
 
     <item gecko:id="@+id/save_as_pdf"
           gecko:icon="@drawable/ic_menu_save_as_pdf"
           gecko:title="@string/save_as_pdf" />
 
     <item gecko:id="@+id/find_in_page"
           gecko:title="@string/find_in_page" />
 
+    <item gecko:id="@+id/desktop_mode"
+          gecko:title="@string/desktop_mode"
+          gecko:checkable="true" />
+    
     <item gecko:id="@+id/site_settings"
           gecko:icon="@drawable/ic_menu_clear_site_settings"
           gecko:title="@string/site_settings_title" />
 
     <item gecko:id="@+id/addons"
           gecko:title="@string/addons"/>
 
     <item gecko:id="@+id/downloads"
--- a/mobile/android/base/resources/menu/gecko_menu.xml.in
+++ b/mobile/android/base/resources/menu/gecko_menu.xml.in
@@ -27,16 +27,20 @@
 
     <item android:id="@+id/save_as_pdf"
           android:icon="@drawable/ic_menu_save_as_pdf"
           android:title="@string/save_as_pdf" />
 
     <item android:id="@+id/find_in_page"
           android:title="@string/find_in_page" />
 
+    <item android:id="@+id/desktop_mode"
+          android:title="@string/desktop_mode"
+          android:checkable="true" />
+
     <item android:id="@+id/site_settings"
           android:title="@string/site_settings_title" />
 
     <item android:id="@+id/addons"
           android:title="@string/addons"/>
 
     <item android:id="@+id/downloads"
           android:title="@string/downloads"/>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -53,16 +53,17 @@
   <string name="history_yesterday_section">&history_yesterday_section;</string>
   <string name="history_week_section">&history_week_section;</string>
   <string name="history_older_section">&history_older_section;</string>
 
   <string name="share">&share;</string>
   <string name="share_title">&share_title;</string>
   <string name="save_as_pdf">&save_as_pdf;</string>
   <string name="find_in_page">&find_in_page;</string>
+  <string name="desktop_mode">&desktop_mode;</string>
 
   <string name="find_text">&find_text;</string>
   <string name="find_prev">&find_prev;</string>
   <string name="find_next">&find_next;</string>
   <string name="find_close">&find_close;</string>
 
   <string name="settings">&settings;</string>
   <string name="settings_title">&settings_title;</string>
--- a/mobile/android/base/tests/MotionEventHelper.java.in
+++ b/mobile/android/base/tests/MotionEventHelper.java.in
@@ -29,25 +29,33 @@ class MotionEventHelper {
         Log.d(LOGTAG, "Triggering down at (" + x + "," + y + ")");
         long downTime = SystemClock.uptimeMillis();
         MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0);
         mInstrumentation.sendPointerSync(event);
         return downTime;
     }
 
     public long move(long downTime, float x, float y) {
+        return move(downTime, SystemClock.uptimeMillis(), x, y);
+    }
+
+    public long move(long downTime, long moveTime, float x, float y) {
         Log.d(LOGTAG, "Triggering move to (" + x + "," + y + ")");
-        MotionEvent event = MotionEvent.obtain(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0);
+        MotionEvent event = MotionEvent.obtain(downTime, moveTime, MotionEvent.ACTION_MOVE, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0);
         mInstrumentation.sendPointerSync(event);
         return downTime;
     }
 
     public long up(long downTime, float x, float y) {
+        return up(downTime, SystemClock.uptimeMillis(), x, y);
+    }
+
+    public long up(long downTime, long upTime, float x, float y) {
         Log.d(LOGTAG, "Triggering up at (" + x + "," + y + ")");
-        MotionEvent event = MotionEvent.obtain(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0);
+        MotionEvent event = MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0);
         mInstrumentation.sendPointerSync(event);
         return -1L;
     }
 
     public Thread dragAsync(final float startX, final float startY, final float endX, final float endY, final long durationMillis) {
         Thread t = new Thread() {
             public void run() {
                 int numEvents = (int)(durationMillis * DRAG_EVENTS_PER_SECOND / 1000);
@@ -80,29 +88,34 @@ class MotionEventHelper {
<