Merge mozilla-central to build-system.
authorMitchell Field <mitchell.field@live.com.au>
Sun, 13 Mar 2011 04:21:37 +1100
changeset 63506 14fc52a00b6cf21735b64aa78783fe0f34dde300
parent 63505 d0dd8edeeb9cc9890d2b4a5a04f9f04cf389ea82 (current diff)
parent 63397 d8fe8514d7e69344437c3f525d99bb862adcec4d (diff)
child 63507 171d8c799fb4592d4ee0764a44d6254206644297
push idunknown
push userunknown
push dateunknown
milestone2.0b13pre
Merge mozilla-central to build-system.
layout/base/nsPresContext.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -884,16 +884,17 @@ TransferZoomLevels(nsIDocument* aFromDoc
   if (!toShell)
     return;
 
   nsPresContext* toCtxt = toShell->GetPresContext();
   if (!toCtxt)
     return;
 
   toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
+  toCtxt->SetMinFontSize(fromCtxt->MinFontSize());
   toCtxt->SetTextZoom(fromCtxt->TextZoom());
 }
 
 void
 TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
 {
   NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
                     "transferring showing state from/to null doc");
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -1,10 +1,10 @@
 load 459439-1.html
 load 466607-1.html
 load 466945-1.html
 load 468763-1.html
 load 474744-1.html
 HTTP load 481136-1.html # needs to be HTTP to recognize the ogg as an audio file?
 load 493915-1.html
-load 495794-1.html
+skip-if(Android) load 495794-1.html
 load 492286-1.xhtml
 load 576612-1.html
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1336,17 +1336,18 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
         FindPrototypeAttribute(aNameSpaceID, aName);
     if (protoattr) {
         // We've got an attribute on the prototype, so we need to
         // fully fault and remove the local copy.
         rv = MakeHeavyweight();
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    nsAutoRemovableScriptBlocker scriptBlocker;
+    nsIDocument* doc = GetCurrentDoc();
+    mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
 
     PRBool isId = PR_FALSE;
     if (aName == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
       // Have to do this before clearing flag. See RemoveFromIdTable
       RemoveFromIdTable();
       isId = PR_TRUE;
     }
 
@@ -1356,19 +1357,16 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
                                  "have a normal one");
 
         return NS_OK;
     }
 
     nsAutoString oldValue;
     GetAttr(aNameSpaceID, aName, oldValue);
 
-    nsIDocument* doc = GetCurrentDoc();
-    mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
-
     // When notifying, make sure to keep track of states whose value
     // depends solely on the value of an attribute.
     nsEventStates stateMask;
     if (aNotify) {
         stateMask = IntrinsicState();
  
         nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
                                          nsIDOMMutationEvent::REMOVAL);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6946,22 +6946,26 @@ nsDocShell::RestoreFromHistory()
         viewer->GetDOMDocument(getter_AddRefs(domDoc));
         nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
         nsIRequest *request = nsnull;
         if (doc)
             request = doc->GetChannel();
         mSavingOldViewer = CanSavePresentation(mLoadType, request, doc);
     }
 
-    nsCOMPtr<nsIMarkupDocumentViewer> oldMUDV(do_QueryInterface(mContentViewer));
-    nsCOMPtr<nsIMarkupDocumentViewer> newMUDV(do_QueryInterface(viewer));
+    nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> oldMUDV(
+        do_QueryInterface(mContentViewer));
+    nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> newMUDV(
+        do_QueryInterface(viewer));
+    PRInt32 minFontSize = 0;
     float textZoom = 1.0f;
     float pageZoom = 1.0f;
     PRBool styleDisabled = PR_FALSE;
     if (oldMUDV && newMUDV) {
+        oldMUDV->GetMinFontSize(&minFontSize);
         oldMUDV->GetTextZoom(&textZoom);
         oldMUDV->GetFullZoom(&pageZoom);
         oldMUDV->GetAuthorStyleDisabled(&styleDisabled);
     }
 
     // Protect against mLSHE going away via a load triggered from
     // pagehide or unload.
     nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
@@ -7151,16 +7155,17 @@ nsDocShell::RestoreFromHistory()
 
     // Tell the event loop to favor plevents over user events, see comments
     // in CreateContentViewer.
     if (++gNumberOfDocumentsLoading == 1)
         FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT);
 
 
     if (oldMUDV && newMUDV) {
+        newMUDV->SetMinFontSize(minFontSize);
         newMUDV->SetTextZoom(textZoom);
         newMUDV->SetFullZoom(pageZoom);
         newMUDV->SetAuthorStyleDisabled(styleDisabled);
     }
 
     nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
     PRUint32 parentSuspendCount = 0;
     if (document) {
@@ -7595,24 +7600,25 @@ nsDocShell::SetupNewViewer(nsIContentVie
                       NS_ERROR_FAILURE);
     nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
 
     nsCAutoString defaultCharset;
     nsCAutoString forceCharset;
     nsCAutoString hintCharset;
     PRInt32 hintCharsetSource;
     nsCAutoString prevDocCharset;
+    PRInt32 minFontSize;
     float textZoom;
     float pageZoom;
     PRBool styleDisabled;
     // |newMUDV| also serves as a flag to set the data from the above vars
-    nsCOMPtr<nsIMarkupDocumentViewer> newMUDV;
+    nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> newMUDV;
 
     if (mContentViewer || parent) {
-        nsCOMPtr<nsIMarkupDocumentViewer> oldMUDV;
+        nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> oldMUDV;
         if (mContentViewer) {
             // Get any interesting state from old content viewer
             // XXX: it would be far better to just reuse the document viewer ,
             //      since we know we're just displaying the same document as before
             oldMUDV = do_QueryInterface(mContentViewer);
 
             // Tell the old content viewer to hibernate in session history when
             // it is destroyed.
@@ -7644,16 +7650,19 @@ nsDocShell::SetupNewViewer(nsIContentVie
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetHintCharacterSet(hintCharset),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetHintCharacterSetSource(&hintCharsetSource),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
+                                  GetMinFontSize(&minFontSize),
+                                  NS_ERROR_FAILURE);
+                NS_ENSURE_SUCCESS(oldMUDV->
                                   GetTextZoom(&textZoom),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetFullZoom(&pageZoom),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetAuthorStyleDisabled(&styleDisabled),
                                   NS_ERROR_FAILURE);
@@ -7723,16 +7732,18 @@ nsDocShell::SetupNewViewer(nsIContentVie
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetHintCharacterSet(hintCharset),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->
                           SetHintCharacterSetSource(hintCharsetSource),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetPrevDocCharacterSet(prevDocCharset),
                           NS_ERROR_FAILURE);
+        NS_ENSURE_SUCCESS(newMUDV->SetMinFontSize(minFontSize),
+                          NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetTextZoom(textZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetFullZoom(pageZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetAuthorStyleDisabled(styleDisabled),
                           NS_ERROR_FAILURE);
     }
 
--- a/docshell/base/nsIMarkupDocumentViewer.idl
+++ b/docshell/base/nsIMarkupDocumentViewer.idl
@@ -149,8 +149,16 @@ interface nsIMarkupDocumentViewer : nsIS
    */
   attribute octet bidiCharacterSet;  
   
   /**
    * Use this attribute to access all the Bidi options in one operation
    */
   attribute PRUint32 bidiOptions;
 };
+
+[scriptable, uuid(cadfcad1-5570-4dac-b5a2-cd1ea751fe29)]
+interface nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH : nsIMarkupDocumentViewer
+{
+	/** The minimum font size  */
+	attribute long minFontSize;
+
+};
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -957,47 +957,96 @@ public class GeckoAppShell
 
         Resources res = GeckoApp.mAppContext.getBaseContext().getResources();
         Configuration config = res.getConfiguration();
         config.locale = locale;
         res.updateConfiguration(config, res.getDisplayMetrics());
     }
 
     public static void killAnyZombies() {
-        File proc = new File("/proc");
-        File[] files = proc.listFiles();
-        for (int i = 0; i < files.length; i++) {
-            File p = files[i];
-            File pEnv = new File(p, "environ");
-            if (pEnv.canRead() && !p.getName().equals("self")) {
-                int pid = Integer.parseInt(p.getName());
-                if (pid != android.os.Process.myPid()) {
-                    Log.i("GeckoProcs", "gonna kill pid: " + p.getName());
+        GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
+            public boolean callback(int pid) {
+                if (pid != android.os.Process.myPid())
                     android.os.Process.killProcess(pid);
-                }
+                return true;
             }
-        }
+        };
+            
+        EnumerateGeckoProcesses(visitor);
     }
 
     public static boolean checkForGeckoProcs() {
-        File proc = new File("/proc");
-        File[] files = proc.listFiles();
-        for (int i = 0; i < files.length; i++) {
-            File p = files[i];
-            File pEnv = new File(p, "environ");
-            if (pEnv.canRead() && !p.getName().equals("self")) {
-                int pid = Integer.parseInt(p.getName());
+
+        class GeckoPidCallback implements GeckoProcessesVisitor {
+            public boolean otherPidExist = false;
+            public boolean callback(int pid) {
                 if (pid != android.os.Process.myPid()) {
-                    Log.i("GeckoProcs", "found pid: " + p.getName());
-                    return true;
+                    otherPidExist = true;
+                    return false;
+                }
+                return true;
+            }            
+        }
+        GeckoPidCallback visitor = new GeckoPidCallback();            
+        EnumerateGeckoProcesses(visitor);
+        return visitor.otherPidExist;
+    }
+
+    interface GeckoProcessesVisitor{
+        boolean callback(int pid);
+    }
+
+    static int sPidColumn = -1;
+    static int sUserColumn = -1;
+    private static void EnumerateGeckoProcesses(GeckoProcessesVisitor visiter) {
+
+        try {
+
+            // run ps and parse its output
+            java.lang.Process ps = Runtime.getRuntime().exec("ps");
+            BufferedReader in = new BufferedReader(new InputStreamReader(ps.getInputStream()),
+                                                   2048);
+
+            String headerOutput = in.readLine();
+
+            // figure out the column offsets.  We only care about the pid and user fields
+            if (sPidColumn == -1 || sUserColumn == -1) {
+                StringTokenizer st = new StringTokenizer(headerOutput);
+                
+                int tokenSoFar = 0;
+                while(st.hasMoreTokens()) {
+                    String next = st.nextToken();
+                    if (next.equalsIgnoreCase("PID"))
+                        sPidColumn = tokenSoFar;
+                    else if (next.equalsIgnoreCase("USER"))
+                        sUserColumn = tokenSoFar;
+                    tokenSoFar++;
                 }
             }
+
+            // alright, the rest are process entries.
+            String psOutput = null;
+            while ((psOutput = in.readLine()) != null) {
+                String[] split = psOutput.split("\\s+");
+                if (split.length <= sPidColumn || split.length <= sUserColumn)
+                    continue;
+                int uid = android.os.Process.getUidForName(split[sUserColumn]);
+                if (uid == android.os.Process.myUid() &&
+                    !split[split.length - 1].equalsIgnoreCase("ps")) {
+                    int pid = Integer.parseInt(split[sPidColumn]);
+                    boolean keepGoing = visiter.callback(pid);
+                    if (keepGoing == false)
+                        break;
+                }
+            }
+            in.close();
         }
-        Log.i("GeckoProcs", "didn't find any other procs");
-        return false;
+        catch (Exception e) {
+            Log.i("GeckoAppShell", "finding procs throws ",  e);
+        }
     }
 
     public static void waitForAnotherGeckoProc(){
         int countdown = 40;
         while (!checkForGeckoProcs() &&  --countdown > 0) {
             try {
                 Thread.currentThread().sleep(100);
             } catch (InterruptedException ie) {}
--- a/embedding/android/Restarter.java.in
+++ b/embedding/android/Restarter.java.in
@@ -54,18 +54,27 @@ public class Restarter extends Activity 
             int countdown = 40;
             while (GeckoAppShell.checkForGeckoProcs() &&  --countdown > 0) {
                 // Wait for the old process to die before we continue
                 try {
                     Thread.currentThread().sleep(100);
                 } catch (InterruptedException ie) {}
             }
             
-            if (countdown <= 0) // if the countdown expired, something is hung
+            if (countdown <= 0) {
+                // if the countdown expired, something is hung
                 GeckoAppShell.killAnyZombies();
+                countdown = 10;
+                // wait for the kill to take effect
+                while (GeckoAppShell.checkForGeckoProcs() &&  --countdown > 0) {
+                    try {
+                        Thread.currentThread().sleep(100);
+                    } catch (InterruptedException ie) {}
+                }
+            }
         } catch (Exception e) {
             Log.i("Restarter", e.toString());
         }
         try {
             String action = "android.intent.action.MAIN";
             Intent intent = new Intent(action);
             intent.setClassName("@ANDROID_PACKAGE_NAME@",
                                 "@ANDROID_PACKAGE_NAME@.App");
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -217,16 +217,17 @@ WrapRotationAxis(PRInt32* aRotationPoint
 }
 
 ThebesLayerBuffer::PaintState
 ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
                               float aXResolution, float aYResolution,
                               PRUint32 aFlags)
 {
   PaintState result;
+  result.mDidSelfCopy = PR_FALSE;
   float curXRes = aLayer->GetXResolution();
   float curYRes = aLayer->GetYResolution();
 
   nsIntRegion validRegion = aLayer->GetValidRegion();
 
   ContentType contentType;
   nsIntRegion neededRegion;
   nsIntSize destBufferDims;
@@ -331,16 +332,17 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
           (newRotation != nsIntPoint(0,0) && !canHaveRotation)) {
         // The stuff we need to redraw will wrap around an edge of the
         // buffer, so move the pixels we can keep into a position that
         // lets us redraw in just one quadrant.
         if (mBufferRotation == nsIntPoint(0,0)) {
           nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
           nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
           MovePixels(mBuffer, srcRect, dest, curXRes, curYRes);
+          result.mDidSelfCopy = PR_TRUE;
           // Don't set destBuffer; we special-case self-copies, and
           // just did the necessary work above.
           mBufferRect = destBufferRect;
         } else {
           // We can't do a real self-copy because the buffer is rotated.
           // So allocate a new buffer for the destination.
           destBufferRect = neededRegion.GetBounds();
           bufferDimsChanged = PR_TRUE;
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -105,22 +105,24 @@ public:
   }
 
   /**
    * This is returned by BeginPaint. The caller should draw into mContext.
    * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
    * by ThebesLayerBuffer and must be redrawn on the screen.
    * mRegionToInvalidate is set when the buffer has changed from
    * opaque to transparent or vice versa, since the details of rendering can
-   * depend on the buffer type.
+   * depend on the buffer type.  mDidSelfCopy is true if we kept our buffer
+   * but used MovePixels() to shift its content.
    */
   struct PaintState {
     nsRefPtr<gfxContext> mContext;
     nsIntRegion mRegionToDraw;
     nsIntRegion mRegionToInvalidate;
+    PRPackedBool mDidSelfCopy;
   };
 
   enum {
     PAINT_WILL_RESAMPLE = 0x01
   };
   /**
    * Start a drawing operation. This returns a PaintState describing what
    * needs to be drawn to bring the buffer up to date in the visible region.
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -423,16 +423,17 @@ protected:
     return static_cast<BasicLayerManager*>(mManager);
   }
 
   virtual void
   PaintBuffer(gfxContext* aContext,
               const nsIntRegion& aRegionToDraw,
               const nsIntRegion& aExtendedRegionToDraw,
               const nsIntRegion& aRegionToInvalidate,
+              PRBool aDidSelfCopy,
               LayerManager::DrawThebesLayerCallback aCallback,
               void* aCallbackData)
   {
     if (!aCallback) {
       BasicManager()->SetTransactionIncomplete();
       return;
     }
     aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate,
@@ -603,16 +604,17 @@ BasicThebesLayer::PaintThebes(gfxContext
       state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
       nsIntRegion extendedDrawRegion = state.mRegionToDraw;
       extendedDrawRegion.ExtendForScaling(paintXRes, paintYRes);
       mXResolution = paintXRes;
       mYResolution = paintYRes;
       SetAntialiasingFlags(this, state.mContext);
       PaintBuffer(state.mContext,
                   state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
+                  state.mDidSelfCopy,
                   aCallback, aCallbackData);
       Mutated();
     } else {
       // It's possible that state.mRegionToInvalidate is nonempty here,
       // if we are shrinking the valid region to nothing.
       NS_ASSERTION(state.mRegionToDraw.IsEmpty(),
                    "If we need to draw, we should have a context");
     }
@@ -1795,16 +1797,17 @@ private:
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   NS_OVERRIDE virtual void
   PaintBuffer(gfxContext* aContext,
               const nsIntRegion& aRegionToDraw,
               const nsIntRegion& aExtendedRegionToDraw,
               const nsIntRegion& aRegionToInvalidate,
+              PRBool aDidSelfCopy,
               LayerManager::DrawThebesLayerCallback aCallback,
               void* aCallbackData);
 
   NS_OVERRIDE virtual already_AddRefed<gfxASurface>
   CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
 
   // This describes the gfxASurface we hand to mBuffer.  We keep a
   // copy of the descriptor here so that we can call
@@ -1855,31 +1858,37 @@ BasicShadowableThebesLayer::SetBackBuffe
   // back buffer (i.e. as they were for the old back buffer)
 }
 
 void
 BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
                                         const nsIntRegion& aRegionToDraw,
                                         const nsIntRegion& aExtendedRegionToDraw,
                                         const nsIntRegion& aRegionToInvalidate,
+                                        PRBool aDidSelfCopy,
                                         LayerManager::DrawThebesLayerCallback aCallback,
                                         void* aCallbackData)
 {
   Base::PaintBuffer(aContext,
                     aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate,
+                    aDidSelfCopy,
                     aCallback, aCallbackData);
   if (!HasShadow()) {
     return;
   }
 
   nsIntRegion updatedRegion;
-  if (mIsNewBuffer) {
+  if (mIsNewBuffer || aDidSelfCopy) {
     // A buffer reallocation clears both buffers. The front buffer has all the
     // content by now, but the back buffer is still clear. Here, in effect, we
     // are saying to copy all of the pixels of the front buffer to the back.
+    // Also when we self-copied in the buffer, the buffer space
+    // changes and some changed buffer content isn't reflected in the
+    // draw or invalidate region (on purpose!).  When this happens, we
+    // need to read back the entire buffer too.
     updatedRegion = mVisibleRegion;
     mIsNewBuffer = false;
   } else {
     updatedRegion = aRegionToDraw;
   }
 
   NS_ASSERTION(mBuffer.BufferRect().Contains(aRegionToDraw.GetBounds()),
                "Update outside of buffer rect!");
--- a/gfx/layers/d3d10/ReadbackManagerD3D10.cpp
+++ b/gfx/layers/d3d10/ReadbackManagerD3D10.cpp
@@ -134,18 +134,18 @@ DWORD WINAPI StartTaskThread(void *aMana
 
   return 0;
 }
 
 ReadbackManagerD3D10::ReadbackManagerD3D10()
   : mRefCnt(0)
 {
   ::InitializeCriticalSection(&mTaskMutex);
-  mShutdownEvent = ::CreateEventA(NULL, FALSE, FALSE, "ReadbackShutdownEvent");
-  mTaskSemaphore = ::CreateSemaphoreA(NULL, 0, 1000000, "ReadbackTaskSemaphore");
+  mShutdownEvent = ::CreateEventA(NULL, FALSE, FALSE, NULL);
+  mTaskSemaphore = ::CreateSemaphoreA(NULL, 0, 1000000, NULL);
   mTaskThread = ::CreateThread(NULL, 0, StartTaskThread, this, 0, 0);
 }
 
 ReadbackManagerD3D10::~ReadbackManagerD3D10()
 {
   ::SetEvent(mShutdownEvent);
 
   // This shouldn't take longer than 5 seconds, if it does we're going to choose
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -413,33 +413,34 @@ gfxAndroidPlatform::AppendFacesFromFontF
         }
         FT_Done_Face(dummy);
         if (aFontCache && 0 == stat_ret)
             aFontCache->CacheFileInfo(fileName, faceList, timestamp, filesize, indexList);
     }
 }
 
 void
-gfxAndroidPlatform::FindFontsInDirectory(const char *aDirectory, FontNameCache* aFontCache)
+gfxAndroidPlatform::FindFontsInDirectory(const nsCString& aFontsDir,
+                                         FontNameCache* aFontCache)
 {
-    DIR *d = opendir(aDirectory);
+    DIR *d = opendir(aFontsDir.get());
     struct dirent *ent = NULL;
     while(d && (ent = readdir(d)) != NULL) {
         int namelen = strlen(ent->d_name);
         if (namelen > 4 &&
             strcasecmp(ent->d_name + namelen - 4, ".ttf") == 0)
         {
-            nsCString s(aDirectory);
-            s.Append("/fonts/");
+            nsCString s(aFontsDir);
             s.Append(nsDependentCString(ent->d_name));
 
             AppendFacesFromFontFile(nsPromiseFlatCString(s).get(),
                                     aFontCache, &mFontList);
         }
     }
+    closedir(d);
 }
 
 void
 gfxAndroidPlatform::GetFontList(InfallibleTArray<FontListEntry>* retValue)
 {
 #ifdef MOZ_IPC
     if (XRE_GetProcessType() != GeckoProcessType_Default) {
         mozilla::dom::ContentChild::GetSingleton()->SendReadFontList(retValue);
@@ -447,23 +448,26 @@ gfxAndroidPlatform::GetFontList(Infallib
     }
 #endif
 
     if (mFontList.Length() > 0) {
         *retValue = mFontList;
         return;
     }
 
-    // Check in both /system and $ANDROID_ROOT
+    // ANDROID_ROOT is the root of the android system, typically /system
+    // font files are in /$ANDROID_ROOT/fonts/
     FontNameCache fnc;
-    const char *systemDirectory = "/system";
-    FindFontsInDirectory(systemDirectory, &fnc);
+    FindFontsInDirectory(NS_LITERAL_CSTRING("/system/fonts/"), &fnc);
     char *androidRoot = PR_GetEnv("ANDROID_ROOT");
-    if (androidRoot && strcmp(androidRoot, systemDirectory))
-        FindFontsInDirectory(androidRoot, &fnc);
+    if (androidRoot && strcmp(androidRoot, "/system")) {
+        nsCString root(androidRoot);
+        root.Append("/fonts/");
+        FindFontsInDirectory(root, &fnc);
+    }
 
     *retValue = mFontList;
 }
 
 nsresult
 gfxAndroidPlatform::UpdateFontList()
 {
     gfxFontCache *fc = gfxFontCache::GetCache();
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -102,17 +102,17 @@ public:
     void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
 
     FT_Library GetFTLibrary();
 
     virtual gfxImageFormat GetOffscreenFormat() { return gfxASurface::ImageFormatRGB16_565; }
 
 protected:
     void AppendFacesFromFontFile(const char *aFileName, FontNameCache* aFontCache, InfallibleTArray<FontListEntry>* retValue);
-    void FindFontsInDirectory(const char *aDirectory, FontNameCache* aFontCache);
+    void FindFontsInDirectory(const nsCString& aFontsDir, FontNameCache* aFontCache);
 
     typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
 
     FontTable mFonts;
     FontTable mFontAliases;
     FontTable mFontSubstitutes;
     InfallibleTArray<FontListEntry> mFontList;
 
--- a/js/src/tests/ecma/Date/jstests.list
+++ b/js/src/tests/ecma/Date/jstests.list
@@ -114,26 +114,26 @@ script 15.9.5.24-3.js
 script 15.9.5.24-4.js
 script 15.9.5.24-5.js
 script 15.9.5.24-6.js
 script 15.9.5.24-7.js
 script 15.9.5.24-8.js
 script 15.9.5.25-1.js
 script 15.9.5.26-1.js
 script 15.9.5.27-1.js
-script 15.9.5.28-1.js
-script 15.9.5.29-1.js
+fails-if(Android) script 15.9.5.28-1.js
+fails-if(Android) script 15.9.5.29-1.js
 script 15.9.5.3-1-n.js
 script 15.9.5.3-2.js
 script 15.9.5.30-1.js
 script 15.9.5.31-1.js
 script 15.9.5.32-1.js
 script 15.9.5.33-1.js
 random-if(xulRuntime.OS=="Linux") script 15.9.5.34-1.js
-script 15.9.5.35-1.js
+fails-if(Android) script 15.9.5.35-1.js
 script 15.9.5.36-1.js
 script 15.9.5.36-2.js
 script 15.9.5.36-3.js
 script 15.9.5.36-4.js
 script 15.9.5.36-5.js
 script 15.9.5.36-6.js
 script 15.9.5.36-7.js
 script 15.9.5.37-1.js
--- a/js/src/tests/ecma/LexicalConventions/jstests.list
+++ b/js/src/tests/ecma/LexicalConventions/jstests.list
@@ -40,27 +40,27 @@ script 7.4.2-6-n.js
 script 7.4.2-7-n.js
 script 7.4.2-8-n.js
 script 7.4.2-9-n.js
 script 7.4.3-1-n.js
 script 7.4.3-10-n.js
 script 7.4.3-11-n.js
 script 7.4.3-12-n.js
 script 7.4.3-13-n.js
-script 7.4.3-14-n.js
-script 7.4.3-15-n.js
+fails-if(Android) script 7.4.3-14-n.js
+fails-if(Android) script 7.4.3-15-n.js
 script 7.4.3-16-n.js
 script 7.4.3-2-n.js
 skip script 7.4.3-3-n.js # obsolete test
-script 7.4.3-4-n.js
+fails-if(Android) script 7.4.3-4-n.js
 script 7.4.3-5-n.js
 script 7.4.3-6-n.js
-script 7.4.3-7-n.js
+fails-if(Android) script 7.4.3-7-n.js
 script 7.4.3-8-n.js
-script 7.4.3-9-n.js
+fails-if(Android) script 7.4.3-9-n.js
 script 7.5-1.js
 script 7.5-10-n.js
 script 7.5-2-n.js
 script 7.5-3-n.js
 script 7.5-4-n.js
 script 7.5-5-n.js
 script 7.5-6.js
 script 7.5-7.js
--- a/js/src/tests/ecma_2/Exceptions/jstests.list
+++ b/js/src/tests/ecma_2/Exceptions/jstests.list
@@ -42,27 +42,27 @@ script lexical-002.js
 script lexical-003.js
 script lexical-004.js
 script lexical-005.js
 script lexical-006.js
 script lexical-007.js
 script lexical-008.js
 script lexical-009.js
 skip script lexical-010.js # obsolete test
-script lexical-011.js
+fails-if(Android) script lexical-011.js
 script lexical-012.js
 script lexical-013.js
-script lexical-014.js
+fails-if(Android) script lexical-014.js
 script lexical-015.js
-script lexical-016.js
+fails-if(Android) script lexical-016.js
 script lexical-017.js
 script lexical-018.js
 script lexical-019.js
 script lexical-020.js
-script lexical-021.js
+fails-if(Android) script lexical-021.js
 skip script lexical-022.js # obsolete test
 script lexical-023.js
 script lexical-024.js
 script lexical-025.js
 script lexical-026.js
 script lexical-027.js
 script lexical-028.js
 script lexical-029.js
--- a/js/src/tests/ecma_2/LexicalConventions/jstests.list
+++ b/js/src/tests/ecma_2/LexicalConventions/jstests.list
@@ -1,4 +1,4 @@
 url-prefix ../../jsreftest.html?test=ecma_2/LexicalConventions/
-script keywords-001.js
+fails-if(Android) script keywords-001.js
 script regexp-literals-001.js
 script regexp-literals-002.js
--- a/js/src/tests/ecma_3/Object/jstests.list
+++ b/js/src/tests/ecma_3/Object/jstests.list
@@ -1,10 +1,10 @@
 url-prefix ../../jsreftest.html?test=ecma_3/Object/
-script 8.6.1-01.js
+fails-if(Android) script 8.6.1-01.js
 script 8.6.2.6-001.js
 fails script 8.6.2.6-002.js
 script class-001.js
 script class-002.js
 script class-003.js
 script class-004.js
 script class-005.js
 script regress-361274.js
--- a/js/src/tests/ecma_5/extensions/jstests.list
+++ b/js/src/tests/ecma_5/extensions/jstests.list
@@ -1,10 +1,10 @@
 url-prefix ../../jsreftest.html?test=ecma_5/extensions/
-script 8.12.5-01.js
+fails-if(Android) script 8.12.5-01.js
 script 15.4.4.11.js
 script Boolean-toSource.js
 script Number-toSource.js
 script Object-keys-and-object-ids.js
 script String-toSource.js
 script bug352085.js
 script bug472534.js
 script bug496985.js
--- a/js/src/tests/js1_5/Exceptions/jstests.list
+++ b/js/src/tests/js1_5/Exceptions/jstests.list
@@ -2,15 +2,15 @@ url-prefix ../../jsreftest.html?test=js1
 script catchguard-002-n.js
 script catchguard-003-n.js
 script errstack-001.js
 script regress-121658.js
 script regress-123002.js
 script regress-232182.js
 script regress-257751.js
 script regress-273931.js
-script regress-315147.js
+fails-if(Android) script regress-315147.js
 script regress-332472.js
 script regress-333728.js
 script regress-342359.js
 script regress-347674.js
 script regress-350650-n.js
 script regress-350837.js
--- a/js/src/tests/js1_5/Regress/jstests.list
+++ b/js/src/tests/js1_5/Regress/jstests.list
@@ -109,17 +109,17 @@ script regress-294191.js
 script regress-294195-01.js
 script regress-294195-02.js
 script regress-294302.js
 script regress-295052.js
 script regress-295666.js
 script regress-299209.js
 script regress-299641.js
 skip-if(!xulRuntime.shell) script regress-303213.js # bug 524731
-script regress-306633.js
+fails-if(Android) script regress-306633.js
 script regress-306727.js
 script regress-306794.js
 script regress-308085.js
 script regress-308566.js
 script regress-309242.js
 script regress-310295.js
 script regress-310607.js
 script regress-310993.js
@@ -129,28 +129,28 @@ script regress-312260.js
 script regress-31255.js
 script regress-312588.js
 random script regress-313967-01.js # BigO
 random script regress-313967-02.js # BigO
 skip-if(xulRuntime.OS=="WINNT"&&isDebugBuild) slow script regress-314401.js
 script regress-315974.js
 script regress-315990.js
 script regress-317476.js
-script regress-317533.js
+fails-if(Android) script regress-317533.js
 script regress-317714-01.js
 script regress-317714-02.js
 script regress-319384.js
 script regress-319391.js
 script regress-320032.js
 skip script regress-320119.js # obsolete test
 script regress-321757.js
 script regress-321874.js
 script regress-321971.js
 script regress-322430.js
-script regress-323314-1.js
+fails-if(Android) script regress-323314-1.js
 script regress-325925.js
 script regress-326453.js
 script regress-326467.js
 script regress-328012.js
 script regress-328664.js
 script regress-328897.js
 script regress-329383.js
 script regress-329530.js
@@ -182,17 +182,17 @@ script regress-350253.js
 script regress-350268.js
 script regress-350312.js
 script regress-350415.js
 script regress-350529.js
 skip script regress-350692.js # obsolete test
 skip-if(xulRuntime.OS=="Linux"&&!xulRuntime.shell&&!xulRuntime.XPCOMABI.match(/x86_64/)&&isDebugBuild) script regress-351116.js # bug 521549
 script regress-351515.js
 script regress-352009.js
-script regress-352197.js
+fails-if(Android) script regress-352197.js
 script regress-352208.js
 script regress-352604.js
 skip script regress-354924.js # obsolete test
 script regress-355341.js
 script regress-355344.js
 script regress-355556.js
 script regress-355829-01.js
 script regress-355829-02.js
--- a/js/src/tests/js1_5/extensions/jstests.list
+++ b/js/src/tests/js1_5/extensions/jstests.list
@@ -103,34 +103,34 @@ script regress-361552.js
 script regress-361558.js
 script regress-361571.js
 script regress-361856.js
 skip script regress-361964.js # slow, alert not dismissed, now busted by harness
 random script regress-363258.js # bug 524788
 script regress-363988.js
 slow script regress-365527.js
 script regress-365692.js
-script regress-365869.js
+fails-if(Android) script regress-365869.js
 script regress-366288.js
 script regress-366292.js
 script regress-366396.js
 script regress-367118-01.js
 script regress-367118-02.js
 script regress-367119-01.js
 script regress-367119-02.js
 script regress-367120-01.js
 script regress-367120-02.js
 script regress-367121.js
 script regress-367501-01.js
 script regress-367501-02.js
 script regress-367501-03.js
 script regress-367501-04.js
 skip-if(xulRuntime.OS=="WINNT"&&isDebugBuild) slow script regress-367589.js
 script regress-367630.js
-script regress-367923.js
+fails-if(Android) script regress-367923.js
 script regress-368859.js
 script regress-369404.js
 script regress-369696-01.js
 script regress-369696-02.js
 script regress-369696-03.js
 random-if(xulRuntime.OS=="WINNT") script regress-371636.js # bug 528284
 script regress-372309.js
 script regress-374589.js
@@ -215,11 +215,11 @@ script regress-481516.js
 script regress-488995.js
 script regress-50447-1.js
 skip script regress-50447.js # obsolete test
 script regress-90596-001.js
 script regress-90596-002.js
 script regress-96284-001.js
 script regress-96284-002.js
 script scope-001.js
-script toLocaleFormat-01.js
+fails-if(Android) script toLocaleFormat-01.js
 fails-if(xulRuntime.OS=="WINNT") script toLocaleFormat-02.js
 script regress-543839.js
--- a/js/src/tests/js1_7/block/jstests.list
+++ b/js/src/tests/js1_7/block/jstests.list
@@ -2,17 +2,17 @@ url-prefix ../../jsreftest.html?test=js1
 script order-of-operation.js
 script regress-341939.js
 script regress-343765.js
 script regress-344139.js
 script regress-344262.js
 script regress-344370.js
 script regress-344601.js
 script regress-345542.js
-script regress-347559.js
+fails-if(Android) script regress-347559.js
 script regress-348685.js
 script regress-349283.js
 script regress-349298.js
 script regress-349507.js
 script regress-349653.js
 script regress-349962.js
 script regress-350279.js
 script regress-350730.js
--- a/js/src/tests/js1_8_1/extensions/jstests.list
+++ b/js/src/tests/js1_8_1/extensions/jstests.list
@@ -7,9 +7,9 @@ script regress-452498-193.js
 script regress-452498-196.js
 script regress-452498-224.js
 script regress-466905-04.js
 skip script regress-466905-05.js  # no-op in browser, fails in shell - see bug 554793
 script regress-477158.js
 script regress-477187.js
 script regress-520572.js
 script new-parenthesization.js
-script strict-warning.js
+fails-if(Android) script strict-warning.js
--- a/js/src/tests/js1_8_1/strict/jstests.list
+++ b/js/src/tests/js1_8_1/strict/jstests.list
@@ -1,5 +1,5 @@
 url-prefix ../../jsreftest.html?test=js1_8_1/strict/
-script 8.7.2.js
-script 12.2.1.js
-script generator-eval-arguments.js
-script let-block-eval-arguments.js
+fails-if(Android) script 8.7.2.js
+fails-if(Android) script 12.2.1.js
+fails-if(Android) script generator-eval-arguments.js
+fails-if(Android) script let-block-eval-arguments.js
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -103,16 +103,32 @@ static void DestroyRegion(void* aPropert
  * is propagated to ContainerState in BuildContainerLayerFor, and then
  * the region(s) are actually invalidated in CreateOrRecycleThebesLayer.
  *
  * When the property value is null, the region is infinite --- i.e. all
  * areas of the ThebesLayers should be invalidated.
  */
 NS_DECLARE_FRAME_PROPERTY(ThebesLayerInvalidRegionProperty, DestroyRegion)
 
+static void DestroyPoint(void* aPropertyValue)
+{
+  delete static_cast<nsPoint*>(aPropertyValue);
+}
+
+/**
+ * The valid content in our child ThebesLayers is defined relative to
+ * the offset from this frame to its active scroll root, mapped back
+ * by the ThebesLayer's inverse transform.  Since we accumulate the
+ * region invalidated between last-paint and next-paint, and because
+ * the offset of this frame to its active root may change during that
+ * period, we save the offset at last-paint in this property and use
+ * it to invalidate at next-paint.
+ */
+NS_DECLARE_FRAME_PROPERTY(ThebesLayerLastPaintOffsetProperty, DestroyPoint)
+
 /**
  * This is a helper object used to build up the layer children for
  * a ContainerLayer.
  */
 class ContainerState {
 public:
   ContainerState(nsDisplayListBuilder* aBuilder,
                  LayerManager* aManager,
@@ -528,16 +544,45 @@ FrameLayerBuilder::WillEndTransaction(La
   // This also empties mNewDisplayItemData.
   mNewDisplayItemData.EnumerateEntries(StoreNewDisplayItemData, data);
   data->mInvalidateAllLayers = PR_FALSE;
 
   NS_ASSERTION(data->mFramesWithLayers.Count() > 0,
                "Some frame must have a layer!");
 }
 
+static void
+SetHasContainerLayer(nsIFrame* aFrame, nsPoint aOffsetToRoot)
+{
+  aFrame->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
+  for (nsIFrame* f = aFrame;
+       f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
+       f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
+    f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
+  }
+
+  FrameProperties props = aFrame->Properties();
+  nsPoint* lastPaintOffset = static_cast<nsPoint*>
+    (props.Get(ThebesLayerLastPaintOffsetProperty()));
+  if (lastPaintOffset) {
+    *lastPaintOffset = aOffsetToRoot;
+  } else {
+    props.Set(ThebesLayerLastPaintOffsetProperty(), new nsPoint(aOffsetToRoot));
+  }
+}
+
+static void
+SetNoContainerLayer(nsIFrame* aFrame)
+{
+  FrameProperties props = aFrame->Properties();
+  props.Delete(ThebesLayerInvalidRegionProperty());
+  props.Delete(ThebesLayerLastPaintOffsetProperty());
+  aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
+}
+
 /* static */ PLDHashOperator
 FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey<nsIFrame>* aEntry,
                                                  void* aUserArg)
 {
   FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>(aUserArg);
   nsIFrame* f = aEntry->GetKey();
   FrameProperties props = f->Properties();
   DisplayItemDataEntry* newDisplayItems =
@@ -550,36 +595,34 @@ FrameLayerBuilder::UpdateDisplayItemData
     // Pass PR_FALSE to not remove from mFramesWithLayers, we'll remove it
     // by returning PL_DHASH_REMOVE below.
     // Note that DestroyDisplayItemData would delete the user data
     // for the retained layer manager if it removed the last entry from
     // mFramesWithLayers, but we won't. That's OK because our caller
     // is DidEndTransaction, which would recreate the user data
     // anyway.
     InternalDestroyDisplayItemData(f, prop, PR_FALSE);
-    props.Delete(ThebesLayerInvalidRegionProperty());
-    f->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
+    SetNoContainerLayer(f);
     return PL_DHASH_REMOVE;
   }
 
   if (newDisplayItems->HasContainerLayer()) {
     // Reset or create the invalid region now so we can start collecting
     // new dirty areas.
     // Note that the NS_FRAME_HAS_CONTAINER_LAYER bit is set in
     // BuildContainerLayerFor, so we don't need to set it here.
     nsRegion* invalidRegion = static_cast<nsRegion*>
       (props.Get(ThebesLayerInvalidRegionProperty()));
     if (invalidRegion) {
       invalidRegion->SetEmpty();
     } else {
       props.Set(ThebesLayerInvalidRegionProperty(), new nsRegion());
     }
   } else {
-    props.Delete(ThebesLayerInvalidRegionProperty());
-    f->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
+    SetNoContainerLayer(f);
   }
 
   // We need to remove and re-add the DisplayItemDataProperty in
   // case the nsTArray changes the value of its mHdr.
   void* propValue = props.Remove(DisplayItemDataProperty());
   NS_ASSERTION(propValue, "mFramesWithLayers out of sync");
   PR_STATIC_ASSERT(sizeof(nsTArray<DisplayItemData>) == sizeof(void*));
   nsTArray<DisplayItemData>* array =
@@ -1500,27 +1543,16 @@ ContainerState::Finish(PRUint32* aTextCo
     }
     // If non-null, 'layer' is now in the right place in the list, so we
     // can just move on to the next one.
   }
 
   *aTextContentFlags = textContentFlags;
 }
 
-static void
-SetHasContainerLayer(nsIFrame* aFrame)
-{
-  aFrame->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
-  for (nsIFrame* f = aFrame;
-       f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
-       f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
-  }
-}
-
 already_AddRefed<ContainerLayer>
 FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
                                           LayerManager* aManager,
                                           nsIFrame* aContainerFrame,
                                           nsDisplayItem* aContainerItem,
                                           const nsDisplayList& aChildren)
 {
   FrameProperties props = aContainerFrame->Properties();
@@ -1561,34 +1593,38 @@ FrameLayerBuilder::BuildContainerLayerFo
 
   if (aManager == mRetainingManager) {
     DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(aContainerFrame);
     if (entry) {
       entry->mData.AppendElement(
           DisplayItemData(containerLayer, containerDisplayItemKey));
     }
 
+    nsPoint* offsetAtLastPaint = static_cast<nsPoint*>
+      (props.Get(ThebesLayerLastPaintOffsetProperty()));
+    nsPoint currentOffset = aBuilder->ToReferenceFrame(aContainerFrame);
+
     nsRegion* invalidThebesContent(static_cast<nsRegion*>
       (props.Get(ThebesLayerInvalidRegionProperty())));
     if (invalidThebesContent) {
-      nsPoint offset = aBuilder->ToReferenceFrame(aContainerFrame);
+      nsPoint offset = offsetAtLastPaint ? *offsetAtLastPaint : currentOffset;
       invalidThebesContent->MoveBy(offset);
       state.SetInvalidThebesContent(invalidThebesContent->
         ToOutsidePixels(appUnitsPerDevPixel));
       // We have to preserve the current contents of invalidThebesContent
       // because there might be multiple container layers for the same
       // frame and we need to invalidate the ThebesLayer children of all
       // of them.
       invalidThebesContent->MoveBy(-offset);
     } else {
       // The region was deleted to indicate that everything should be
       // invalidated.
       state.SetInvalidateAllThebesContent();
     }
-    SetHasContainerLayer(aContainerFrame);
+    SetHasContainerLayer(aContainerFrame, currentOffset);
   }
 
   Clip clip;
   state.ProcessDisplayItems(aChildren, clip);
 
   // Set CONTENT_COMPONENT_ALPHA if any of our children have it.
   // This is suboptimal ... a child could have text that's over transparent
   // pixels in its own layer, but over opaque parts of previous siblings.
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -295,17 +295,17 @@ private:
 #pragma mark ** DocumentViewerImpl **
 #endif
 
 //-------------------------------------------------------------
 class DocumentViewerImpl : public nsIDocumentViewer,
                            public nsIContentViewer_MOZILLA_2_0_BRANCH,
                            public nsIContentViewerEdit,
                            public nsIContentViewerFile,
-                           public nsIMarkupDocumentViewer,
+                           public nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH,
                            public nsIDocumentViewerPrint
 
 #ifdef NS_PRINTING
                            , public nsIWebBrowserPrint
 #endif
 
 {
   friend class nsDocViewerSelectionListener;
@@ -340,16 +340,19 @@ public:
   NS_DECL_NSICONTENTVIEWEREDIT
 
   // nsIContentViewerFile
   NS_DECL_NSICONTENTVIEWERFILE
 
   // nsIMarkupDocumentViewer
   NS_DECL_NSIMARKUPDOCUMENTVIEWER
 
+  // nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH
+  NS_DECL_NSIMARKUPDOCUMENTVIEWER_MOZILLA_2_0_BRANCH
+
 #ifdef NS_PRINTING
   // nsIWebBrowserPrint
   NS_DECL_NSIWEBBROWSERPRINT
 #endif
 
   typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer,
                                 void* aClosure);
   void CallChildren(CallChildFunc aFunc, void* aClosure);
@@ -457,16 +460,17 @@ protected:
   PRBool mAttachedToParent; // view is attached to the parent widget
 
   nsIntRect mBounds;
 
   // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
   // presshell only.
   float mTextZoom;      // Text zoom, defaults to 1.0
   float mPageZoom;
+  int mMinFontSize;
 
   PRInt16 mNumURLStarts;
   PRInt16 mDestroyRefCount;    // a second "refcount" for the document viewer's "destroy"
 
   unsigned      mStopped : 1;
   unsigned      mLoaded : 1;
   unsigned      mDeferredWindowClose : 1;
   // document management data
@@ -557,17 +561,17 @@ void DocumentViewerImpl::PrepareToStartL
   mDebugFile = nsnull;
 #endif
 
 #endif // NS_PRINTING
 }
 
 // Note: operator new zeros our memory, so no need to init things to null.
 DocumentViewerImpl::DocumentViewerImpl()
-  : mTextZoom(1.0), mPageZoom(1.0),
+  : mTextZoom(1.0), mPageZoom(1.0), mMinFontSize(0),
     mIsSticky(PR_TRUE),
 #ifdef NS_PRINT_PREVIEW
     mPrintPreviewZoom(1.0),
 #endif
     mHintCharsetSource(kCharsetUninitialized),
     mInitializedForPrintPreview(PR_FALSE),
     mHidden(PR_FALSE)
 {
@@ -576,16 +580,17 @@ DocumentViewerImpl::DocumentViewerImpl()
 
 NS_IMPL_ADDREF(DocumentViewerImpl)
 NS_IMPL_RELEASE(DocumentViewerImpl)
 
 NS_INTERFACE_MAP_BEGIN(DocumentViewerImpl)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewer)
     NS_INTERFACE_MAP_ENTRY(nsIDocumentViewer)
     NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer)
+    NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit)
     NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentViewer)
 #ifdef NS_PRINTING
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint)
 #endif
     NS_INTERFACE_MAP_ENTRY(nsIContentViewer_MOZILLA_2_0_BRANCH)
@@ -749,16 +754,17 @@ DocumentViewerImpl::InitPresentationStuf
 
   // Initialize our view manager
   nscoord width = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * mBounds.width;
   nscoord height = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * mBounds.height;
 
   mViewManager->SetWindowDimensions(width, height);
   mPresContext->SetTextZoom(mTextZoom);
   mPresContext->SetFullZoom(mPageZoom);
+  mPresContext->SetMinFontSize(mMinFontSize);
 
   if (aDoInitialReflow) {
     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
     if (htmlDoc) {
       nsCOMPtr<nsIDOMHTMLFrameSetElement> frameset =
         do_QueryInterface(mDocument->GetRootElement());
       htmlDoc->SetIsFrameset(frameset != nsnull);
     }
@@ -2745,16 +2751,25 @@ struct ZoomInfo
 static void
 SetChildTextZoom(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
   aChild->SetTextZoom(ZoomInfo->mZoom);
 }
 
 static void
+SetChildMinFontSize(nsIMarkupDocumentViewer* aChild, void* aClosure)
+{
+  nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> branch =
+    do_QueryInterface(aChild);
+  struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
+  branch->SetMinFontSize(ZoomInfo->mZoom);
+}
+
+static void
 SetChildFullZoom(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   struct ZoomInfo* ZoomInfo = (struct ZoomInfo*) aClosure;
   aChild->SetFullZoom(ZoomInfo->mZoom);
 }
 
 static PRBool
 SetExtResourceTextZoom(nsIDocument* aDocument, void* aClosure)
@@ -2768,16 +2783,31 @@ SetExtResourceTextZoom(nsIDocument* aDoc
       ctxt->SetTextZoom(ZoomInfo->mZoom);
     }
   }
 
   return PR_TRUE;
 }
 
 static PRBool
+SetExtResourceMinFontSize(nsIDocument* aDocument, void* aClosure)
+{
+  nsIPresShell* shell = aDocument->GetShell();
+  if (shell) {
+    nsPresContext* ctxt = shell->GetPresContext();
+    if (ctxt) {
+      struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
+      ctxt->SetMinFontSize(ZoomInfo->mZoom);
+    }
+  }
+
+  return PR_TRUE;
+}
+
+static PRBool
 SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure)
 {
   // Would it be better to enumerate external resource viewers instead?
   nsIPresShell* shell = aDocument->GetShell();
   if (shell) {
     nsPresContext* ctxt = shell->GetPresContext();
     if (ctxt) {
       struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
@@ -2825,16 +2855,57 @@ DocumentViewerImpl::GetTextZoom(float* a
 {
   NS_ENSURE_ARG_POINTER(aTextZoom);
   nsPresContext* pc = GetPresContext();
   *aTextZoom = pc ? pc->TextZoom() : 1.0f;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+DocumentViewerImpl::SetMinFontSize(PRInt32 aMinFontSize)
+{
+  if (GetIsPrintPreview()) {
+    return NS_OK;
+  }
+
+  mMinFontSize = aMinFontSize;
+
+  nsIViewManager::UpdateViewBatch batch(GetViewManager());
+      
+  // Set the min font on all children of mContainer (even if our min font didn't
+  // change, our children's min font may be different, though it would be unusual).
+  // Do this first, in case kids are auto-sizing and post reflow commands on
+  // our presshell (which should be subsumed into our own style change reflow).
+  struct ZoomInfo ZoomInfo = { aMinFontSize };
+  CallChildren(SetChildMinFontSize, &ZoomInfo);
+
+  // Now change our own min font
+  nsPresContext* pc = GetPresContext();
+  if (pc && aMinFontSize != mPresContext->MinFontSize()) {
+    pc->SetMinFontSize(aMinFontSize);
+  }
+
+  // And do the external resources
+  mDocument->EnumerateExternalResources(SetExtResourceMinFontSize, &ZoomInfo);
+
+  batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
+  
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DocumentViewerImpl::GetMinFontSize(PRInt32* aMinFontSize)
+{
+  NS_ENSURE_ARG_POINTER(aMinFontSize);
+  nsPresContext* pc = GetPresContext();
+  *aMinFontSize = pc ? pc->MinFontSize() : 0;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 DocumentViewerImpl::SetFullZoom(float aFullZoom)
 {
 #ifdef NS_PRINT_PREVIEW
   if (GetIsPrintPreview()) {
     nsPresContext* pc = GetPresContext();
     NS_ENSURE_TRUE(pc, NS_OK);
     nsCOMPtr<nsIPresShell> shell = pc->GetPresShell();
     NS_ENSURE_TRUE(shell, NS_OK);
@@ -4187,16 +4258,17 @@ DocumentViewerImpl::ReturnToGalleyPresen
   mPrintEngine->Destroy();
   mPrintEngine = nsnull;
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
   ResetFocusState(docShell);
 
   SetTextZoom(mTextZoom);
   SetFullZoom(mPageZoom);
+  SetMinFontSize(mMinFontSize);
   Show();
 
 #endif // NS_PRINTING && NS_PRINT_PREVIEW
 }
 
 //------------------------------------------------------------
 // Reset ESM focus for all descendent doc shells.
 static void
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -181,17 +181,17 @@ destroy_loads(const void * aKey, nsRefPt
 static NS_DEFINE_CID(kLookAndFeelCID,  NS_LOOKANDFEEL_CID);
 #include "nsContentCID.h"
 
   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
   : mType(aType), mDocument(aDocument), mTextZoom(1.0), mFullZoom(1.0),
-    mPageSize(-1, -1), mPPScale(1.0f),
+    mPageSize(-1, -1), mPPScale(1.0f), mMinFontSize(0),
     mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
     mImageAnimationModePref(imgIContainer::kNormalAnimMode),
     // Font sizes default to zero; they will be set in GetFontPreferences
     mDefaultVariableFont("serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
                          NS_FONT_WEIGHT_NORMAL, NS_FONT_STRETCH_NORMAL, 0, 0),
     mDefaultFixedFont("monospace", NS_FONT_STYLE_NORMAL,
                       NS_FONT_VARIANT_NORMAL, NS_FONT_WEIGHT_NORMAL,
                       NS_FONT_STRETCH_NORMAL, 0, 0),
@@ -479,20 +479,20 @@ nsPresContext::GetFontPreferences()
 
   // get font.minimum-size.[langGroup]
 
   pref.Assign("font.minimum-size.");
   pref.Append(langGroup);
 
   PRInt32 size = nsContentUtils::GetIntPref(pref.get());
   if (unit == eUnit_px) {
-    mMinimumFontSize = CSSPixelsToAppUnits(size);
+    mMinimumFontSizePref = CSSPixelsToAppUnits(size);
   }
   else if (unit == eUnit_pt) {
-    mMinimumFontSize = CSSPointsToAppUnits(size);
+    mMinimumFontSizePref = CSSPointsToAppUnits(size);
   }
 
   // get attributes specific to each generic font
   nsCAutoString generic_dot_langGroup;
   for (PRInt32 eType = eDefaultFont_Variable; eType < eDefaultFont_COUNT; ++eType) {
     generic_dot_langGroup.Assign(kGenericFont[eType]);
     generic_dot_langGroup.Append(langGroup);
 
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -367,17 +367,17 @@ public:
   /** Get a cached integer pref, by its type */
   // *  - initially created for bugs 30910, 61883, 74186, 84398
   PRInt32 GetCachedIntPref(nsPresContext_CachedIntPrefType aPrefType) const
   {
     // If called with a constant parameter, the compiler should optimize
     // this switch statement away.
     switch (aPrefType) {
     case kPresContext_MinimumFontSize:
-      return mMinimumFontSize;
+      return mMinimumFontSizePref;
     case kPresContext_ScrollbarSide:
       return mPrefScrollbarSide;
     case kPresContext_BidiDirection:
       return mPrefBidiDirection;
     default:
       NS_ERROR("invalid arg passed to GetCachedIntPref");
     }
 
@@ -551,16 +551,33 @@ public:
     if (HasCachedStyleData()) {
       // Media queries could have changed since we changed the meaning
       // of 'em' units in them.
       MediaFeatureValuesChanged(PR_TRUE);
       RebuildAllStyleData(NS_STYLE_HINT_REFLOW);
     }
   }
 
+  PRInt32 MinFontSize() const {
+    return NS_MAX(mMinFontSize, mMinimumFontSizePref);
+  }
+
+  void SetMinFontSize(PRInt32 aMinFontSize) {
+    if (aMinFontSize == mMinFontSize)
+      return;
+
+    mMinFontSize = aMinFontSize;
+    if (HasCachedStyleData()) {
+      // Media queries could have changed since we changed the meaning
+      // of 'em' units in them.
+      MediaFeatureValuesChanged(PR_TRUE);
+      RebuildAllStyleData(NS_STYLE_HINT_REFLOW);
+    }
+  }
+
   float GetFullZoom() { return mFullZoom; }
   void SetFullZoom(float aZoom);
 
   nscoord GetAutoQualityMinFontSize() {
     return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
   }
   
   static PRInt32 AppUnitsPerCSSPixel() { return nsIDeviceContext::AppUnitsPerCSSPixel(); }
@@ -1049,16 +1066,17 @@ protected:
   // charset rather than explicitly specified as a lang attribute).
   nsIAtom*              mLanguage;      // [STRONG]
 
   nsRefPtrHashtable<nsVoidPtrHashKey, nsImageLoader>
                         mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
 
   nsWeakPtr             mContainer;
 
+  PRInt32               mMinFontSize;   // Min font size, defaults to 0
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
 
   PRInt32               mCurAppUnitsPerDevPixel;
   PRInt32               mAutoQualityMinFontSizePixelsPref;
 
 #ifdef IBMBIDI
   nsAutoPtr<nsBidiPresUtils> mBidiUtils;
@@ -1074,17 +1092,17 @@ protected:
   nsInvalidateRequestList mInvalidateRequests;
 
   // container for per-context fonts (downloadable, SVG, etc.)
   nsUserFontSet*        mUserFontSet;
   // The list of @font-face rules that we put into mUserFontSet
   nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
   
   PRInt32               mFontScaler;
-  nscoord               mMinimumFontSize;
+  nscoord               mMinimumFontSizePref;
 
   nsRect                mVisibleArea;
   nsSize                mPageSize;
   float                 mPageScale;
   float                 mPPScale;
 
   nscolor               mDefaultColor;
   nscolor               mBackgroundColor;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6057,31 +6057,21 @@ void PresShell::SetRenderingState(const 
   if (UsingDisplayPort()) {
     mDisplayPort = aState.mDisplayPort;
   } else {
     mDisplayPort = nsRect();
   }
   mXResolution = aState.mXResolution;
   mYResolution = aState.mYResolution;
 
-  // FIXME (Bug 593243 should fix this.)
-  //
-  // Invalidated content does not pay any attention to the displayport, so
-  // invalidating the subdocument's root frame could end up not repainting
-  // visible content.
-  //
-  // For instance, imagine the iframe is located at y=1000. Even though the
-  // displayport may intersect the iframe's viewport, the visual overflow
-  // rect of the root content could be (0, 0, 800, 500). Since the dirty region
-  // does not intersect the visible overflow rect, the display list for the
-  // iframe will not even be generated.
-  //
-  // Here, we find the very top presShell and use its root frame for
-  // invalidation instead.
-  //
+  nsIView* rootView;
+  if (NS_SUCCEEDED(mViewManager->GetRootView(rootView)) && rootView) {
+    rootView->SetInvalidationDimensions(&mDisplayPort);
+  }
+
   nsPresContext* rootPresContext = mPresContext->GetRootPresContext();
   if (rootPresContext) {
     nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
     nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
     if (rootFrame) {
       rootFrame->InvalidateWithFlags(rootFrame->GetVisualOverflowRectRelativeToSelf(),
                                      nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
     }
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -277,17 +277,17 @@ load 473894-1.html
 load 476241-1.html
 load 477731-1.html
 load 477928.html
 load 478131-1.html
 load 478170-1.html
 load 478185-1.html
 asserts(1) load 479938-1.html # Bug 575011
 load 480345-1.html
-load 481921.html
+skip-if(Android) load 481921.html
 load 489462-1.html
 load 489480-1.xhtml
 load 493111-1.html
 load 493118-1.html
 load 494300-1.xul
 load 494332-1.html
 load 495875-1.html
 load 495875-2.html
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -190,17 +190,25 @@ nsHTMLScrollFrame::InvalidateInternal(co
                                       nscoord aX, nscoord aY, nsIFrame* aForChild,
                                       PRUint32 aFlags)
 {
   if (aForChild) {
     if (aForChild == mInner.mScrolledFrame) {
       nsRect damage = aDamageRect + nsPoint(aX, aY);
       // This is the damage rect that we're going to pass up to our parent.
       nsRect parentDamage;
-      parentDamage.IntersectRect(damage, mInner.mScrollPort);
+      nsIPresShell* presShell = PresContext()->PresShell();
+      // If we're using a displayport, we might be displaying an area
+      // different than our scroll port and the damage needs to be
+      // clipped to that instead.
+      if (mInner.mIsRoot && presShell->UsingDisplayPort()) {
+        parentDamage.IntersectRect(damage, presShell->GetDisplayPort());
+      } else {
+        parentDamage.IntersectRect(damage, mInner.mScrollPort);
+      }
 
       if (IsScrollingActive()) {
         // This is the damage rect that we're going to pass up and
         // only request invalidation of ThebesLayers for.
         // damage is now in our coordinate system, which means it was
         // translated using the current scroll position. Adjust it to
         // reflect the scroll position at last paint, since that's what
         // the ThebesLayers are currently set up for.
@@ -1099,17 +1107,25 @@ void
 nsXULScrollFrame::InvalidateInternal(const nsRect& aDamageRect,
                                      nscoord aX, nscoord aY, nsIFrame* aForChild,
                                      PRUint32 aFlags)
 {
   if (aForChild == mInner.mScrolledFrame) {
     nsRect damage = aDamageRect + nsPoint(aX, aY);
     // This is the damage rect that we're going to pass up to our parent.
     nsRect parentDamage;
-    parentDamage.IntersectRect(damage, mInner.mScrollPort);
+    nsIPresShell* presShell = PresContext()->PresShell();
+    // If we're using a displayport, we might be displaying an area
+    // different than our scroll port and the damage needs to be
+    // clipped to that instead.
+    if (mInner.mIsRoot && presShell->UsingDisplayPort()) {
+      parentDamage.IntersectRect(damage, presShell->GetDisplayPort());
+    } else {
+      parentDamage.IntersectRect(damage, mInner.mScrollPort);
+    }
 
     if (IsScrollingActive()) {
       // This is the damage rect that we're going to pass up and
       // only request invalidation of ThebesLayers for.
       // damage is now in our coordinate system, which means it was
       // translated using the current scroll position. Adjust it to
       // reflect the scroll position at last paint, since that's what
       // the ThebesLayers are currently set up for.
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -5852,16 +5852,19 @@ void nsPluginInstanceOwner::Paint(const 
       DoCocoaEventDrawRect(aDirtyRect, cgContext);
     }
     pluginWidget->EndDrawPlugin();
   }
 }
 
 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
 {
+  if (!mInstance || !mObjectFrame)
+    return;
+ 
   // The context given here is only valid during the HandleEvent call.
   NPCocoaEvent updateEvent;
   InitializeNPCocoaEvent(&updateEvent);
   updateEvent.type = NPCocoaEventDrawRect;
   updateEvent.data.draw.context = cgContext;
   updateEvent.data.draw.x = aDrawRect.X();
   updateEvent.data.draw.y = aDrawRect.Y();
   updateEvent.data.draw.width = aDrawRect.Width();
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -498,21 +498,22 @@ nsPrintEngine::DoCommonPrint(PRBool     
   NS_ENSURE_SUCCESS(rv, rv);
 
   mPrt->mPrintSettings->SetIsCancelled(PR_FALSE);
   mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit);
 
   if (aIsPrintPreview) {
     SetIsCreatingPrintPreview(PR_TRUE);
     SetIsPrintPreview(PR_TRUE);
-    nsCOMPtr<nsIMarkupDocumentViewer> viewer =
+    nsCOMPtr<nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH> viewer =
       do_QueryInterface(mDocViewerPrint);
     if (viewer) {
       viewer->SetTextZoom(1.0f);
       viewer->SetFullZoom(1.0f);
+      viewer->SetMinFontSize(0);
     }
   } else {
     SetIsPrinting(PR_TRUE);
   }
 
   // Create a print session and let the print settings know about it.
   // The print settings hold an nsWeakPtr to the session so it does not
   // need to be cleared from the settings at the end of the job.
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/593243-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<body style="width: 600px; height: 400px;">
+  <div style="position: absolute; left: 0px; top: 0px;
+              width=600px height=600px">
+    <div style="position: absolute; left: 0px; top: 0px;
+                width: 600px; height: 400px;
+                background-color: green;"></div>
+    <div style="position: absolute; left: 300px; top: 400px;
+                width: 100px; height: 100px;
+                background-color: red;"></div>
+    <div style="position: absolute; left: 0px; top: 500px;
+                width: 600px; height: 100px;
+                background-color: yellow;"></div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/593243-1.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"
+      reftest-viewport-w="600" reftest-viewport-h="400"
+      reftest-displayport-w="800" reftest-displayport-h="1000"
+      reftest-no-sync-layers>
+<head>
+  <title></title>
+<script type="text/javascript">
+function initialPaint() {
+  window.removeEventListener("MozAfterPaint", initialPaint, false);
+  setTimeout(moveBox, 0);
+}
+
+function moveBox() {
+  var box = document.getElementById("box");
+  box.style.left = "300px";
+  window.addEventListener("MozAfterPaint", repaint, false);
+}
+
+function repaint() {
+  window.removeEventListener("MozAfterPaint", repaint, false);
+  setTimeout(finish, 0);
+}
+
+function finish() {
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozAfterPaint", initialPaint, false);
+</script>
+</head>
+
+<body style="width: 600px; height: 400px;">
+  <div style="position: absolute; left: 0px; top: 0px;
+              width=600px height=600px">
+    <div style="position: absolute; left: 0px; top: 0px;
+                width: 600px; height: 400px;
+                background-color: green;"></div>
+    <div id="box"
+         style="position: absolute; left: 0px; top: 400px;
+                width: 100px; height: 100px;
+                background-color: red;"></div>
+    <div style="position: absolute; left: 0px; top: 500px;
+                width: 600px; height: 100px;
+                background-color: yellow;"></div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/593243-2-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<body style="width: 600px; height: 400px;">
+  <div style="position: absolute; left: 0px; top: 0px;
+              width=600px height=600px">
+    <div style="position: absolute; left: 0px; top: 0px;
+                width: 600px; height: 400px;
+                background-color: green;"></div>
+    <div style="position: absolute; left: 0px; top: 400px;
+                width: 100px; height: 100px;">
+      <input type="text" id="input" size="20" style="border: none;" value="Hello kitty"></input>
+    </div>
+    <div style="position: absolute; left: 0px; top: 500px;
+                width: 600px; height: 100px;
+                background-color: yellow;"></div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/593243-2.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"
+      reftest-viewport-w="600" reftest-viewport-h="400"
+      reftest-displayport-w="800" reftest-displayport-h="1000"
+      reftest-no-sync-layers>
+<head>
+  <title></title>
+<script type="text/javascript">
+function initialPaint() {
+  window.removeEventListener("MozAfterPaint", initialPaint, false);
+  setTimeout(type, 0);
+}
+
+function type() {
+  var box = document.getElementById("input");
+  box.value = "Hello kitty";
+  window.addEventListener("MozAfterPaint", repaint, false);
+}
+
+function repaint() {
+  window.removeEventListener("MozAfterPaint", repaint, false);
+  setTimeout(finish, 0);
+}
+
+function finish() {
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozAfterPaint", initialPaint, false);
+</script>
+</head>
+
+<body style="width: 600px; height: 400px;">
+  <div style="position: absolute; left: 0px; top: 0px;
+              width=600px height=600px">
+    <div style="position: absolute; left: 0px; top: 0px;
+                width: 600px; height: 400px;
+                background-color: green;"></div>
+    <div style="position: absolute; left: 0px; top: 400px;
+                width: 100px; height: 100px;">
+      <input type="text" id="input" size="20" style="border: none;"></input>
+    </div>
+    <div style="position: absolute; left: 0px; top: 500px;
+                width: 600px; height: 100px;
+                background-color: yellow;"></div>
+  </div>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1558,16 +1558,18 @@ asserts(0-1) == 582146-1.html about:blan
 == 584400-dash-length.svg 584400-dash-length-ref.svg
 == 584699-1.html 584699-1-ref.html
 == 585598-2.xhtml 585598-2-ref.xhtml
 == 586400-1.html 586400-1-ref.html
 fails-if(cocoaWidget) == 586683-1.html 586683-1-ref.html
 == 589615-1a.xhtml 589615-1-ref.html
 == 589615-1b.html 589615-1-ref.html
 == 589672-1.html 589672-1-ref.html
+skip-if(!browserIsRemote) == 593243-1.html 593243-1-ref.html # bug 593168
+skip-if(!browserIsRemote) == 593243-2.html 593243-2-ref.html # bug 593168
 == 593544-1.html 593544-1-ref.html
 == 594333-1.html 594333-1-ref.html
 == 594624-1.html 594624-1-ref.html
 == 594737-1.html 594737-1-ref.html
 == 597721-1.html 597721-1-ref.html
 needs-focus == 598726-1.html 598726-1-ref.html
 == 599113-1.html 599113-1-ref.html
 fails-if(!haveTestPlugin) == 599476.html 599476-ref.html
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2170,18 +2170,17 @@ nsRuleNode::WalkRuleTree(const nsStyleSt
 const void*
 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext)
 {
   switch (aSID) {
     case eStyleStruct_Font:
     {
       nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext);
       if (NS_LIKELY(fontData != nsnull)) {
-        nscoord minimumFontSize =
-          mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
+        nscoord minimumFontSize = mPresContext->MinFontSize();
 
         if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
           fontData->mFont.size = NS_MAX(fontData->mSize, minimumFontSize);
         }
         else {
           fontData->mFont.size = fontData->mSize;
         }
         aContext->SetStyle(eStyleStruct_Font, fontData);
@@ -3270,18 +3269,17 @@ nsRuleNode::ComputeFontData(void* aStart
   // walk further up the tree.  So this means that when the font struct
   // is fully specified using *longhand* properties (excluding
   // -moz-system-font), we won't cache in the rule tree even though we
   // could.  However, it's pretty unlikely authors will do that
   // (although there is a pretty good chance they'll fully specify it
   // using the 'font' shorthand).
 
   // See if there is a minimum font-size constraint to honor
-  nscoord minimumFontSize =
-    mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
+  nscoord minimumFontSize = mPresContext->MinFontSize();
 
   if (minimumFontSize < 0)
     minimumFontSize = 0;
 
   PRBool useDocumentFonts =
     mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
 
   // See if we are in the chrome
@@ -3492,18 +3490,17 @@ nsRuleNode::ComputeTextData(void* aStart
   else {
     SetCoord(textData.mLineHeight, text->mLineHeight, parentText->mLineHeight,
              SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL,
              aContext, mPresContext, canStoreInRuleTree);
     if (textData.mLineHeight.IsLengthUnit() &&
         !textData.mLineHeight.IsRelativeLengthUnit()) {
       nscoord lh = nsStyleFont::ZoomText(mPresContext,
                                          text->mLineHeight.GetCoordValue());
-      nscoord minimumFontSize =
-        mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
+      nscoord minimumFontSize = mPresContext->MinFontSize();
 
       if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
         // If we applied a minimum font size, scale the line height by
         // the same ratio.  (If we *might* have applied a minimum font
         // size, we can't cache in the rule tree.)
         canStoreInRuleTree = PR_FALSE;
         const nsStyleFont *font = aContext->GetStyleFont();
         if (font->mSize != 0) {
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -396,16 +396,17 @@ function BuildConditionSandbox(aURL) {
     }
 
     if (gWindowUtils && gWindowUtils.layerManagerType != "Basic")
       sandbox.layersGPUAccelerated = true;
     else
       sandbox.layersGPUAccelerated = false;
  
     // Shortcuts for widget toolkits.
+    sandbox.Android = xr.OS == "Android";
     sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
     sandbox.gtk2Widget = xr.widgetToolkit == "gtk2";
     sandbox.qtWidget = xr.widgetToolkit == "qt";
     sandbox.winWidget = xr.widgetToolkit == "windows";
 
     var hh = CC[NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX + "http"].
                  getService(CI.nsIHttpProtocolHandler);
     sandbox.http = { __exposedProps__: {} };
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -297,17 +297,17 @@ class RemoteReftest(RefTest):
         self.server.ensureReady(self.SERVER_STARTUP_TIMEOUT)
         options.xrePath = remoteXrePath
         options.utilityPath = remoteUtilityPath
          
     def stopWebServer(self, options):
         self.server.stop()
 
     def createReftestProfile(self, options, profileDir):
-        RefTest.createReftestProfile(self, options, profileDir)
+        RefTest.createReftestProfile(self, options, profileDir, server=options.remoteWebServer)
 
         if (self._devicemanager.pushDir(profileDir, options.remoteProfile) == None):
             raise devicemanager.FileError("Failed to copy profiledir to device")
 
     def copyExtraFilesToProfile(self, options, profileDir):
         RefTest.copyExtraFilesToProfile(self, options, profileDir)
         if (self._devicemanager.pushDir(profileDir, options.remoteProfile) == None):
             raise devicemanager.FileError("Failed to copy extra files to device") 
@@ -370,17 +370,17 @@ def main():
     automation.setRemoteProfile(options.remoteProfile)
     automation.setRemoteLog(options.remoteLogFile)
     reftest = RemoteReftest(automation, dm, options, SCRIPT_DIRECTORY)
 
     # Start the webserver
     reftest.startWebServer(options)
 
     # Hack in a symbolic link for jsreftest
-    os.system("ln -s ../jsreftest jsreftest")
+    os.system("ln -s ../jsreftest " + str(os.path.join(SCRIPT_DIRECTORY, "jsreftest")))
 
     # Dynamically build the reftest URL if possible, beware that args[0] should exist 'inside' the webroot
     manifest = args[0]
     if os.path.exists(os.path.join(SCRIPT_DIRECTORY, args[0])):
         manifest = "http://" + str(options.remoteWebServer) + ":" + str(options.httpPort) + "/" + args[0]
     elif os.path.exists(args[0]):
         manifestPath = os.path.abspath(args[0]).split(SCRIPT_DIRECTORY)[1].strip('/')
         manifest = "http://" + str(options.remoteWebServer) + ":" + str(options.httpPort) + "/" + manifestPath
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -60,21 +60,21 @@ class RefTest(object):
   def getFullPath(self, path):
     "Get an absolute path relative to self.oldcwd."
     return os.path.normpath(os.path.join(self.oldcwd, os.path.expanduser(path)))
 
   def getManifestPath(self, path):
     "Get the path of the manifest, and for remote testing this function is subclassed to point to remote manifest"
     return self.getFullPath(path)
 
-  def createReftestProfile(self, options, profileDir):
+  def createReftestProfile(self, options, profileDir, server='localhost'):
     "Sets up a profile for reftest."
 
     self.automation.setupPermissionsDatabase(profileDir,
-      {'allowXULXBL': [('localhost', True), ('<file>', True)]})
+      {'allowXULXBL': [(server, True), ('<file>', True)]})
 
     # Set preferences for communication between our command line arguments
     # and the reftest harness.  Preferences that are required for reftest
     # to work should instead be set in reftest-cmdline.js .
     prefsFile = open(os.path.join(profileDir, "user.js"), "w")
     prefsFile.write('user_pref("reftest.timeout", %d);\n' % (options.timeout * 1000))
 
     if options.totalChunks != None:
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -169,16 +169,27 @@ public:
    * are in appunits of this.
    * The view's bounds (x,y) might not be the same as the view's position,
    * if the view has content above or to the left of its origin.
    * @param aBounds out parameter for bounds
    */
   nsRect GetBounds() const { return mDimBounds; }
 
   /**
+   * Set the dimensions at which invalidations are clipped, which can
+   * be different than |GetDimensions()|.  |aRect| is relative to
+   * |this|.  It can be null, in which case invalidations return to
+   * being clipped to the view dimensions.
+   *
+   * The caller is responsible for invalidating the area that may lie
+   * outside the view dimensions but inside |aRect| after this call.
+   */
+  void SetInvalidationDimensions(const nsRect* aRect);
+
+  /**
    * Get the offset between the coordinate systems of |this| and aOther.
    * Adding the return value to a point in the coordinate system of |this|
    * will transform the point to the coordinate system of aOther.
    *
    * The offset is expressed in appunits of |this|. So if you are getting the
    * offset between views in different documents that might have different
    * appunits per devpixel ratios you need to be careful how you use the
    * result.
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -204,16 +204,17 @@ nsView::nsView(nsViewManager* aViewManag
   // Views should be transparent by default. Not being transparent is
   // a promise that the view will paint all its pixels opaquely. Views
   // should make this promise explicitly by calling
   // SetViewContentTransparency.
   mVFlags = 0;
   mViewManager = aViewManager;
   mDirtyRegion = nsnull;
   mDeletionObserver = nsnull;
+  mHaveInvalidationDimensions = PR_FALSE;
   mWidgetIsTopLevel = PR_FALSE;
 }
 
 void nsView::DropMouseGrabbing()
 {
   nsCOMPtr<nsIViewObserver> viewObserver = mViewManager->GetViewObserver();
   if (viewObserver) {
     viewObserver->ClearMouseCapture(this);
@@ -345,16 +346,21 @@ void nsView::SetPosition(nscoord aX, nsc
   mPosY = aY;
 
   NS_ASSERTION(GetParent() || (aX == 0 && aY == 0),
                "Don't try to move the root widget to something non-zero");
 
   ResetWidgetBounds(PR_TRUE, PR_TRUE, PR_FALSE);
 }
 
+void nsIView::SetInvalidationDimensions(const nsRect* aRect)
+{
+  return Impl()->SetInvalidationDimensions(aRect);
+}
+
 void nsView::SetPositionIgnoringChildWidgets(nscoord aX, nscoord aY)
 {
   mDimBounds.x += aX - mPosX;
   mDimBounds.y += aY - mPosY;
   mPosX = aX;
   mPosY = aY;
 
   ResetWidgetBounds(PR_FALSE, PR_TRUE, PR_FALSE);
@@ -490,16 +496,23 @@ void nsView::SetDimensions(const nsRect&
 
   mDimBounds = dims;
 
   if (aResizeWidget) {
     ResetWidgetBounds(PR_FALSE, PR_FALSE, aPaint);
   }
 }
 
+void nsView::SetInvalidationDimensions(const nsRect* aRect)
+{
+  if ((mHaveInvalidationDimensions = !!aRect)) {
+    mInvalidationDimensions = *aRect;
+  }
+}
+
 void nsView::NotifyEffectiveVisibilityChanged(PRBool aEffectivelyVisible)
 {
   if (!aEffectivelyVisible)
   {
     DropMouseGrabbing();
   }
 
   if (nsnull != mWindow)
--- a/view/src/nsView.h
+++ b/view/src/nsView.h
@@ -71,16 +71,17 @@ public:
   /**
    * Called to indicate that the dimensions of the view have been changed.
    * The x and y coordinates may be < 0, indicating that the view extends above
    * or to the left of its origin position. The term 'dimensions' indicates it
    * is relative to this view.
    */
   virtual void SetDimensions(const nsRect &aRect, PRBool aPaint = PR_TRUE,
                              PRBool aResizeWidget = PR_TRUE);
+  void SetInvalidationDimensions(const nsRect* aRect);
   void GetDimensions(nsRect &aRect) const { aRect = mDimBounds; aRect.x -= mPosX; aRect.y -= mPosY; }
   void GetDimensions(nsSize &aSize) const { aSize.width = mDimBounds.width; aSize.height = mDimBounds.height; }
 
   /**
    * Called to indicate that the visibility of a view has been
    * changed.
    * @param visibility new visibility state
    */
@@ -143,16 +144,21 @@ public:
   nsViewManager* GetViewManager() const { return mViewManager; }
   // These are superseded by a better interface in nsIView
   PRInt32 GetZIndex() const { return mZIndex; }
   PRBool GetZIndexIsAuto() const { return (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; }
   // This is a better interface than GetDimensions(nsRect&) above
   nsRect GetDimensions() const { nsRect r = mDimBounds; r.MoveBy(-mPosX, -mPosY); return r; }
   // Same as GetBounds but converts to parent appunits if they are different.
   nsRect GetBoundsInParentUnits() const;
+
+  nsRect GetInvalidationDimensions() const {
+    return mHaveInvalidationDimensions ? mInvalidationDimensions : GetDimensions();
+  }
+
   // These are defined exactly the same in nsIView, but for now they have to be redeclared
   // here because of stupid C++ method hiding rules
 
   PRBool HasNonEmptyDirtyRegion() {
     return mDirtyRegion && !mDirtyRegion->IsEmpty();
   }
   nsRegion* GetDirtyRegion() {
     if (!mDirtyRegion) {
@@ -197,14 +203,21 @@ public:
   nsIWidget* GetNearestWidget(nsPoint* aOffset, const PRInt32 aAPD) const;
 
 protected:
   // Do the actual work of ResetWidgetBounds, unconditionally.  Don't
   // call this method if we have no widget.
   void DoResetWidgetBounds(PRBool aMoveOnly, PRBool aInvalidateChangedSize);
 
   nsRegion*    mDirtyRegion;
+  // invalidations are clipped to mInvalidationDimensions, not
+  // GetDimensions(), when mHaveInvalidationDimensions is true.  This
+  // is used to support persistent "displayport" rendering; see
+  // nsPresShell.cpp.  The coordinates of mInvalidationDimensions are
+  // relative to |this|.
+  nsRect       mInvalidationDimensions;
+  PRPackedBool mHaveInvalidationDimensions;
 
 private:
   void InitializeWindow(PRBool aEnableDragDrop, PRBool aResetVisibility);
 };
 
 #endif
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -566,17 +566,17 @@ nsViewManager::UpdateWidgetArea(nsView *
     return;
     // this should only happen at the top level, and this result
     // should not be consumed by top-level callers, so it doesn't
     // really matter what we return
   }
 
   // If the bounds don't overlap at all, there's nothing to do
   nsRegion intersection;
-  intersection.And(aWidgetView->GetDimensions(), aDamagedRegion);
+  intersection.And(aWidgetView->GetInvalidationDimensions(), aDamagedRegion);
   if (intersection.IsEmpty()) {
     return;
   }
 
   // If the widget is hidden, it don't cover nothing
   if (aWidget) {
     PRBool visible;
     aWidget->IsVisible(visible);
@@ -1618,17 +1618,17 @@ NS_IMETHODIMP nsViewManager::ForceUpdate
   return NS_OK;
 }
 
 nsIntRect nsViewManager::ViewToWidget(nsView *aView, const nsRect &aRect) const
 {
   NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
 
   // intersect aRect with bounds of aView, to prevent generating any illegal rectangles.
-  nsRect bounds = aView->GetDimensions();
+  nsRect bounds = aView->GetInvalidationDimensions();
   nsRect rect;
   rect.IntersectRect(aRect, bounds);
 
   // account for the view's origin not lining up with the widget's
   rect += aView->ViewToWidgetOffset();
 
   // finally, convert to device coordinates.
   return rect.ToOutsidePixels(AppUnitsPerDevPixel());
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -518,17 +518,16 @@ nsWindow::IsEnabled(PRBool *aState)
     *aState = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Invalidate(const nsIntRect &aRect,
                      PRBool aIsSynchronous)
 {
-    ALOG("nsWindow::Invalidate %p [%d %d %d %d]", (void*) this, aRect.x, aRect.y, aRect.width, aRect.height);
     nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Update()
 {
     return NS_OK;
@@ -896,18 +895,16 @@ nsWindow::DrawTo(gfxASurface *targetSurf
 
         if (mChildren[i]->mBounds.Contains(boundsRect)) {
             coveringChildIndex = PRInt32(i);
         }
     }
 
     // If we have no covering child, then we need to render this.
     if (coveringChildIndex == -1) {
-        ALOG("nsWindow[%p]::DrawTo no covering child, drawing this", (void*) this);
-
         nsPaintEvent event(PR_TRUE, NS_PAINT, this);
         event.region = boundsRect;
         switch (GetLayerManager(nsnull)->GetBackendType()) {
             case LayerManager::LAYERS_BASIC: {
                 nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
 
                 {
                     AutoLayerManagerSetup
@@ -945,17 +942,16 @@ nsWindow::DrawTo(gfxASurface *targetSurf
     }
 
     gfxPoint offset;
 
     if (targetSurface)
         offset = targetSurface->GetDeviceOffset();
 
     for (PRUint32 i = coveringChildIndex; i < mChildren.Length(); ++i) {
-        ALOG("nsWindow[%p]::DrawTo child[%d]", (void*) this, i);
         if (mChildren[i]->mBounds.IsEmpty() ||
             !mChildren[i]->mBounds.Intersects(boundsRect)) {
             continue;
         }
 
         if (targetSurface)
             targetSurface->SetDeviceOffset(offset + gfxPoint(mChildren[i]->mBounds.x,
                                                              mChildren[i]->mBounds.y));
@@ -965,26 +961,22 @@ nsWindow::DrawTo(gfxASurface *targetSurf
         if (!ok) {
             ALOG("nsWindow[%p]::DrawTo child %d[%p] returned FALSE!", (void*) this, i, (void*)mChildren[i]);
         }
     }
 
     if (targetSurface)
         targetSurface->SetDeviceOffset(offset);
 
-    ALOG("nsWindow[%p]::DrawTo done", (void*) this);
-
     return PR_TRUE;
 }
 
 void
 nsWindow::OnDraw(AndroidGeckoEvent *ae)
 {
-    ALOG(">> OnDraw");
-
     if (!IsTopLevel()) {
         ALOG("##### redraw for window %p, which is not a toplevel window -- sending to toplevel!", (void*) this);
         DumpWindows();
         return;
     }
 
     if (!mIsVisible) {
         ALOG("##### redraw for window %p, which is not visible -- ignoring!", (void*) this);