Backout merge, a=backout
authorDavid Mandelin <dmandelin@mozilla.com>
Wed, 29 Dec 2010 17:47:55 -0800
changeset 59732 37068ce988b98c3fbe7196c7e887cc8e21835852
parent 59730 2571397d53be3baa5a2d4b03390d05358bc2b84e (diff)
parent 59731 ed90ba2b89454305ed8099f9a4220dfe9f99396e (current diff)
child 59733 c9682df3daf8f31c3f0d1f8fb4a525d8af9de30b
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersbackout
milestone2.0b9pre
Backout merge, a=backout
js/src/jsscope.h
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -248,24 +248,30 @@ var FullZoom = {
       return;
 
     // Avoid the cps roundtrip and apply the default/global pref.
     if (aURI.spec == "about:blank") {
       this._applyPrefToSetting(undefined, aBrowser);
       return;
     }
 
-    var self = this;
-    Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
-      // Check that we're still where we expect to be in case this took a while.
-      let browser = aBrowser || gBrowser.selectedBrowser;
-      if (aURI.equals(browser.currentURI)) {
-        self._applyPrefToSetting(aResult, browser);
-      }
-    });
+    let browser = aBrowser || gBrowser.selectedBrowser;
+
+    if (Services.contentPrefs.hasCachedPref(aURI, this.name)) {
+      let zoomValue = Services.contentPrefs.getPref(aURI, this.name);
+      this._applyPrefToSetting(zoomValue, browser);
+    } else {
+      var self = this;
+      Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
+        // Check that we're still where we expect to be in case this took a while.
+        if (aURI.equals(browser.currentURI)) {
+          self._applyPrefToSetting(aResult, browser);
+        }
+      });
+    }
   },
 
   // update state of zoom type menu item
 
   updateMenu: function FullZoom_updateMenu() {
     var menuItem = document.getElementById("toggle_zoom");
 
     menuItem.setAttribute("checked", !ZoomManager.useFullZoom);
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -953,18 +953,18 @@ var PlacesStarButton = {
     if (!this._starIcon || (this._uri && gBrowser.currentURI.equals(this._uri))) {
       return;
     }
 
     // Reset tracked values.
     this._uri = gBrowser.currentURI;
     this._itemIds = [];
 
-    // Hide the star while we update its state.
-    this._starIcon.hidden = true;
+    // Ignore clicks on the star while we update its state.
+    this._ignoreClicks = true;
 
     // We can load about:blank before the actual page, but there is no point in handling that page.
     if (this._uri.spec == "about:blank") {
       return;
     }
 
     PlacesUtils.asyncGetBookmarkIds(this._uri, function (aItemIds) {
       this._itemIds = aItemIds;
@@ -975,18 +975,18 @@ var PlacesStarButton = {
         try {
           PlacesUtils.bookmarks.addObserver(this, false);
           this._hasBookmarksObserver = true;
         } catch(ex) {
           Components.utils.reportError("PlacesStarButton failed adding a bookmarks observer: " + ex);
         }
       }
 
-      // Finally show the star.
-      this._starIcon.hidden = false;
+      // Finally re-enable the star.
+      this._ignoreClicks = false;
     }, this);
   },
 
   _updateStateInternal: function PSB__updateStateInternal()
   {
     if (!this._starIcon) {
       return;
     }
@@ -999,17 +999,17 @@ var PlacesStarButton = {
     else if (this._itemIds.length == 0 && starred) {
       this._starIcon.removeAttribute("starred");
       this._starIcon.setAttribute("tooltiptext", this._unstarredTooltip);
     }
   },
 
   onClick: function PSB_onClick(aEvent)
   {
-    if (aEvent.button == 0) {
+    if (aEvent.button == 0 && !this._ignoreClicks) {
       PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0);
     }
     // Don't bubble to the textbox, to avoid unwanted selection of the address.
     aEvent.stopPropagation();
   },
 
   // nsINavBookmarkObserver
   onItemAdded:
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -570,17 +570,16 @@
             <image id="page-report-button"
                    class="urlbar-icon"
                    hidden="true"
                    tooltiptext="&pageReportIcon.tooltip;"
                    onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
 
             <image id="star-button"
                    class="urlbar-icon"
-                   hidden="true"
                    onclick="PlacesStarButton.onClick(event);"/>
             <image id="go-button"
                    class="urlbar-icon"
                    tooltiptext="&goEndCap.tooltip;"
                    onclick="gURLBar.handleCommand(event);"/>
           </hbox>
           <toolbarbutton id="urlbar-go-button"
                          class="chromeclass-toolbar-additional"
--- a/browser/base/content/test/browser_bug432599.js
+++ b/browser/base/content/test/browser_bug432599.js
@@ -56,17 +56,17 @@ function initTest() {
   // First, bookmark the page.
   bookmarkId = add_bookmark(makeURI(testURL), "Bug 432599 Test");
 
   checkBookmarksPanel(invokers[currentInvoker], 1);
 }
 
 function waitForStarChange(aValue, aCallback) {
   let starButton = document.getElementById("star-button");
-  if (starButton.hidden || starButton.hasAttribute("starred") != aValue) {
+  if (PlacesStarButton._ignoreClicks || starButton.hasAttribute("starred") != aValue) {
     info("Waiting for star button change.");
     setTimeout(arguments.callee, 50, aValue, aCallback);
     return;
   }
   aCallback();
 }
 
 let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
--- a/browser/base/content/test/browser_bug559991.js
+++ b/browser/base/content/test/browser_bug559991.js
@@ -13,29 +13,22 @@ function test() {
   };
 
   gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", true);
   gPrefService.setBoolPref("browser.zoom.siteSpecific", true);
 
   let oldAPTS = FullZoom._applyPrefToSetting;
   let uri = "http://example.org/browser/browser/base/content/test/dummy_page.html";
 
-  // ------------------------------------------------------
-  // Test 1 - Zoom should not be called if URIs don't match
-  FullZoom._applyPrefToSetting = function() {
-    ok(false, "This should not be called");
-  };
-  FullZoom.onLocationChange(makeURI(uri), true);
-
   let tab = gBrowser.addTab();
   tab.linkedBrowser.addEventListener("load", function(event) {
     tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
 
     // -------------------------------------------------------------------
-    // Test 2 - Trigger a tab switch that should now update the zoom level
+    // Test - Trigger a tab switch that should update the zoom level
     FullZoom._applyPrefToSetting = function() {
       ok(true, "applyPrefToSetting was called");
       endTest();
     }
     gBrowser.selectedTab = tab;
 
   }, true); 
   tab.linkedBrowser.loadURI(uri);
--- a/content/smil/test/db_smilCSSFromBy.js
+++ b/content/smil/test/db_smilCSSFromBy.js
@@ -80,19 +80,16 @@ var _fromByTestLists =
     new AnimTestcaseFromBy("0.8", "-1.4", { midComp: "0.1", toComp: "0"},
                            "opacities with abs val >1 get clamped too early"),
     new AnimTestcaseFromBy("1.2", "-0.6", { midComp: "0.9", toComp: "0.6"},
                            "opacities with abs val >1 get clamped too early"),
   ],
   paint: [
     // The "none" keyword & URI values aren't addiditve, so the animations in
     // these testcases are expected to have no effect.
-    // XXXdholbert Of course, we don't support animation between URI values yet
-    // (bug 520487), so the testcases that use URIs currently have no effect
-    // for that reason, too.
     new AnimTestcaseFromBy("none", "none",  { noEffect: 1 }),
     new AnimTestcaseFromBy("url(#gradA)", "url(#gradB)", { noEffect: 1 }),
     new AnimTestcaseFromBy("url(#gradA)", "url(#gradB) red", { noEffect: 1 }),
     new AnimTestcaseFromBy("url(#gradA)", "none", { noEffect: 1 }),
     new AnimTestcaseFromBy("red", "url(#gradA)", { noEffect: 1 }),
   ],
   URIsAndNone: [
     // No need to specify { noEffect: 1 }, since plain URI-valued properties
--- a/dom/interfaces/base/nsIContentPrefService.idl
+++ b/dom/interfaces/base/nsIContentPrefService.idl
@@ -125,17 +125,17 @@ interface nsIContentPrefService : nsISup
    *                       from which the hostname will be used, a string
    *                       (typically in the format of a hostname), or null
    *                       to check for the global pref (applies to all sites)
    * @param    aName       the name of the pref to check for
    * @throws   NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
    * @throws   NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
    */
   boolean hasPref(in nsIVariant aGroup, in AString aName);
-  
+
   /**
    * Remove a pref.
    *
    * @param    aGroup      the group for which to remove the pref, as an nsIURI
    *                       from which the hostname will be used, a string
    *                       (typically in the format of a hostname), or null
    *                       to remove the global pref (applies to all sites) 
    * @param    aName       the name of the pref to remove
@@ -212,12 +212,29 @@ interface nsIContentPrefService : nsISup
    * specific or for which there is not yet a generic method, although generic
    * functionality useful to multiple callers should generally be added to this
    * unfrozen interface.  Also useful for testing the database creation
    * and migration code.
    */
   readonly attribute mozIStorageConnection DBConnection;
 };
 
+[scriptable, uuid(126f07cb-edfe-497e-87dd-ba906506b287)]
+interface nsIContentPrefService_MOZILLA_2_0 : nsIContentPrefService
+{
+  /**
+   * Check whether or not the value of a pref (or its non-existance) is cached.
+   *
+   * @param    aGroup      the group for which to check for the pref, as an nsIURI
+   *                       from which the hostname will be used, a string
+   *                       (typically in the format of a hostname), or null
+   *                       to check for the global pref (applies to all sites)
+   * @param    aName       the name of the pref to check for
+   * @throws   NS_ERROR_ILLEGAL_VALUE if aGroup is not a string, nsIURI, or null
+   * @throws   NS_ERROR_ILLEGAL_VALUE if aName is null or an empty string
+   */
+  boolean hasCachedPref(in nsIVariant aGroup, in AString aName);
+};
+
 %{C++
 // The contractID for the generic implementation built in to xpcom.
 #define NS_CONTENT_PREF_SERVICE_CONTRACTID "@mozilla.org/content-pref/service;1"
 %}
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -9,16 +9,20 @@
     <uses-sdk android:minSdkVersion="5"
               android:targetSdkVersion="5"/>
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
 
+    <uses-feature android:name="android.hardware.location" android:required="false"/>
+    <uses-feature android:name="android.hardware.location.gps" android:required="false"/>
+    <uses-feature android:name="android.hardware.touchscreen"/>
+
     <application android:label="@MOZ_APP_DISPLAYNAME@"
 		 android:icon="@drawable/icon"
 		 android:debuggable="true">
         <activity android:name="App"
                   android:label="@MOZ_APP_DISPLAYNAME@"
                   android:configChanges="keyboard|keyboardHidden|mcc|mnc"
                   android:windowSoftInputMode="stateUnspecified|adjustResize"
                   android:launchMode="singleTask"
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -64,17 +64,16 @@ abstract public class GeckoApp
 {
     public static final String ACTION_ALERT_CLICK = "org.mozilla.gecko.ACTION_ALERT_CLICK";
     public static final String ACTION_ALERT_CLEAR = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
 
     public static FrameLayout mainLayout;
     public static GeckoSurfaceView surfaceView;
     public static GeckoApp mAppContext;
     public static boolean mFullscreen = false;
-    ProgressDialog mProgressDialog;
 
     enum LaunchState {PreLaunch, Launching, WaitButton,
                       Launched, GeckoRunning, GeckoExiting};
     private static LaunchState sLaunchState = LaunchState.PreLaunch;
 
     
     static boolean checkLaunchState(LaunchState checkState) {
         synchronized(sLaunchState) {
@@ -130,21 +129,16 @@ abstract public class GeckoApp
             String msg = ie.getMessage();
             if (msg.equalsIgnoreCase("No space left on device"))
                 showErrorDialog(getString(R.string.no_space_to_start_error));
             else
                 showErrorDialog(getString(R.string.error_loading_file));
             return false;
         }
 
-        mProgressDialog = 
-            ProgressDialog.show(GeckoApp.this, "",
-                                getString(R.string.splash_screen_label),
-                                true);
-
         // and then fire us up
         if (i == null)
             i = getIntent();
         String env = i.getStringExtra("env0");
         GeckoAppShell.runGecko(getApplication().getPackageResourcePath(),
                                i.getStringExtra("args"),
                                i.getDataString());
         return true;
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -59,17 +59,18 @@ import android.location.*;
 import android.util.*;
 import android.net.Uri;
 
 class GeckoAppShell
 {
     // static members only
     private GeckoAppShell() { }
 
-    static private GeckoEvent gPendingResize = null;
+    static private LinkedList<GeckoEvent> gPendingEvents =
+        new LinkedList<GeckoEvent>();
 
     static private boolean gRestartScheduled = false;
 
     static private final Timer mIMETimer = new Timer();
     static private final HashMap<Integer, AlertNotification>
          mAlertNotifications = new HashMap<Integer, AlertNotification>();
 
     static private final int NOTIFY_IME_RESETINPUTSTATE = 0;
@@ -138,26 +139,30 @@ class GeckoAppShell
         if (url != null)
             combinedArgs += " " + url;
         // and go
         GeckoAppShell.nativeRun(combinedArgs);
     }
 
     private static GeckoEvent mLastDrawEvent;
 
+    private static void sendPendingEventsToGecko() {
+        try {
+            while (!gPendingEvents.isEmpty()) {
+                GeckoEvent e = gPendingEvents.removeFirst();
+                notifyGeckoOfEvent(e);
+            }
+        } catch (NoSuchElementException e) {}
+    }
+ 
     public static void sendEventToGecko(GeckoEvent e) {
         if (GeckoApp.checkLaunchState(GeckoApp.LaunchState.GeckoRunning)) {
-            if (gPendingResize != null) {
-                notifyGeckoOfEvent(gPendingResize);
-                gPendingResize = null;
-            }
             notifyGeckoOfEvent(e);
         } else {
-            if (e.mType == GeckoEvent.SIZE_CHANGED)
-                gPendingResize = e;
+            gPendingEvents.addLast(e);
         }
     }
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
@@ -330,20 +335,17 @@ class GeckoAppShell
         } catch (InterruptedException e) {
         }
     }
 
     static void onAppShellReady()
     {
         // mLaunchState can only be Launched at this point
         GeckoApp.setLaunchState(GeckoApp.LaunchState.GeckoRunning);
-        if (gPendingResize != null) {
-            notifyGeckoOfEvent(gPendingResize);
-            gPendingResize = null;
-        }
+        sendPendingEventsToGecko();
     }
 
     static void onXreExit() {
         // mLaunchState can only be Launched or GeckoRunning at this point
         GeckoApp.setLaunchState(GeckoApp.LaunchState.GeckoExiting);
         Log.i("GeckoAppJava", "XRE exited");
         if (gRestartScheduled) {
             GeckoApp.mAppContext.doRestart();
@@ -628,20 +630,17 @@ class GeckoAppShell
     }
 
     public static void showInputMethodPicker() {
         InputMethodManager imm = (InputMethodManager) GeckoApp.surfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showInputMethodPicker();       
     }
 
     public static void hideProgressDialog() {
-        if (GeckoApp.mAppContext.mProgressDialog != null) {
-            GeckoApp.mAppContext.mProgressDialog.dismiss();
-            GeckoApp.mAppContext.mProgressDialog = null;
-        }
+        GeckoApp.surfaceView.mShowingSplashScreen = false;
     }
 
     public static void setKeepScreenOn(final boolean on) {
         GeckoApp.mAppContext.runOnUiThread(new Runnable() {
             public void run() {
                 GeckoApp.surfaceView.setKeepScreenOn(on);
             }
         });
--- a/embedding/android/GeckoSurfaceView.java
+++ b/embedding/android/GeckoSurfaceView.java
@@ -51,16 +51,18 @@ import android.text.*;
 import android.text.method.*;
 import android.view.*;
 import android.view.inputmethod.*;
 import android.content.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
+import android.graphics.drawable.*;
+import android.content.res.*;
 
 import android.util.*;
 
 /*
  * GeckoSurfaceView implements a GL surface view,
  * similar to GLSurfaceView.  However, since we
  * already have a thread for Gecko, we don't really want
  * a separate renderer thread that GLSurfaceView provides.
@@ -90,21 +92,47 @@ class GeckoSurfaceView
         mIMETypeHint = "";
         mIMEActionHint = "";
     }
 
     protected void finalize() throws Throwable {
         super.finalize();
     }
 
+    void drawSplashScreen(SurfaceHolder holder, int width, int height) {
+        Canvas c = holder.lockCanvas();
+        if (c == null) {
+            Log.i("GeckoSurfaceView", "canvas is null");
+            return;
+        }
+        Resources res = getResources();
+        c.drawColor(res.getColor(R.color.splash_background));
+        Drawable drawable = res.getDrawable(R.drawable.splash);
+        int w = drawable.getIntrinsicWidth();
+        int h = drawable.getIntrinsicHeight();
+        int x = (width - w)/2;
+        int y = (height - h)/2;
+        drawable.setBounds(x, y, x + w, y + h);
+        drawable.draw(c);
+        Paint p = new Paint();
+        p.setTextAlign(Paint.Align.CENTER);
+        p.setTextSize(32f);
+        p.setAntiAlias(true);
+        p.setColor(res.getColor(R.color.splash_font));
+        c.drawText(res.getString(R.string.splash_screen_label), width/2, y + h + 32, p);
+        holder.unlockCanvasAndPost(c);
+    }
+
     /*
      * Called on main thread
      */
 
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        if (mShowingSplashScreen)
+            drawSplashScreen(holder, width, height);
         mSurfaceLock.lock();
 
         try {
             if (mInDrawing) {
                 Log.w("GeckoAppJava", "surfaceChanged while mInDrawing is true!");
             }
 
             if (width == 0 || height == 0)
@@ -127,17 +155,17 @@ class GeckoSurfaceView
 
             GeckoEvent e = new GeckoEvent(GeckoEvent.SIZE_CHANGED, width, height, -1, -1);
             GeckoAppShell.sendEventToGecko(e);
 
             if (mSoftwareBuffer != null)
                 GeckoAppShell.scheduleRedraw();
 
             if (!doSyncDraw) {
-                if (mDrawMode == DRAW_GLES_2)
+                if (mDrawMode == DRAW_GLES_2 || mShowingSplashScreen)
                     return;
                 Canvas c = holder.lockCanvas();
                 c.drawARGB(255, 255, 255, 255);
                 holder.unlockCanvasAndPost(c);
                 return;
             }
         } finally {
             mSurfaceLock.unlock();
@@ -498,16 +526,18 @@ class GeckoSurfaceView
     boolean mInDrawing;
 
     // Are we waiting for a buffer to draw in surfaceChanged?
     boolean mSyncDraw;
 
     // True if gecko requests a buffer
     int mDrawMode;
 
+    static boolean mShowingSplashScreen = true;
+
     // let's not change stuff around while we're in the middle of
     // starting drawing, ending drawing, or changing surface
     // characteristics
     ReentrantLock mSurfaceLock;
 
     // Surface format, from surfaceChanged.  Largely
     // useless.
     int mFormat;
--- a/embedding/android/Makefile.in
+++ b/embedding/android/Makefile.in
@@ -97,16 +97,20 @@ ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
 endif
 
 RES_LAYOUT = \
   res/layout/notification_progress.xml \
   res/layout/notification_progress_text.xml \
   $(NULL)
 
+RES_VALUES = res/values/colors.xml
+
+AB_rCD = $(shell echo $(AB_CD) | sed -e s/-/-r/)
+
 JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar
 
 DEFAULT_BRANDPATH = $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales/en-US/brand.dtd
 DEFAULT_STRINGSPATH = locales/en-US/android_strings.dtd
 LOCALIZED_BRANDPATH = $(DEPTH)/dist/bin/chrome/$(AB_CD)/locale/branding/brand.dtd
 LOCALIZED_STRINGSPATH = $(DEPTH)/dist/bin/chrome/android-res/res/values-$(AB_CD)/android_strings.dtd
 
 ifdef MOZ_CRASHREPORTER
@@ -117,17 +121,17 @@ endif
 
 MOZ_ANDROID_DRAWABLES += embedding/android/resources/drawable/desktop_notification.png
 
 MOZ_ANDROID_DRAWABLES += $(shell if test -e $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/android-resources.mn; then cat $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/android-resources.mn | tr '\n' ' ';  fi)
 
 include $(topsrcdir)/config/rules.mk
 
 ifneq ($(AB_CD),en-US)
-LOCALIZED_STRINGS_XML = res/values-$(AB_CD)/strings.xml
+LOCALIZED_STRINGS_XML = res/values-$(AB_rCD)/strings.xml
 endif
 
 # Override the Java settings with some specific android settings
 include $(topsrcdir)/config/android-common.mk
 
 # Note that we're going to set up a dependency directly between embed_android.dex and the java files
 # Instead of on the .class files, since more than one .class file might be produced per .java file
 classes.dex: $(JAVAFILES) $(PROCESSEDJAVAFILES) R.java
@@ -152,32 +156,36 @@ RES_DRAWABLE = $(addprefix res/drawable/
 $(RES_DRAWABLE): $(addprefix $(topsrcdir)/,$(MOZ_ANDROID_DRAWABLES))
 	$(NSINSTALL) -D res/drawable
 	$(NSINSTALL) $^ res/drawable/
 
 $(RES_LAYOUT): $(subst res/,$(srcdir)/resources/,$(RES_LAYOUT))
 	$(NSINSTALL) -D res/layout
 	$(NSINSTALL) $(srcdir)/resources/layout/* res/layout/
 
-R.java: $(MOZ_APP_ICON) $(RES_LAYOUT) $(RES_DRAWABLE) res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml
+$(RES_VALUES): $(subst res/,$(srcdir)/resources/,$(RES_VALUES))
+	$(NSINSTALL) -D res/values
+	$(NSINSTALL) $(srcdir)/resources/values/* res/values/
+
+R.java: $(MOZ_APP_ICON) $(RES_LAYOUT) $(RES_DRAWABLE) $(RES_VALUES) res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
 
-gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_LAYOUT) $(RES_DRAWABLE) res/values/strings.xml FORCE
+gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_LAYOUT) $(RES_DRAWABLE) $(RES_VALUES) res/values/strings.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
 
 res/values/strings.xml: $(DEFAULT_BRANDPATH) $(DEFAULT_STRINGSPATH)
 	mkdir -p res/values
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) \
 	  -DBRANDPATH="$(DEFAULT_BRANDPATH)" \
 	  -DSTRINGSPATH="$(DEFAULT_STRINGSPATH)" \
 	  $(srcdir)/strings.xml.in \
 	  > $@
 
-res/values-$(AB_CD)/strings.xml: $(LOCALIZED_BRANDPATH) $(LOCALIZED_STRINGSPATH)
-	mkdir -p res/values-$(AB_CD)
+res/values-$(AB_rCD)/strings.xml: $(LOCALIZED_BRANDPATH) $(LOCALIZED_STRINGSPATH)
+	mkdir -p res/values-$(AB_rCD)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) \
 	  -DBRANDPATH="$(call core_abspath,$(LOCALIZED_BRANDPATH))" \
 	  -DSTRINGSPATH="$(call core_abspath,$(LOCALIZED_STRINGSPATH))" \
 	  $(srcdir)/strings.xml.in \
 	  > $@
 
 chrome:: $(LOCALIZED_STRINGS_XML)
 
--- a/embedding/android/locales/en-US/android_strings.dtd
+++ b/embedding/android/locales/en-US/android_strings.dtd
@@ -1,9 +1,9 @@
-<!ENTITY  splash_screen_label "&brandShortName; is loading">
+<!ENTITY  splash_screen_label "loading">
 <!ENTITY  incompatable_cpu_error "This device does not meet the minimum system requirements for &brandShortName;.">
 <!ENTITY  no_space_to_start_error "There is not enough space available for &brandShortName; to start.">
 <!ENTITY  error_loading_file "An error occurred when trying to load files required to run &brandShortName;">
 
 <!ENTITY  crash_reporter_title "&brandShortName; Crash Reporter">
 <!ENTITY  crash_message "&brandShortName; has crashed. Your tabs should be listed on the &brandShortName; Start page when you restart.">
 <!ENTITY  crash_help_message "Please help us fix this problem!">
 <!ENTITY  crash_send_report_message "Send Mozilla a crash report">
new file mode 100644
--- /dev/null
+++ b/embedding/android/resources/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <color name="splash_background">#3a3a3a</color>
+  <color name="splash_font">#ffffff</color>
+</resources>
+
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -190,16 +190,23 @@ public:
 
   /**
    * Sets a size that the image is expected to be rendered at.
    * This is a hint for image backends to optimize scaling.
    * Default implementation in this class is to ignore the hint.
    */
   virtual void SetScaleHint(const gfxIntSize& /* aScaleHint */) { }
 
+  /**
+   * Get the layer manager type this image container was created with,
+   * presumably its users might want to do something special if types do not
+   * match.
+   */
+  virtual LayerManager::LayersBackend GetBackendType() = 0;
+
 protected:
   LayerManager* mManager;
 
   ImageContainer(LayerManager* aManager) : mManager(aManager) {}
 };
 
 /**
  * A Layer which renders an Image.
--- a/gfx/layers/basic/BasicImages.cpp
+++ b/gfx/layers/basic/BasicImages.cpp
@@ -286,30 +286,31 @@ BasicPlanarYCbCrImage::GetAsSurface()
  * Our image container is very simple. It's really just a factory
  * for the image objects. We use a Monitor to synchronize access to
  * mImage.
  */
 class BasicImageContainer : public ImageContainer {
 public:
   typedef gfxASurface::gfxImageFormat gfxImageFormat;
 
-  BasicImageContainer(BasicLayerManager* aManager) :
-    ImageContainer(aManager), mMonitor("BasicImageContainer"),
+  BasicImageContainer() :
+    ImageContainer(nsnull), mMonitor("BasicImageContainer"),
     mScaleHint(-1, -1),
     mOffscreenFormat(gfxASurface::ImageFormatUnknown)
   {}
   virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
                                               PRUint32 aNumFormats);
   virtual void SetCurrentImage(Image* aImage);
   virtual already_AddRefed<Image> GetCurrentImage();
   virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
   virtual gfxIntSize GetCurrentSize();
   virtual PRBool SetLayerManager(LayerManager *aManager);
   virtual void SetScaleHint(const gfxIntSize& aScaleHint);
   void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
+  virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_BASIC; }
 
 protected:
   Monitor mMonitor;
   nsRefPtr<Image> mImage;
   gfxIntSize mScaleHint;
   gfxImageFormat mOffscreenFormat;
 };
 
@@ -395,24 +396,22 @@ PRBool
 BasicImageContainer::SetLayerManager(LayerManager *aManager)
 {
   if (aManager &&
       aManager->GetBackendType() != LayerManager::LAYERS_BASIC)
   {
     return PR_FALSE;
   }
 
-  // for basic layers, we can just swap; no magic needed.
-  mManager = aManager;
   return PR_TRUE;
 }
 
 already_AddRefed<ImageContainer>
 BasicLayerManager::CreateImageContainer()
 {
-  nsRefPtr<ImageContainer> container = new BasicImageContainer(this);
+  nsRefPtr<ImageContainer> container = new BasicImageContainer();
   static_cast<BasicImageContainer*>(container.get())->
     SetOffscreenFormat(gfxPlatform::GetPlatform()->GetOffscreenFormat());
   return container.forget();
 }
 
 }
 }
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -86,19 +86,19 @@ SurfaceToTexture(ID3D10Device *aDevice,
   data.pSysMem = imageSurface->Data();
   data.SysMemPitch = imageSurface->Stride();
 
   nsRefPtr<ID3D10Texture2D> texture;
   aDevice->CreateTexture2D(&desc, &data, getter_AddRefs(texture));
   return texture.forget();
 }
 
-ImageContainerD3D10::ImageContainerD3D10(LayerManagerD3D10 *aManager)
-  : ImageContainer(aManager)
-  , mDevice(aManager->device())
+ImageContainerD3D10::ImageContainerD3D10(ID3D10Device1 *aDevice)
+  : ImageContainer(nsnull)
+  , mDevice(aDevice)
   , mActiveImageLock("mozilla.layers.ImageContainerD3D10.mActiveImageLock")
 {
 }
 
 already_AddRefed<Image>
 ImageContainerD3D10::CreateImage(const Image::Format *aFormats,
                                  PRUint32 aNumFormats)
 {
@@ -177,17 +177,16 @@ ImageContainerD3D10::GetCurrentSize()
 
   return gfxIntSize(0,0);
 }
 
 PRBool
 ImageContainerD3D10::SetLayerManager(LayerManager *aManager)
 {
   if (aManager->GetBackendType() == LayerManager::LAYERS_D3D10) {
-    mManager = aManager;
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 Layer*
 ImageLayerD3D10::GetLayer()
 {
@@ -202,36 +201,39 @@ ImageLayerD3D10::RenderLayer()
   }
 
   nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
 
   SetEffectTransformAndOpacity();
 
   ID3D10EffectTechnique *technique;
 
-  if (GetContainer()->Manager() != Manager()) {
-    GetContainer()->SetLayerManager(Manager());
-  }
-
-  if (GetContainer()->Manager() != Manager() ||
+  if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D10 ||
       image->GetFormat() == Image::CAIRO_SURFACE)
   {
     gfxIntSize size;
     bool hasAlpha;
     nsRefPtr<ID3D10ShaderResourceView> srView;
 
-    if (GetContainer()->Manager() != Manager()) {
+    if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D10)
+    {
       nsRefPtr<gfxASurface> surf = GetContainer()->GetCurrentAsSurface(&size);
       
       nsRefPtr<ID3D10Texture2D> texture = SurfaceToTexture(device(), surf, size);
       
       hasAlpha = surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
       
       device()->CreateShaderResourceView(texture, NULL, getter_AddRefs(srView));
     } else {
+      ImageContainerD3D10 *container =
+        static_cast<ImageContainerD3D10*>(GetContainer());
+      if (container->device() != device()) {
+        container->SetDevice(device());
+      }
+
       // image->GetFormat() == Image::CAIRO_SURFACE
       CairoImageD3D10 *cairoImage =
         static_cast<CairoImageD3D10*>(image.get());
       srView = cairoImage->mSRView;
       hasAlpha = cairoImage->mHasAlpha;
       size = cairoImage->mSize;
     }
 
--- a/gfx/layers/d3d10/ImageLayerD3D10.h
+++ b/gfx/layers/d3d10/ImageLayerD3D10.h
@@ -44,32 +44,37 @@
 #include "mozilla/Mutex.h"
 
 namespace mozilla {
 namespace layers {
 
 class THEBES_API ImageContainerD3D10 : public ImageContainer
 {
 public:
-  ImageContainerD3D10(LayerManagerD3D10 *aManager);
+  ImageContainerD3D10(ID3D10Device1 *aDevice);
   virtual ~ImageContainerD3D10() {}
 
   virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
                                               PRUint32 aNumFormats);
 
   virtual void SetCurrentImage(Image* aImage);
 
   virtual already_AddRefed<Image> GetCurrentImage();
 
   virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
 
   virtual gfxIntSize GetCurrentSize();
 
   virtual PRBool SetLayerManager(LayerManager *aManager);
 
+  virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_D3D10; }
+
+  ID3D10Device1 *device() { return mDevice; }
+  void SetDevice(ID3D10Device1 *aDevice) { mDevice = aDevice; }
+
 private:
   typedef mozilla::Mutex Mutex;
 
   nsRefPtr<Image> mActiveImage;
   nsRefPtr<ID3D10Device1> mDevice;
 
   Mutex mActiveImageLock;
 };
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -284,17 +284,17 @@ LayerManagerD3D10::CreateCanvasLayer()
 {
   nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this);
   return layer.forget();
 }
 
 already_AddRefed<ImageContainer>
 LayerManagerD3D10::CreateImageContainer()
 {
-  nsRefPtr<ImageContainer> layer = new ImageContainerD3D10(this);
+  nsRefPtr<ImageContainer> layer = new ImageContainerD3D10(mDevice);
   return layer.forget();
 }
 
 static void ReleaseTexture(void *texture)
 {
   static_cast<ID3D10Texture2D*>(texture)->Release();
 }
 
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -245,26 +245,34 @@ CanvasLayerD3D9::RenderLayer()
   }
 
   device()->SetVertexShaderConstantF(CBvLayerQuad, quad, 1);
 
   SetShaderTransformAndOpacity();
 
   mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
 
+  if (mFilter == gfxPattern::FILTER_NEAREST) {
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+  }
   if (!mDataIsPremultiplied) {
     device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
     device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   }
   device()->SetTexture(0, mTexture);
   device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   if (!mDataIsPremultiplied) {
     device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
     device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
   }
+  if (mFilter == gfxPattern::FILTER_NEAREST) {
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+  }
 }
 
 void
 CanvasLayerD3D9::CleanResources()
 {
   if (mD3DManager->deviceManager()->HasDynamicTextures()) {
     // In this case we have a texture in POOL_DEFAULT
     mTexture = nsnull;
--- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -431,16 +431,22 @@ DeviceManagerD3D9::SetupRenderState()
   mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
   mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
   mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
   mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
   mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
   mDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
+  mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+  mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+  mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+  mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+  mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+  mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
   mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
   mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
   mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
   mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
   mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
 }
 
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -123,34 +123,35 @@ SurfaceToTexture(IDirect3DDevice9 *aDevi
     }
 
     texture->UnlockRect(0);
   }
 
   return texture.forget();
 }
 
-ImageContainerD3D9::ImageContainerD3D9(LayerManagerD3D9 *aManager)
-  : ImageContainer(aManager)
+ImageContainerD3D9::ImageContainerD3D9(IDirect3DDevice9 *aDevice)
+  : ImageContainer(nsnull)
+  , mDevice(aDevice)
   , mActiveImageLock("mozilla.layers.ImageContainerD3D9.mActiveImageLock")
 {
 }
 
 already_AddRefed<Image>
 ImageContainerD3D9::CreateImage(const Image::Format *aFormats,
                                PRUint32 aNumFormats)
 {
   if (!aNumFormats) {
     return nsnull;
   }
   nsRefPtr<Image> img;
   if (aFormats[0] == Image::PLANAR_YCBCR) {
     img = new PlanarYCbCrImageD3D9();
   } else if (aFormats[0] == Image::CAIRO_SURFACE) {
-    img = new CairoImageD3D9(static_cast<LayerManagerD3D9*>(mManager)->device());
+    img = new CairoImageD3D9(mDevice);
   }
   return img.forget();
 }
 
 void
 ImageContainerD3D9::SetCurrentImage(Image *aImage)
 {
   MutexAutoLock lock(mActiveImageLock);
@@ -213,17 +214,16 @@ ImageContainerD3D9::GetCurrentSize()
 
   return gfxIntSize(0,0);
 }
 
 PRBool
 ImageContainerD3D9::SetLayerManager(LayerManager *aManager)
 {
   if (aManager->GetBackendType() == LayerManager::LAYERS_D3D9) {
-    mManager = aManager;
     return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
 Layer*
 ImageLayerD3D9::GetLayer()
@@ -234,24 +234,21 @@ ImageLayerD3D9::GetLayer()
 void
 ImageLayerD3D9::RenderLayer()
 {
   if (!GetContainer()) {
     return;
   }
 
   nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
-
-  if (Manager() != GetContainer()->Manager()) {
-    GetContainer()->SetLayerManager(Manager());
-  }
   
   SetShaderTransformAndOpacity();
 
-  if (Manager() != GetContainer()->Manager()) {
+  if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D9)
+  {
     gfxIntSize size;
     nsRefPtr<gfxASurface> surface =
       GetContainer()->GetCurrentAsSurface(&size);
     nsRefPtr<IDirect3DTexture9> texture =
       SurfaceToTexture(device(), surface, size);
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
@@ -311,31 +308,35 @@ ImageLayerD3D9::RenderLayer()
 
         nsRefPtr<IDirect3DSurface9> renderTarget;
         device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
         mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width,
                                                         (unsigned int)yuvImage->mSize.height, (HANDLE)(yuvImage->mYTexture), (HANDLE)(renderTarget));
       }
     }
 
+    // Linear scaling is default here, adhering to mFilter is difficult since
+    // presumably even with point filtering we'll still want chroma upsampling
+    // to be linear. In the current approach we can't.
     device()->SetTexture(0, yuvImage->mYTexture);
-    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
-    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(1, yuvImage->mCbTexture);
-    device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
-    device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(2, yuvImage->mCrTexture);
-    device()->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
-    device()->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
 
     device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 
   } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
     CairoImageD3D9 *cairoImage =
       static_cast<CairoImageD3D9*>(image.get());
+    ImageContainerD3D9 *container =
+      static_cast<ImageContainerD3D9*>(GetContainer());
+
+    if (container->device() != device()) {
+      // Ensure future images get created with the right device.
+      container->SetDevice(device());
+    }
 
     if (cairoImage->device() != device()) {
       cairoImage->SetDevice(device());
     }
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
                                                           0,
@@ -344,18 +345,26 @@ ImageLayerD3D9::RenderLayer()
                                        1);
 
     if (cairoImage->HasAlpha()) {
       mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
     } else {
       mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
     }
 
+    if (mFilter == gfxPattern::FILTER_NEAREST) {
+      device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+      device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    }
     device()->SetTexture(0, cairoImage->GetOrCreateTexture());
     device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+    if (mFilter == gfxPattern::FILTER_NEAREST) {
+      device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+      device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    }
   }
 }
 
 PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9()
   : PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
   , mHasData(PR_FALSE)
 {
 }
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -44,37 +44,44 @@
 #include "mozilla/Mutex.h"
 
 namespace mozilla {
 namespace layers {
 
 class THEBES_API ImageContainerD3D9 : public ImageContainer
 {
 public:
-  ImageContainerD3D9(LayerManagerD3D9 *aManager);
+  ImageContainerD3D9(IDirect3DDevice9 *aDevice);
   virtual ~ImageContainerD3D9() {}
 
   virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
                                               PRUint32 aNumFormats);
 
   virtual void SetCurrentImage(Image* aImage);
 
   virtual already_AddRefed<Image> GetCurrentImage();
 
   virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
 
   virtual gfxIntSize GetCurrentSize();
 
   virtual PRBool SetLayerManager(LayerManager *aManager);
 
+  virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_D3D9; }
+
+  IDirect3DDevice9 *device() { return mDevice; }
+  void SetDevice(IDirect3DDevice9 *aDevice) { mDevice = aDevice; }
+
 private:
   typedef mozilla::Mutex Mutex;
 
   nsRefPtr<Image> mActiveImage;
 
+  nsRefPtr<IDirect3DDevice9> mDevice;
+
   Mutex mActiveImageLock;
 };
 
 class THEBES_API ImageLayerD3D9 : public ImageLayer,
                                   public LayerD3D9
 {
 public:
   ImageLayerD3D9(LayerManagerD3D9 *aManager)
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -201,17 +201,17 @@ LayerManagerD3D9::CreateCanvasLayer()
 {
   nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this);
   return layer.forget();
 }
 
 already_AddRefed<ImageContainer>
 LayerManagerD3D9::CreateImageContainer()
 {
-  nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this);
+  nsRefPtr<ImageContainer> container = new ImageContainerD3D9(device());
   return container.forget();
 }
 
 cairo_user_data_key_t gKeyD3D9Texture;
 
 void ReleaseTexture(void *texture)
 {
   static_cast<IDirect3DTexture9*>(texture)->Release();
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -151,16 +151,18 @@ public:
   virtual already_AddRefed<Image> GetCurrentImage();
 
   virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
 
   virtual gfxIntSize GetCurrentSize();
 
   virtual PRBool SetLayerManager(LayerManager *aManager);
 
+  virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_OPENGL; }
+
 private:
   typedef mozilla::Mutex Mutex;
 
   nsRefPtr<RecycleBin> mRecycleBin;
 
   // This protects mActiveImage
   Mutex mActiveImageLock;
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -744,16 +744,20 @@ Invoke(JSContext *cx, const CallArgs &ar
 }
 
 bool
 InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &thisv, uintN argc)
 {
 #ifdef JS_TRACER
     if (TRACE_RECORDER(cx))
         AbortRecording(cx, "attempt to reenter VM while recording");
+#ifdef JS_METHODJIT
+    if (TRACE_PROFILER(cx))
+        AbortProfiling(cx);
+#endif
     LeaveTrace(cx);
 #endif
 
     /* Always push arguments, regardless of optimized/normal invoke. */
     StackSpace &stack = cx->stack();
     if (!stack.pushInvokeArgs(cx, argc, &args_))
         return false;
 
@@ -2332,21 +2336,31 @@ Interpret(JSContext *cx, JSStackFrame *e
 # define END_VARLEN_CASE    goto advance_pc;
 # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
 # define END_EMPTY_CASES    goto advance_pc_by_one;
 
 #endif /* !JS_THREADED_INTERP */
 
     /* Check for too deep of a native thread stack. */
 #ifdef JS_TRACER
+#ifdef JS_METHODJIT
+    JS_CHECK_RECURSION(cx, do {
+            if (TRACE_RECORDER(cx))
+                AbortRecording(cx, "too much recursion");
+            if (TRACE_PROFILER(cx))
+                AbortProfiling(cx);
+            return JS_FALSE;
+        } while (0););
+#else
     JS_CHECK_RECURSION(cx, do {
             if (TRACE_RECORDER(cx))
                 AbortRecording(cx, "too much recursion");
             return JS_FALSE;
         } while (0););
+#endif
 #else
     JS_CHECK_RECURSION(cx, return JS_FALSE);
 #endif
 
 #define LOAD_ATOM(PCOFF, atom)                                                \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT(regs.fp->hasImacropc()                                      \
                   ? atoms == COMMON_ATOMS_START(&rt->atomState) &&            \
@@ -2399,16 +2413,17 @@ Interpret(JSContext *cx, JSStackFrame *e
     JS_END_MACRO
 
 #define MONITOR_BRANCH()                                                      \
     JS_BEGIN_MACRO                                                            \
         if (TRACING_ENABLED(cx)) {                                            \
             MonitorResult r = MonitorLoopEdge(cx, inlineCallCount);           \
             if (r == MONITOR_RECORDING) {                                     \
                 JS_ASSERT(TRACE_RECORDER(cx));                                \
+                JS_ASSERT(!TRACE_PROFILER(cx));                               \
                 MONITOR_BRANCH_TRACEVIS;                                      \
                 ENABLE_INTERRUPTS();                                          \
                 CLEAR_LEAVE_ON_TRACE_POINT();                                 \
             }                                                                 \
             RESTORE_INTERP_VARS();                                            \
             JS_ASSERT_IF(cx->throwing, r == MONITOR_ERROR);                   \
             if (r == MONITOR_ERROR)                                           \
                 goto error;                                                   \
@@ -2548,16 +2563,20 @@ Interpret(JSContext *cx, JSStackFrame *e
      */
     if (interpMode == JSINTERP_RECORD) {
         JS_ASSERT(TRACE_RECORDER(cx));
         ENABLE_INTERRUPTS();
     } else if (interpMode == JSINTERP_PROFILE) {
         ENABLE_INTERRUPTS();
     } else if (TRACE_RECORDER(cx)) {
         AbortRecording(cx, "attempt to reenter interpreter while recording");
+#ifdef JS_METHODJIT
+    } else if (TRACE_PROFILER(cx)) {
+        AbortProfiling(cx);
+#endif
     }
 
     if (regs.fp->hasImacropc())
         atoms = COMMON_ATOMS_START(&rt->atomState);
 #endif
 
     /* Don't call the script prologue if executing between Method and Trace JIT. */
     if (interpMode == JSINTERP_NORMAL) {
@@ -2622,16 +2641,20 @@ Interpret(JSContext *cx, JSStackFrame *e
 #endif /* !JS_THREADED_INTERP */
     {
         bool moreInterrupts = false;
         JSInterruptHook hook = cx->debugHooks->interruptHook;
         if (hook) {
 #ifdef JS_TRACER
             if (TRACE_RECORDER(cx))
                 AbortRecording(cx, "interrupt hook");
+#ifdef JS_METHODJIT
+            if (TRACE_PROFILER(cx))
+                AbortProfiling(cx);
+#endif
 #endif
             Value rval;
             switch (hook(cx, script, regs.pc, Jsvalify(&rval),
                          cx->debugHooks->interruptHookData)) {
               case JSTRAP_ERROR:
                 goto error;
               case JSTRAP_CONTINUE:
                 break;
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -4408,16 +4408,20 @@ ResetJITImpl(JSContext* cx)
     if (!cx->traceJitEnabled)
         return;
     TraceMonitor* tm = &JS_TRACE_MONITOR(cx);
     debug_only_print0(LC_TMTracer, "Flushing cache.\n");
     if (tm->recorder) {
         JS_ASSERT_NOT_ON_TRACE(cx);
         AbortRecording(cx, "flush cache");
     }
+#if JS_METHODJIT
+    if (tm->profile)
+        AbortProfiling(cx);
+#endif
     if (ProhibitFlush(cx)) {
         debug_only_print0(LC_TMTracer, "Deferring JIT flush due to deep bail.\n");
         tm->needFlush = JS_TRUE;
         return;
     }
     tm->flush();
 }
 
--- a/js/src/tests/js1_5/extensions/jstests.list
+++ b/js/src/tests/js1_5/extensions/jstests.list
@@ -40,19 +40,19 @@ script regress-319683.js
 script regress-322957.js
 script regress-327608.js
 script regress-328443.js
 script regress-328556.js
 skip script regress-330569.js # Yarr doesn't bail on complex regexps.
 script regress-333541.js
 skip script regress-335700.js # bug xxx - reftest hang, BigO
 skip-if(!xulRuntime.shell) script regress-336409-1.js # no results reported.
-skip-if(!xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) silentfail script regress-336409-2.js # can fail silently due to out of memory
+skip-if(!xulRuntime.shell&&((isDebugBuild&&xulRuntime.OS=="Linux")||xulRuntime.XPCOMABI.match(/x86_64/))) silentfail script regress-336409-2.js # can fail silently due to out of memory, bug 615011 - timeouts on slow debug Linux
 skip-if(!xulRuntime.shell) silentfail script regress-336410-1.js # can fail silently due to out of memory
-skip-if(!xulRuntime.shell&&(xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) silentfail script regress-336410-2.js # can fail silently due to out of memory
+skip-if(!xulRuntime.shell&&((isDebugBuild&&xulRuntime.OS=="Linux")||xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) silentfail script regress-336410-2.js # can fail silently due to out of memory, bug 621348 - timeouts on slow debug Linux
 script regress-338804-01.js
 script regress-338804-02.js
 script regress-338804-03.js
 script regress-339685.js
 script regress-341956-01.js
 script regress-341956-02.js
 script regress-341956-03.js
 skip-if(!xulRuntime.shell&&(xulRuntime.OS=="WINNT"||xulRuntime.OS=="Linux")) script regress-342960.js # bug 528464
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1717,17 +1717,21 @@ ImageContainer*
 nsObjectFrame::GetImageContainer()
 {
   nsRefPtr<LayerManager> manager =
     nsContentUtils::LayerManagerForDocument(mContent->GetOwnerDoc());
   if (!manager) {
     return nsnull;
   }
 
-  if (mImageContainer && mImageContainer->Manager() == manager) {
+  // XXX - in the future image containers will be manager independent and
+  // we can remove the manager equals check and only check the backend type.
+  if (mImageContainer && 
+      (!mImageContainer->Manager() || mImageContainer->Manager() == manager) &&
+      mImageContainer->GetBackendType() == manager->GetBackendType()) {
     return mImageContainer;
   }
 
   mImageContainer = manager->CreateImageContainer();
   return mImageContainer;
 }
 
 class AsyncPaintWaitEvent : public nsRunnable
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -188,21 +188,25 @@ nsVideoFrame::BuildLayer(nsDisplayListBu
   // If we have a container with a different layer manager, try to hand
   // off the container to the new one.
   if (container && container->Manager() != aManager) {
     // we don't care about the return type here -- if the set didn't take, it'll
     // be handled when we next check the manager
     container->SetLayerManager(aManager);
   }
 
-  // If we have a container with the right layer manager already, we don't
-  // need to do anything here. Otherwise we need to set up a temporary
+  // If we have a container of the correct type already, we don't need
+  // to do anything here. Otherwise we need to set up a temporary
   // ImageContainer, capture the video data and store it in the temp
-  // container.
-  if (!container || container->Manager() != aManager) {
+  // container. For now we also check if the manager is equal since not all
+  // image containers are manager independent yet.
+  if (!container || 
+      (container->Manager() && container->Manager() != aManager) ||
+      container->GetBackendType() != aManager->GetBackendType())
+  {
     nsRefPtr<ImageContainer> tmpContainer = aManager->CreateImageContainer();
     if (!tmpContainer)
       return nsnull;
     
     // We get a reference to the video data as a cairo surface.
     CairoImage::Data cairoData;
     nsRefPtr<gfxASurface> imageSurface;
     if (container) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-paintserver-1-ref.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect x="0" y="0" width="300" height="400" fill="lime"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-paintserver-1.svg
@@ -0,0 +1,86 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="lime">
+      <stop offset="0.0" stop-color="lime"/>
+    </linearGradient>
+    <linearGradient id="red">
+      <stop offset="0.0" stop-color="red"/>
+    </linearGradient>
+  </defs>
+
+  <!-- 1. Set paint server -->
+  <rect x="0" y="0" width="100" height="100" fill="red">
+    <set attributeName="fill" to="url(#lime)"/>
+  </rect>
+  <!-- 2. Get paint server. We're looking for a code path that will fetch the
+       base value, fail to replace it, and end up setting the animation
+       value as the fetched base value.
+       To-animation requires fetching the base value so we use that, plus
+       invalid animation values so that we won't replace the base value. -->
+  <rect x="100" y="0" width="100" height="100" fill="url(#lime)">
+    <animate attributeName="fill" to="pikapikaglittergold"/>
+  </rect>
+  <!-- 3. "Interpolate" paint servers. We should fall back to discrete mode
+       which should mean that 150s into a 3-valued animation of 400s duration
+       we're in the middle value since each value will get about 133s each.
+  -->
+  <rect x="200" y="0" width="100" height="100" fill="red">
+    <animate attributeName="fill" values="orange; url(#lime); purple"
+      begin="-150s" dur="400s"/>
+  </rect>
+
+  <!-- By addition tests: In the following cases we'll go to calculate our
+       animation function values but since they're by-animation we'll try to do
+       some addition which should fail since addition with paint servers isn't
+       supported and hence the animation should not be applied. -->
+  <!-- 4. Check by-addition behaves (1): by: paint server -->
+  <rect x="0" y="100" width="100" height="100" fill="lime">
+    <animate attributeName="fill" from="#f00" by="url(#red)"/>
+  </rect>
+  <!-- 5. Check by-addition behaves (2): from: paint server -->
+  <rect x="100" y="100" width="100" height="100" fill="lime">
+    <animate attributeName="fill" from="url(#red)" by="#f00"/>
+  </rect>
+  <!-- 6. Check by-addition behaves (3): from-by paint server -->
+  <rect x="200" y="100" width="100" height="100" fill="#0f0">
+    <animate attributeName="fill" from="url(#red)" by="url(#red)"/>
+  </rect>
+
+  <!-- 7. Check that by-addition without a paint server is ok though.
+       (Since the animation has indefinite simple duration we'll never get past
+       the first value which is is lime green.) -->
+  <rect x="0" y="200" width="100" height="100" fill="red">
+    <animate attributeName="fill" from="#0f0" by="#00f" dur="indefinite"/>
+  </rect>
+  <!-- 8. Sandwich addition test. In the following cases we should be able to
+       calculate the animation function ok, but we'll fail to add it to the
+       underlying values (since paint servers can't be added) and just set the
+       value instead. (SMIL 3 12.6.3 says, "[The additive] attribute is
+       ignored if the target attribute does not support additive animation.")
+       -->
+  <rect x="100" y="200" width="100" height="100" fill="red">
+    <animate attributeName="fill" values="url(#lime)" additive="sum"/>
+  </rect>
+  <!-- 9. Check paced animation fails expectedly. The operation is as with case
+       3 and we should fall back to discrete mode -->
+  <rect x="200" y="200" width="100" height="100" fill="red">
+    <animate attributeName="fill" values="#0f1; url(#lime); #00f"
+      begin="-150s" dur="400s" calcMode="paced"/>
+  </rect>
+
+  <!-- 10. Fallback color - specified color -->
+  <rect x="0" y="300" width="100" height="100" fill="red">
+    <set attributeName="fill" to="url(#nonexistant) lime"/>
+  </rect>
+  <!-- 11. Fallback color - currentColor -->
+  <g color="lime">
+    <rect x="100" y="300" width="100" height="100" fill="red">
+      <set attributeName="fill" to="url(#nonexistant) currentColor"/>
+    </rect>
+  </g>
+  <!-- 12. Fallback color - none -->
+  <rect x="200" y="300" width="100" height="100" fill="lime"/>
+  <rect x="200" y="300" width="100" height="100" fill="red">
+    <set attributeName="fill" to="url(#nonexistant) none"/>
+  </rect>
+</svg>
--- a/layout/reftests/svg/smil/reftest.list
+++ b/layout/reftests/svg/smil/reftest.list
@@ -125,16 +125,19 @@ fails == anim-fillcolor-1.svg      anim-
 
 # animate some string attributes:
 == anim-filter-href-01.svg lime.svg
 == anim-gradient-href-01.svg lime.svg
 == anim-image-href-01.svg lime.svg
 == anim-pattern-href-01.svg lime.svg
 asserts(9) == anim-use-href-01.svg lime.svg  # the asserts here are bug 563481
 
+# animate with some paint server values
+== anim-paintserver-1.svg anim-paintserver-1-ref.svg
+
 # animate where the base value is non-interpolatable but will be replaced anyway
 == anim-fill-overpaintserver-1.svg lime.svg
 == anim-fill-overpaintserver-2.svg lime.svg
 
 # animate where we fallback from 'additive' animation to non-additive
 == anim-additive-fallback-1.svg anim-standard-ref.svg
 
 == anim-remove-1.svg anim-standard-ref.svg
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -240,16 +240,26 @@ SetCalcValue(const nsStyleCoord::Calc* a
     arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus);
     nscoordToCSSValue(aCalc->mLength, arr2->Item(0));
     arr2->Item(1).SetPercentValue(aCalc->mPercent);
   }
 
   aValue.SetArrayValue(arr, eCSSUnit_Calc);
 }
 
+static already_AddRefed<nsStringBuffer>
+GetURIAsUtf16StringBuffer(nsIURI* aUri)
+{
+  nsCAutoString utf8String;
+  nsresult rv = aUri->GetSpec(utf8String);
+  NS_ENSURE_SUCCESS(rv, nsnull);
+
+  return nsCSSValue::BufferFromString(NS_ConvertUTF8toUTF16(utf8String));
+}
+
 // CLASS METHODS
 // -------------
 
 PRBool
 nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty,
                                   const Value& aStartValue,
                                   const Value& aEndValue,
                                   double& aDistance)
@@ -357,17 +367,18 @@ nsStyleAnimation::ComputeDistance(nsCSSP
     case eUnit_CSSValuePair: {
       const nsCSSValuePair *pair1 = aStartValue.GetCSSValuePairValue();
       const nsCSSValuePair *pair2 = aEndValue.GetCSSValuePairValue();
       nsCSSUnit unit[2];
       unit[0] = GetCommonUnit(aProperty, pair1->mXValue.GetUnit(),
                               pair2->mXValue.GetUnit());
       unit[1] = GetCommonUnit(aProperty, pair1->mYValue.GetUnit(),
                               pair2->mYValue.GetUnit());
-      if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null) {
+      if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null ||
+          unit[0] == eCSSUnit_URL) {
         return PR_FALSE;
       }
 
       double squareDistance = 0.0;
       static nsCSSValue nsCSSValuePair::* const pairValues[2] = {
         &nsCSSValuePair::mXValue, &nsCSSValuePair::mYValue
       };
       for (PRUint32 i = 0; i < 2; ++i) {
@@ -1452,17 +1463,18 @@ nsStyleAnimation::AddWeighted(nsCSSPrope
     case eUnit_CSSValuePair: {
       const nsCSSValuePair *pair1 = aValue1.GetCSSValuePairValue();
       const nsCSSValuePair *pair2 = aValue2.GetCSSValuePairValue();
       nsCSSUnit unit[2];
       unit[0] = GetCommonUnit(aProperty, pair1->mXValue.GetUnit(),
                               pair2->mXValue.GetUnit());
       unit[1] = GetCommonUnit(aProperty, pair1->mYValue.GetUnit(),
                               pair2->mYValue.GetUnit());
-      if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null) {
+      if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null ||
+          unit[0] == eCSSUnit_URL) {
         return PR_FALSE;
       }
 
       nsAutoPtr<nsCSSValuePair> result(new nsCSSValuePair);
       static nsCSSValue nsCSSValuePair::* const pairValues[2] = {
         &nsCSSValuePair::mXValue, &nsCSSValuePair::mYValue
       };
       for (PRUint32 i = 0; i < 2; ++i) {
@@ -2603,26 +2615,45 @@ nsStyleAnimation::ExtractComputedValue(n
       return PR_TRUE;
     case eStyleAnimType_Color:
       aComputedValue.SetColorValue(*static_cast<const nscolor*>(
         StyleDataAtOffset(styleStruct, ssOffset)));
       return PR_TRUE;
     case eStyleAnimType_PaintServer: {
       const nsStyleSVGPaint &paint = *static_cast<const nsStyleSVGPaint*>(
         StyleDataAtOffset(styleStruct, ssOffset));
-      // FIXME: At some point in the future, we should animate gradients.
       if (paint.mType == eStyleSVGPaintType_Color) {
         aComputedValue.SetColorValue(paint.mPaint.mColor);
         return PR_TRUE;
       }
-      if (paint.mType == eStyleSVGPaintType_None) {
-        aComputedValue.SetNoneValue();
+      if (paint.mType == eStyleSVGPaintType_Server) {
+        if (!paint.mPaint.mPaintServer) {
+          NS_WARNING("Null paint server");
+          return PR_FALSE;
+        }
+        nsAutoPtr<nsCSSValuePair> pair(new nsCSSValuePair);
+        nsRefPtr<nsStringBuffer> uriAsStringBuffer =
+          GetURIAsUtf16StringBuffer(paint.mPaint.mPaintServer);
+        NS_ENSURE_TRUE(!!uriAsStringBuffer, PR_FALSE);
+        nsIDocument* doc = aStyleContext->PresContext()->Document();
+        nsRefPtr<nsCSSValue::URL> url =
+          new nsCSSValue::URL(paint.mPaint.mPaintServer,
+                              uriAsStringBuffer,
+                              doc->GetDocumentURI(),
+                              doc->NodePrincipal());
+        pair->mXValue.SetURLValue(url);
+        pair->mYValue.SetColorValue(paint.mFallbackColor);
+        aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(),
+                                                    eUnit_CSSValuePair);
         return PR_TRUE;
       }
-      return PR_FALSE;
+      NS_ABORT_IF_FALSE(paint.mType == eStyleSVGPaintType_None,
+          "Unexpected SVG paint type");
+      aComputedValue.SetNoneValue();
+      return PR_TRUE;
     }
     case eStyleAnimType_Shadow: {
       const nsCSSShadowArray *shadowArray =
         *static_cast<const nsRefPtr<nsCSSShadowArray>*>(
           StyleDataAtOffset(styleStruct, ssOffset));
       if (!shadowArray) {
         aComputedValue.SetAndAdoptCSSValueListValue(nsnull, eUnit_Shadow);
         return PR_TRUE;
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -764,17 +764,18 @@ nsSVGUtils::GetOuterSVGFrame(nsIFrame *a
 }
 
 nsIFrame*
 nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame, nsRect* aRect)
 {
   nsISVGChildFrame* svg = do_QueryFrame(aFrame);
   if (!svg)
     return nsnull;
-  *aRect = svg->GetCoveredRegion();
+  *aRect = (aFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) ?
+             nsRect(0, 0, 0, 0) : svg->GetCoveredRegion();
   return GetOuterSVGFrame(aFrame);
 }
 
 gfxMatrix
 nsSVGUtils::GetViewBoxTransform(nsSVGElement* aElement,
                                 float aViewportWidth, float aViewportHeight,
                                 float aViewboxX, float aViewboxY,
                                 float aViewboxWidth, float aViewboxHeight,
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/621598-1.svg
@@ -0,0 +1,16 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <marker id="m1">
+    <rect/>
+    <marker>
+      <line id="z" marker-end="url(#m1)"/>
+    </marker>
+  </marker>
+  <script>
+    function boom()
+    {
+      document.getElementById("z").getBoundingClientRect();
+    }
+    window.addEventListener("load", boom, false);
+  </script>
+
+</svg>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -95,8 +95,9 @@ load extref-test-1.xhtml
 load 566216-1.svg
 load 587336-1.html
 load 590291-1.svg
 load 601999-1.html
 load 605626-1.svg
 load 610954-1.html
 load 612662-1.svg
 load 612662-2.svg
+load 621598-1.svg
--- a/toolkit/components/contentprefs/src/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/src/nsContentPrefService.js
@@ -36,16 +36,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 const Cu = Components.utils;
 
+const CACHE_MAX_GROUP_ENTRIES = 100;
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * Remotes the service. All the remoting/electrolysis code is in here,
  * so the regular service code below remains uncluttered and maintainable.
  */
 function electrolify(service) {
   // FIXME: For now, use the wrappedJSObject hack, until bug
@@ -136,16 +138,17 @@ function ContentPrefService() {
 }
 
 ContentPrefService.prototype = {
   //**************************************************************************//
   // XPCOM Plumbing
 
   classID:          Components.ID("{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7}"),
   QueryInterface:   XPCOMUtils.generateQI([Ci.nsIContentPrefService,
+                                           Ci.nsIContentPrefService_MOZILLA_2_0,
                                            Ci.nsIFrameMessageListener]),
 
 
   //**************************************************************************//
   // Convenience Getters
 
   // Observer Service
   __observerSvc: null,
@@ -207,16 +210,85 @@ ContentPrefService.prototype = {
       case "xpcom-shutdown":
         this._destroy();
         break;
     }
   },
 
 
   //**************************************************************************//
+  // Prefs cache
+
+  _cache: {
+    _prefCache: {},
+
+    cachePref: function(aName, aValue, aGroup) {
+      aGroup = aGroup || "__GlobalPrefs__";
+
+      if (!this._prefCache[aGroup]) {
+        this._possiblyCleanCache();
+        this._prefCache[aGroup] = {};
+      }
+
+      this._prefCache[aGroup][aName] = aValue;
+    },
+
+    getPref: function(aName, aGroup) {
+      aGroup = aGroup || "__GlobalPrefs__";
+
+      if (this._prefCache[aGroup] && this._prefCache[aGroup].hasOwnProperty(aName)) {
+        let value = this._prefCache[aGroup][aName];
+        return [true, value];
+      }
+      return [false, undefined];
+    },
+
+    setPref: function(aName, aValue, aGroup) {
+      if (typeof aValue == "boolean")
+        aValue = aValue ? 1 : 0;
+      else if (aValue === undefined)
+        aValue = null;
+
+      this.cachePref(aName, aValue, aGroup);
+    },
+
+    removePref: function(aName, aGroup) {
+      aGroup = aGroup || "__GlobalPrefs__";
+
+      if (this._prefCache[aGroup].hasOwnProperty(aName)) {
+        delete this._prefCache[aGroup][aName];
+        if (Object.keys(this._prefCache[aGroup]).length == 0) {
+          // remove empty group
+          delete this._prefCache[aGroup];
+        }
+      }
+    },
+
+    invalidate: function() {
+      this._prefCache = {};
+    },
+
+    _possiblyCleanCache: function() {
+      let groupCount = Object.keys(this._prefCache).length;
+
+      if (groupCount >= CACHE_MAX_GROUP_ENTRIES) {
+        // Clean half of the entries
+        for (let entry in this._prefCache) {
+          delete this._prefCache[entry];
+          groupCount--;
+
+          if (groupCount < CACHE_MAX_GROUP_ENTRIES / 2)
+            break;
+        }
+      }
+    }
+  },
+
+
+  //**************************************************************************//
   // nsIContentPrefService
 
   getPref: function ContentPrefService_getPref(aGroup, aName, aCallback) {
     if (!aName)
       throw Components.Exception("aName cannot be null or an empty string",
                                  Cr.NS_ERROR_ILLEGAL_VALUE);
 
     var group = this._parseGroupParam(aGroup);
@@ -257,32 +329,43 @@ ContentPrefService.prototype = {
     }
 
     // Update the existing record, if any, or create a new one.
     if (prefID)
       this._updatePref(prefID, aValue);
     else
       this._insertPref(groupID, settingID, aValue);
 
+    this._cache.setPref(aName, aValue, group);
     for each (var observer in this._getObservers(aName)) {
       try {
         observer.onContentPrefSet(group, aName, aValue);
       }
       catch(ex) {
         Cu.reportError(ex);
       }
     }
   },
 
   hasPref: function ContentPrefService_hasPref(aGroup, aName) {
     // XXX If consumers end up calling this method regularly, then we should
     // optimize this to query the database directly.
     return (typeof this.getPref(aGroup, aName) != "undefined");
   },
 
+  hasCachedPref: function ContentPrefService_hasCachedPref(aGroup, aName) {
+    if (!aName)
+      throw Components.Exception("aName cannot be null or an empty string",
+                                 Cr.NS_ERROR_ILLEGAL_VALUE);
+
+    let group = this._parseGroupParam(aGroup);
+    let [cached,] = this._cache.getPref(aName, group);
+    return cached;
+  },
+
   removePref: function ContentPrefService_removePref(aGroup, aName) {
     // If there's no old value, then there's nothing to remove.
     if (!this.hasPref(aGroup, aName))
       return;
 
 
     var settingID = this._selectSettingID(aName);
     var group = this._parseGroupParam(aGroup);
@@ -298,20 +381,22 @@ ContentPrefService.prototype = {
 
     this._deletePref(prefID);
 
     // Get rid of extraneous records that are no longer being used.
     this._deleteSettingIfUnused(settingID);
     if (groupID)
       this._deleteGroupIfUnused(groupID);
 
+    this._cache.removePref(aName, group);
     this._notifyPrefRemoved(group, aName);
   },
 
   removeGroupedPrefs: function ContentPrefService_removeGroupedPrefs() {
+    this._cache.invalidate();
     this._dbConnection.beginTransaction();
     try {
       this._dbConnection.executeSimpleSQL("DELETE FROM prefs WHERE groupID IS NOT NULL");
       this._dbConnection.executeSimpleSQL("DELETE FROM groups");
       this._dbConnection.executeSimpleSQL(
         "DELETE FROM settings " +
         "WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)"
       );
@@ -356,16 +441,17 @@ ContentPrefService.prototype = {
     if (this.hasPref(null, aName)) {
       groupNames.push(null);
     }
 
     this._dbConnection.executeSimpleSQL("DELETE FROM prefs WHERE settingID = " + settingID);
     this._dbConnection.executeSimpleSQL("DELETE FROM settings WHERE id = " + settingID);
 
     for (var i = 0; i < groupNames.length; i++) {
+      this._cache.removePref(aName, groupNames[i]);
       this._notifyPrefRemoved(groupNames[i], aName);
       if (groupNames[i]) // ie. not null, which will be last (and i == groupIDs.length)
         this._deleteGroupIfUnused(groupIDs[i]);
     }
   },
 
   getPrefs: function ContentPrefService_getPrefs(aGroup) {
     var group = this._parseGroupParam(aGroup);
@@ -470,27 +556,49 @@ ContentPrefService.prototype = {
         "JOIN settings ON prefs.settingID = settings.id " +
         "WHERE groups.name = :group " +
         "AND settings.name = :setting"
       );
 
     return this.__stmtSelectPref;
   },
 
+  _scheduleCallback: function(func) {
+    let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
+    tm.mainThread.dispatch(func, Ci.nsIThread.DISPATCH_NORMAL);
+  },
+
   _selectPref: function ContentPrefService__selectPref(aGroup, aSetting, aCallback) {
-    var value;
+
+    let [cached, value] = this._cache.getPref(aSetting, aGroup);
+    if (cached) {
+      if (aCallback) {
+        this._scheduleCallback(function(){aCallback.onResult(value);});
+        return;
+      }
+      return value;
+    }
 
     try {
       this._stmtSelectPref.params.group = aGroup;
       this._stmtSelectPref.params.setting = aSetting;
 
-      if (aCallback)
-        new AsyncStatement(this._stmtSelectPref).execute(aCallback);
-      else if (this._stmtSelectPref.executeStep())
-        value = this._stmtSelectPref.row["value"];
+      if (aCallback) {
+        let cache = this._cache;
+        new AsyncStatement(this._stmtSelectPref).execute({onResult: function(aResult) {
+          cache.cachePref(aSetting, aResult, aGroup);
+          aCallback.onResult(aResult);
+        }});
+      }
+      else {
+        if (this._stmtSelectPref.executeStep()) {
+          value = this._stmtSelectPref.row["value"];
+        }
+        this._cache.cachePref(aSetting, value, aGroup);
+      }
     }
     finally {
       this._stmtSelectPref.reset();
     }
 
     return value;
   },
 
@@ -504,25 +612,42 @@ ContentPrefService.prototype = {
         "WHERE prefs.groupID IS NULL " +
         "AND settings.name = :name"
       );
 
     return this.__stmtSelectGlobalPref;
   },
 
   _selectGlobalPref: function ContentPrefService__selectGlobalPref(aName, aCallback) {
-    var value;
+
+    let [cached, value] = this._cache.getPref(aName, null);
+    if (cached) {
+      if (aCallback) {
+        this._scheduleCallback(function(){aCallback.onResult(value);});
+        return;
+      }
+      return value;
+    }
 
     try {
       this._stmtSelectGlobalPref.params.name = aName;
 
-      if (aCallback)
-        new AsyncStatement(this._stmtSelectGlobalPref).execute(aCallback);
-      else if (this._stmtSelectGlobalPref.executeStep())
-        value = this._stmtSelectGlobalPref.row["value"];
+      if (aCallback) {
+        let cache = this._cache;
+        new AsyncStatement(this._stmtSelectGlobalPref).execute({onResult: function(aResult) {
+          cache.cachePref(aName, aResult);
+          aCallback.onResult(aResult);
+        }});
+      }
+      else {
+        if (this._stmtSelectGlobalPref.executeStep()) {
+          value = this._stmtSelectGlobalPref.row["value"];
+        }
+        this._cache.cachePref(aName, value);
+      }
     }
     finally {
       this._stmtSelectGlobalPref.reset();
     }
 
     return value;
   },
 
--- a/toolkit/components/contentprefs/tests/unit/tail_contentPrefs.js
+++ b/toolkit/components/contentprefs/tests/unit/tail_contentPrefs.js
@@ -30,8 +30,9 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 ContentPrefTest.deleteDatabase();
+ContentPrefTest.__dirSvc = null;
new file mode 100644
--- /dev/null
+++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefsCache.js
@@ -0,0 +1,243 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+let cps = Cc["@mozilla.org/content-pref/service;1"].
+          getService(Ci.nsIContentPrefService_MOZILLA_2_0);
+
+function run_test() {
+  testCacheWorks("test1.example.com", "test-pref1");
+  testHasCachedPrefFunction("test2.example.com", "test-pref2");
+  testSetCaches("test3.example.com", "test-pref3");
+  testGetCaches("test4.example.com", "test-pref4");
+  testRemovePrefs("test5.example.com", "test-pref5");
+  testTypeConversions("test6.example.com", "test-pref6");
+  testNonExistingPrefCachesAsUndefined("test7.example.com", "test-pref7");
+  testCacheEviction("test8.example.com", "test-pref8");
+}
+
+function testCacheWorks(uri, prefName) {
+  const CACHED_VALUE = 3;
+  const NEW_VALUE = 5;
+
+  cps.setPref(uri, prefName, CACHED_VALUE);
+  do_check_eq(cps.getPref(uri, prefName), CACHED_VALUE);
+
+  // Now change the value directly through the DB and check
+  // that the cached value is different
+
+  let groupId = selectValue("SELECT id FROM groups WHERE name = :param1", "id", uri);
+  let settingId = selectValue("SELECT id FROM settings WHERE name = :param1", "id", prefName);
+  let prefId = selectValue("SELECT id FROM prefs WHERE groupID = :param1 AND settingID = :param2",
+                           "id", groupId, settingId);
+
+  let stmt = cps.DBConnection.createStatement("UPDATE prefs SET value = :value WHERE id = :id");
+  stmt.params.value = NEW_VALUE;
+  stmt.params.id = prefId;
+  stmt.execute();
+
+  let dbValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
+  let cacheValue = cps.getPref(uri, prefName);
+
+  do_check_eq(dbValue, NEW_VALUE);
+  do_check_eq(cacheValue, CACHED_VALUE);
+  do_check_neq(cacheValue, dbValue);
+
+  do_test_pending();
+  cps.getPref(uri, prefName, function (value) {
+    do_check_eq(dbValue, NEW_VALUE);
+    do_check_eq(value, CACHED_VALUE);
+    do_check_neq(value, dbValue);
+    do_test_finished();
+  });
+}
+
+function testHasCachedPrefFunction(uri, prefName) {
+  const STARTING_VALUE = 3;
+  const NEW_VALUE = 5;
+
+  do_check_false(isCached(uri, prefName));
+
+  cps.setPref(uri, prefName, STARTING_VALUE);
+
+  let groupId = selectValue("SELECT id FROM groups WHERE name = :param1", "id", uri);
+  let settingId = selectValue("SELECT id FROM settings WHERE name = :param1", "id", prefName);
+  let prefId = selectValue("SELECT id FROM prefs WHERE groupID = :param1 AND settingID = :param2",
+                       "id", groupId, settingId);
+
+  do_check_neq(prefId, undefined);
+
+  let originalValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
+  do_check_eq(originalValue, STARTING_VALUE);
+
+  let stmt = cps.DBConnection.createStatement("UPDATE prefs SET value = :value WHERE id = :id");
+  stmt.params.value = NEW_VALUE;
+  stmt.params.id = prefId;
+  stmt.execute();
+
+  let newValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
+  do_check_eq(newValue, NEW_VALUE);
+
+  let cachedValue = cps.getPref(uri, prefName);
+  do_check_eq(cachedValue, STARTING_VALUE);
+  do_check_true(isCached(uri, prefName));
+}
+
+function testSetCaches(uri, prefName) {
+  cps.setPref(uri, prefName, 0);
+  do_check_true(isCached(uri, prefName));
+}
+
+function testRemovePrefs(uri, prefName) {
+
+  /* removePref */
+  cps.setPref("www1." + uri, prefName, 1);
+
+  do_check_eq(cps.getPref("www1." + uri, prefName), 1);
+
+  cps.removePref("www1." + uri, prefName);
+
+  do_check_false(isCached("www1." + uri, prefName));
+  do_check_false(cps.hasPref("www1." + uri, prefName));
+  do_check_neq(cps.getPref("www1." + uri, prefName), 1);
+
+  /* removeGroupedPrefs */
+  cps.setPref("www2." + uri, prefName, 2);
+  cps.setPref("www3." + uri, prefName, 3);
+
+  do_check_eq(cps.getPref("www2." + uri, prefName), 2);
+  do_check_eq(cps.getPref("www3." + uri, prefName), 3);
+
+  cps.removeGroupedPrefs();
+
+  do_check_false(isCached("www2." + uri, prefName));
+  do_check_false(isCached("www3." + uri, prefName));
+  do_check_false(cps.hasPref("www2." + uri, prefName));
+  do_check_false(cps.hasPref("www3." + uri, prefName));
+  do_check_neq(cps.getPref("www2." + uri, prefName), 2);
+  do_check_neq(cps.getPref("www3." + uri, prefName), 3);
+
+  /* removePrefsByName */
+  cps.setPref("www4." + uri, prefName, 4);
+  cps.setPref("www5." + uri, prefName, 5);
+
+  do_check_eq(cps.getPref("www4." + uri, prefName), 4);
+  do_check_eq(cps.getPref("www5." + uri, prefName), 5);
+
+  cps.removePrefsByName(prefName);
+
+  do_check_false(isCached("www4." + uri, prefName));
+  do_check_false(isCached("www5." + uri, prefName));
+  do_check_false(cps.hasPref("www4." + uri, prefName));
+  do_check_false(cps.hasPref("www5." + uri, prefName));
+  do_check_neq(cps.getPref("www4." + uri, prefName), 4);
+  do_check_neq(cps.getPref("www5." + uri, prefName), 5);
+}
+
+function testGetCaches(uri, prefName) {
+  const VALUE = 4;
+
+  let insertGroup = cps.DBConnection.createStatement("INSERT INTO groups (name) VALUES (:name)");
+  insertGroup.params.name = uri;
+  insertGroup.execute();
+  let groupId = cps.DBConnection.lastInsertRowID;
+
+  let insertSetting = cps.DBConnection.createStatement("INSERT INTO settings (name) VALUES (:name)");
+  insertSetting.params.name = prefName;
+  insertSetting.execute();
+  let settingId = cps.DBConnection.lastInsertRowID;
+
+  let insertPref = cps.DBConnection.createStatement("INSERT INTO prefs (groupID, settingID, value) " +
+                                                    "VALUES (:groupId, :settingId, :value)");
+  insertPref.params.groupId = groupId;
+  insertPref.params.settingId = settingId;
+  insertPref.params.value = VALUE;
+  insertPref.execute();
+  let prefId = cps.DBConnection.lastInsertRowID;
+
+  let dbValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
+
+  // First access from service should hit the DB
+  let svcValue = cps.getPref(uri, prefName);
+
+  // Second time should get the value from cache
+  let cacheValue = cps.getPref(uri, prefName);
+
+  do_check_eq(VALUE, dbValue);
+  do_check_eq(VALUE, svcValue);
+  do_check_eq(VALUE, cacheValue);
+
+  do_check_true(isCached(uri, prefName));
+}
+
+function testTypeConversions(uri, prefName) {
+  let value;
+
+  cps.setPref(uri, prefName, true);
+  value = cps.getPref(uri, prefName);
+  do_check_true(value === 1);
+
+  cps.setPref(uri, prefName, false);
+  value = cps.getPref(uri, prefName);
+  do_check_true(value === 0);
+
+  cps.setPref(uri, prefName, null);
+  value = cps.getPref(uri, prefName);
+  do_check_true(value === null);
+
+  cps.setPref(uri, prefName, undefined);
+  value = cps.getPref(uri, prefName);
+  do_check_true(value === null);
+}
+
+function testNonExistingPrefCachesAsUndefined(uri, prefName) {
+
+  do_check_false(isCached(uri, prefName));
+
+  // Cache the pref
+  let value = cps.getPref(uri, prefName);
+  do_check_true(value === undefined);
+
+  do_check_true(isCached(uri, prefName));
+
+  // Cached pref
+  value = cps.getPref(uri, prefName);
+  do_check_true(value === undefined);
+}
+
+function testCacheEviction(uri, prefName) {
+
+  cps.setPref(uri, prefName, 5);
+  do_check_eq(cps.getPref(uri, prefName), 5);
+  do_check_true(isCached(uri, prefName));
+
+  // try to evict value from cache by adding various other entries
+  const ENTRIES_TO_ADD = 200;
+  for (let i = 0; i < ENTRIES_TO_ADD; i++) {
+    let uriToAdd = "www" + i + uri;
+    cps.setPref(uriToAdd, prefName, 0);
+  }
+
+  do_check_false(isCached(uri, prefName));
+
+}
+
+function selectValue(stmt, columnName, param1, param2) {
+  let stmt = cps.DBConnection.createStatement(stmt);
+  if (param1)
+    stmt.params.param1 = param1;
+
+  if (param2)
+    stmt.params.param2 = param2;
+
+  stmt.executeStep();
+  let val = stmt.row[columnName];
+  stmt.reset();
+  stmt.finalize();
+  return val;
+}
+
+function isCached(uri, prefName) {
+  return cps.hasCachedPref(uri, prefName);
+}
--- a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
@@ -135,17 +135,17 @@ nsTypeAheadFind::Init(nsIDocShell* aDocS
   mEndPointRange = do_CreateInstance(kRangeCID);
   mFind = do_CreateInstance(NS_FIND_CONTRACTID);
   if (!prefInternal || !mSearchRange || !mStartPointRange || !mEndPointRange || !mFind)
     return NS_ERROR_FAILURE;
 
   SetDocShell(aDocShell);
 
   // ----------- Listen to prefs ------------------
-  nsresult rv = prefInternal->AddObserver("accessibility.browsewithcaret", this, PR_FALSE);
+  nsresult rv = prefInternal->AddObserver("accessibility.browsewithcaret", this, PR_TRUE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // ----------- Get initial preferences ----------
   PrefsReset();
 
   // ----------- Set search options ---------------
   mFind->SetCaseSensitive(PR_FALSE);
   mFind->SetWordBreaker(nsnull);
--- a/toolkit/content/Services.jsm
+++ b/toolkit/content/Services.jsm
@@ -58,17 +58,17 @@ XPCOMUtils.defineLazyGetter(Services, "a
 XPCOMUtils.defineLazyGetter(Services, "dirsvc", function () {
   return Cc["@mozilla.org/file/directory_service;1"]
            .getService(Ci.nsIDirectoryService)
            .QueryInterface(Ci.nsIProperties);
 });
 
 XPCOMUtils.defineLazyServiceGetter(Services, "contentPrefs",
                                    "@mozilla.org/content-pref/service;1",
-                                   "nsIContentPrefService");
+                                   "nsIContentPrefService_MOZILLA_2_0");
 
 XPCOMUtils.defineLazyServiceGetter(Services, "wm",
                                    "@mozilla.org/appshell/window-mediator;1",
                                    "nsIWindowMediator");
 
 XPCOMUtils.defineLazyServiceGetter(Services, "obs",
                                    "@mozilla.org/observer-service;1",
                                    "nsIObserverService");
--- a/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js
+++ b/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js
@@ -45,16 +45,23 @@ function test()
       ok((scrollHori && elem.scrollLeft > 0) ||
          (!scrollHori && elem.scrollLeft == 0),
          test.elem+' should'+(scrollHori ? '' : ' not')+' have scrolled horizontally');
       window.removeEventListener("MozAfterPaint", checkScroll, false);
       nextTest();
     };
     EventUtils.synthesizeMouse(elem, 50, 50, { button: 1 },
                                gBrowser.contentWindow);
+
+    var iframe = gBrowser.contentDocument.getElementById("iframe");
+    var e = iframe.contentDocument.createEvent("pagetransition");
+    e.initPageTransitionEvent("pagehide", true, true, false);
+    iframe.contentDocument.dispatchEvent(e);
+    iframe.contentDocument.documentElement.dispatchEvent(e);
+
     EventUtils.synthesizeMouse(elem, 100, 100,
                                { type: "mousemove", clickCount: "0" },
                                gBrowser.contentWindow);
     window.addEventListener("MozAfterPaint", checkScroll, false);
     /*
      * if scrolling didn’t work, we wouldn’t do any redraws and thus time out.
      * so request and force redraws to get the chance to check for scrolling at
      * all.
@@ -72,16 +79,17 @@ function test()
     <select id="e" style="width: 100px; height: 100px;" multiple="multiple"><option>aaaaaaaaaaaaaaaaaaaaaaaa</option><option>a</option><option>a</option>\
     <option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option>\
     <option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option></select>\
     <select id="f" style="width: 100px; height: 100px;"><option>a</option><option>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</option><option>a</option>\
     <option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option>\
     <option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option></select>\
     <div id="g" style="width: 99px; height: 99px; padding: 10px; border: 10px solid black; margin: 10px; overflow: auto;"><div style="width: 100px; height: 100px;"></div></div>\
     <div id="h" style="width: 100px; height: 100px; overflow: -moz-hidden-unscrollable;"><div style="width: 200px; height: 200px;"></div></div>\
+    <iframe id="iframe" style="display: none;"></iframe>\
     </body>';
   gBrowser.selectedBrowser.addEventListener("pageshow", onLoad, false);
   gBrowser.loadURI(dataUri);
 
   function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("pageshow", onLoad, false);
     waitForFocus(onFocus, content);
   }
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -499,18 +499,24 @@
             if (this.feeds && aEvent.target == this.contentDocument)
               this.feeds = null;
             if (!this.docShell || !this.fastFind)
               return;
             var tabBrowser = this.getTabBrowser();
             if (!tabBrowser || tabBrowser.mCurrentBrowser == this)
               this.fastFind.setDocShell(this.docShell);
 
-            if (this._scrollable)
-              this._autoScrollPopup.hidePopup();
+            
+            if (this._scrollable) {
+              var doc =
+                this._scrollable.ownerDocument || this._scrollable.document;
+              if (doc == aEvent.target) {
+                this._autoScrollPopup.hidePopup();
+              }
+            }
          ]]>
         </body>
       </method>
 
       <method name="updatePageReport">
         <body>
           <![CDATA[
             var event = document.createEvent("Events");
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -677,16 +677,17 @@ CHECKSUM_ALGORITHM = 'sha512'
 
 # This variable defines where the checksum file will be located
 CHECKSUM_FILE = "$(DIST)/$(PKG_PATH)/$(PKG_BASENAME).checksums"
 
 UPLOAD_FILES= \
   $(call QUOTED_WILDCARD,$(DIST)/$(PACKAGE)) \
   $(call QUOTED_WILDCARD,$(INSTALLER_PACKAGE)) \
   $(call QUOTED_WILDCARD,$(DIST)/$(COMPLETE_MAR)) \
+  $(call QUOTED_WILDCARD,$(DIST)/$(LANGPACK)) \
   $(call QUOTED_WILDCARD,$(wildcard $(DIST)/$(PARTIAL_MAR))) \
   $(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)) \
   $(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip) \
   $(call QUOTED_WILDCARD,$(DIST)/$(SDK)) \
   $(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)/$(PKG_BASENAME).txt) \
   $(if $(UPLOAD_EXTRA_FILES), $(foreach f, $(UPLOAD_EXTRA_FILES), $(wildcard $(DIST)/$(f))))
 
 checksum: