Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 23 Jun 2012 08:35:25 -0400
changeset 106384 87e239ca45c65753eaf4e6c0f6c451cf420bd9f3
parent 106382 879b2a08107a70eb6a37ff8196a67ebf4f346b91 (current diff)
parent 106383 53d0ad70087b0796e89f59bac8ba3b8e5fd8c670 (diff)
child 106385 51bda50648bc21f5bf73fd5cf046bdd860551248
push id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherdermozilla-central@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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 {
         }
     }
 
     public void dragSync(float startX, float startY, float endX, float endY) {
         dragSync(startX, startY, endX, endY, 1000);
     }
 
     public Thread flingAsync(final float startX, final float startY, final float endX, final float endY, final float velocity) {
-        float dx = endX - startX;
-        float dy = endY - startY;
+        // note that the first move after the touch-down is used to get over the panning threshold, and
+        // is basically cancelled out. this means we need to generate (at least) two move events, with
+        // the last move event hitting the target velocity. to do this we just slice the total distance
+        // in half, assuming the first half will get us over the panning threshold and the second half
+        // will trigger the fling.
+        final float dx = (endX - startX) / 2;
+        final float dy = (endY - startY) / 2;
         float distance = FloatMath.sqrt((dx * dx) + (dy * dy));
         final long time = (long)(distance / velocity);
         if (time <= 0) {
             throw new IllegalArgumentException( "Fling parameters require too small a time period" );
         }
         Thread t = new Thread() {
             public void run() {
                 long downTime = down(startX, startY);
-                MotionEvent event = MotionEvent.obtain(downTime, downTime + time, MotionEvent.ACTION_MOVE, endX, endY, 0);
-                mInstrumentation.sendPointerSync(event);
-                downTime = up(downTime, endX, endY);
+                downTime = move(downTime, downTime + time, startX + dx, startY + dy);
+                downTime = move(downTime, downTime + time + time, endX, endY);
+                downTime = up(downTime, downTime + time, endX, endY);
             }
         };
         t.start();
         return t;
     }
 
     public void flingSync(float startX, float startY, float endX, float endY, float velocity) {
         try {
--- a/mobile/android/base/tests/PixelTest.java.in
+++ b/mobile/android/base/tests/PixelTest.java.in
@@ -1,15 +1,15 @@
 #filter substitution
 package @ANDROID_PACKAGE_NAME@.tests;
 
 import @ANDROID_PACKAGE_NAME@.*;
 
 class PixelTest extends BaseTest {
-    private static final long PAINT_CLEAR_DELAY = 500; // milliseconds
+    private static final long PAINT_CLEAR_DELAY = 1000; // milliseconds
 
     protected final PaintedSurface loadAndPaint(String url) {
         Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
         loadUrl(url);
         paintExpecter.blockUntilClear(PAINT_CLEAR_DELAY);
         PaintedSurface p = mDriver.getPaintedSurface();
         if (p == null) {
             mAsserter.ok(p != null, "checking that painted surface loaded", 
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -1,16 +1,16 @@
 [testAwesomebar]
 [testBookmark]
 [testBookmarklets]
 [testLoad]
 [testNewTab]
 [testPanCorrectness]
 # [test_bug720538] # see bug 746876
-# [testFlingCorrectness] # see bug 727351
+[testFlingCorrectness]
 [testOverscroll]
 [testAxisLocking]
 [testAboutPage]
 [testWebContentContextMenu]
 [testPasswordProvider]
 [testPasswordEncrypt]
 [testFormHistory]
 [testBrowserProvider]
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -54,17 +54,17 @@ let AboutReader = {
       { name: gStrings.GetStringFromName("aboutReader.colorSchemeSepia"),
         value: "sepia"}
     ];
 
     let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
     this._setupSegmentedButton("color-scheme-buttons", colorSchemeOptions, colorScheme, this._setColorScheme.bind(this));
     this._setColorScheme(colorScheme);
 
-    let fontTitle = gStrings.GetStringFromName("aboutReader.fontTitle");
+    let fontTitle = gStrings.GetStringFromName("aboutReader.textTitle");
     this._setupStepControl("font-size-control", fontTitle, this._onFontSizeChange.bind(this));
     this._fontSize = 0;