Bug 687972 - backing out changesets b17ab862bbc1 and a6db0c6c94a3 r=orange
authorBrad Lassey <blassey@mozilla.com>
Wed, 30 Nov 2011 22:59:00 -0500
changeset 82702 ac1fff73e20116a87620a5c0b89b31865fe5bb8b
parent 82701 43e18ca6cc8c874aebf48228aec3e1d73c4cef75
child 82703 399ccb34b69b0807e36a87656ea84c67dd699192
push idunknown
push userunknown
push dateunknown
reviewersorange
bugs687972
milestone11.0a1
Bug 687972 - backing out changesets b17ab862bbc1 and a6db0c6c94a3 r=orange
content/base/public/nsIFrameLoader.idl
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/media/nsBuiltinDecoder.cpp
content/media/test/test_timeupdate_small_files.html
layout/base/nsPresShell.cpp
layout/base/tests/chrome/Makefile.in
layout/base/tests/chrome/no_clip_iframe_subdoc.html
layout/base/tests/chrome/no_clip_iframe_window.xul
layout/base/tests/chrome/test_no_clip_iframe.xul
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIFrame.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/generic/nsViewportFrame.cpp
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -136,17 +136,17 @@ interface nsIContentViewManager : nsISup
                          [retval, array, size_is(aLength)] out nsIContentView aResult);
 
   /**
    * The root content view.
    */
   readonly attribute nsIContentView rootContentView;
 };
 
-[scriptable, uuid(efc0b731-45dc-4189-8ffa-d3eeeb850977)]
+[scriptable, uuid(12905a29-4246-475a-81d4-fc389197df02)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -253,23 +253,16 @@ interface nsIFrameLoader : nsISupports
 
   /**
    * With this event mode, it's the application's responsability to 
    * convert and forward events to the content process
    */
   const unsigned long EVENT_MODE_DONT_FORWARD_TO_CHILD = 0x00000001;
 
   attribute unsigned long eventMode;
-
-  /**
-   * If false, then the subdocument is not clipped to its CSS viewport, and the
-   * subdocument's viewport scrollbar(s) are not rendered.
-   * Defaults to true.
-   */
-  attribute boolean clipSubdocument;
 };
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
 [scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
 interface nsIFrameLoaderOwner : nsISupports
 {
   /**
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -138,22 +138,24 @@ public:
     if (base_win) {
       base_win->Destroy();
     }
     return NS_OK;
   }
   nsRefPtr<nsIDocShell> mDocShell;
 };
 
-static void InvalidateFrame(nsIFrame* aFrame, PRUint32 aFlags)
+static void InvalidateFrame(nsIFrame* aFrame)
 {
-  if (!aFrame)
-    return;
   nsRect rect = nsRect(nsPoint(0, 0), aFrame->GetRect().Size());
-  aFrame->InvalidateWithFlags(rect, aFlags);
+  // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
+  // semantics the same for both in-process and out-of-process
+  // <browser>.  This is just a transform of the layer subtree in
+  // both.
+  aFrame->InvalidateWithFlags(rect, nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
 }
 
 NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
 
 bool
 nsContentView::IsRoot() const
 {
   return mScrollId == FrameMetrics::ROOT_SCROLL_ID;
@@ -182,21 +184,18 @@ nsContentView::Update(const ViewConfig& 
   }
 
   if (RenderFrameParent* rfp = mFrameLoader->GetCurrentRemoteFrame()) {
     rfp->ContentViewScaleChanged(this);
   }
 
   // XXX could be clever here and compute a smaller invalidation
   // rect
-  // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
-  // semantics the same for both in-process and out-of-process
-  // <browser>.  This is just a transform of the layer subtree in
-  // both.
-  InvalidateFrame(mFrameLoader->GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
+  nsIFrame* frame = mFrameLoader->GetPrimaryFrameOfOwningContent();
+  InvalidateFrame(frame);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentView::ScrollTo(float aXpx, float aYpx)
 {
   ViewConfig config(mConfig);
   config.mScrollOffset = nsPoint(nsPresContext::CSSPixelsToAppUnits(aXpx),
@@ -324,17 +323,16 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mNeedsAsyncDestroy(false)
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mDelayRemoteDialogs(false)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
-  , mClipSubdocument(true)
   , mCurrentRemoteFrame(nsnull)
   , mRemoteBrowser(nsnull)
   , mRenderMode(RENDER_MODE_DEFAULT)
   , mEventMode(EVENT_MODE_NORMAL_DISPATCH)
 {
 }
 
 nsFrameLoader*
@@ -1690,21 +1688,17 @@ nsFrameLoader::GetRenderMode(PRUint32* a
 NS_IMETHODIMP
 nsFrameLoader::SetRenderMode(PRUint32 aRenderMode)
 {
   if (aRenderMode == mRenderMode) {
     return NS_OK;
   }
 
   mRenderMode = aRenderMode;
-  // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
-  // semantics the same for both in-process and out-of-process
-  // <browser>.  This is just a transform of the layer subtree in
-  // both.
-  InvalidateFrame(GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
+  InvalidateFrame(GetPrimaryFrameOfOwningContent());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::GetEventMode(PRUint32* aEventMode)
 {
   *aEventMode = mEventMode;
   return NS_OK;
@@ -1712,48 +1706,16 @@ nsFrameLoader::GetEventMode(PRUint32* aE
 
 NS_IMETHODIMP
 nsFrameLoader::SetEventMode(PRUint32 aEventMode)
 {
   mEventMode = aEventMode;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsFrameLoader::GetClipSubdocument(bool* aResult)
-{
-  *aResult = mClipSubdocument;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFrameLoader::SetClipSubdocument(bool aClip)
-{
-  mClipSubdocument = aClip;
-  nsIFrame* frame = GetPrimaryFrameOfOwningContent();
-  if (frame) {
-    InvalidateFrame(frame, 0);
-    frame->PresContext()->PresShell()->
-      FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
-    nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
-    if (subdocFrame) {
-      nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
-      if (subdocRootFrame) {
-        nsIFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
-          GetRootScrollFrame();
-        if (subdocRootScrollFrame) {
-          frame->PresContext()->PresShell()->
-            FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
-        }
-      }
-    }
-  }
-  return NS_OK;
-}
-
 nsIntSize
 nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame)
 {
   nsSize docSizeAppUnits;
   nsPresContext* presContext = aIFrame->PresContext();
   nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = 
     do_QueryInterface(aIFrame->GetContent());
   if (frameElem) {
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -282,18 +282,16 @@ public:
   {
     mCurrentRemoteFrame = aFrame;
   }
   nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
 
   mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
-  bool ShouldClipSubdocument() { return mClipSubdocument; }
-
 private:
 
   bool ShouldUseRemoteProcess();
 
   /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
    * initialize mDocShell.
    */
@@ -335,19 +333,17 @@ private:
   bool mHideCalled : 1;
   // True when the object is created for an element which the parser has
   // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
   // it may lose the flag.
   bool mNetworkCreated : 1;
 
   bool mDelayRemoteDialogs : 1;
   bool mRemoteBrowserShown : 1;
-  bool mRemoteFrame : 1;
-  bool mClipSubdocument : 1;
-
+  bool mRemoteFrame;
   // XXX leaking
   nsCOMPtr<nsIObserver> mChildHost;
   RenderFrameParent* mCurrentRemoteFrame;
   TabParent* mRemoteBrowser;
 
   // See nsIFrameLoader.idl.  Short story, if !(mRenderMode &
   // RENDER_MODE_ASYNC_SCROLL), all the fields below are ignored in
   // favor of what content tells.
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -639,17 +639,19 @@ void nsBuiltinDecoder::UpdatePlaybackRat
   mStream->SetPlaybackRate(rate);
 }
 
 void nsBuiltinDecoder::NotifySuspendedStatusChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (!mStream)
     return;
-  if (mStream->IsSuspendedByCache() && mElement) {
+  bool suspended = mStream->IsSuspendedByCache();
+  printf("*** nsBuiltinDecoder::NotifySuspendedStatusChanged(%p), suspended=%d\n", this, suspended);
+  if (suspended && mElement) {
     // if this is an autoplay element, we need to kick off its autoplaying
     // now so we consume data and hopefully free up cache space
     mElement->NotifyAutoplayDataReady();
   }
 }
 
 void nsBuiltinDecoder::NotifyBytesDownloaded()
 {
--- a/content/media/test/test_timeupdate_small_files.html
+++ b/content/media/test/test_timeupdate_small_files.html
@@ -41,29 +41,39 @@ function ended(e) {
       v.removeEventListener("ended", ended, false);
       v.removeEventListener("timeupdate", timeupdate, false);
       v.parentNode.removeChild(v);
       manager.finished(v.token);
     },
     500);
 }
 
+var eventsToLog = ["play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
+  "loadeddata", "playing", "progress", "timeupdate", "ended", "suspend", "error", "stalled", "emptied", "abort",
+  "waiting", "pause"];
+function logEvent(event) {
+  ok(true, event.target.currentSrc + " got " + event.type);
+}
+
 function startTest(test, token) {
   var type = /^video/.test(test.type) ? "video" : "audio";
   var v = document.createElement(type);
   v.token = token;
   manager.started(token);
   v.src = test.name;
   v._name = test.name;
   v._timeupdateCount = 0;
   v._finished = false;
   v.gotEnded = false;
   v.autoplay = true;
   v.addEventListener("ended", ended, false);
   v.addEventListener("timeupdate", timeupdate, false);
+  for (var i = 0; i < eventsToLog.length; ++i) {
+    v.addEventListener(eventsToLog[i], logEvent, false);
+  }
   document.body.appendChild(v);
 }
 
 manager.runTests(gSmallTests, startTest);
 
 </script>
 </pre>
 </body>
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -7290,24 +7290,24 @@ PresShell::DoReflow(nsIFrame* target, bo
   // root frame, then its desired size had better not change!  If it's
   // initiated at the root, then the size better not change unless its
   // height was unconstrained to start with.
   NS_ASSERTION((target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) ||
                (desiredSize.width == size.width &&
                 desiredSize.height == size.height),
                "non-root frame's desired size changed during an "
                "incremental reflow");
-  NS_ASSERTION(target == rootFrame || desiredSize.VisualOverflow().IsEqualInterior(
+  NS_ASSERTION(desiredSize.VisualOverflow().IsEqualInterior(
                  nsRect(nsPoint(0, 0),
                         nsSize(desiredSize.width, desiredSize.height))),
-               "non-root reflow roots must not have visible overflow");
-  NS_ASSERTION(target == rootFrame || desiredSize.ScrollableOverflow().IsEqualEdges(
+               "reflow roots must not have visible overflow");
+  NS_ASSERTION(desiredSize.ScrollableOverflow().IsEqualEdges(
                  nsRect(nsPoint(0, 0),
                         nsSize(desiredSize.width, desiredSize.height))),
-               "non-root reflow roots must not have scrollable overflow");
+               "reflow roots must not have scrollable overflow");
   NS_ASSERTION(status == NS_FRAME_COMPLETE,
                "reflow roots should never split");
 
   target->SetSize(nsSize(desiredSize.width, desiredSize.height));
 
   nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, target,
                                              target->GetView(),
                                              desiredSize.VisualOverflow());
--- a/layout/base/tests/chrome/Makefile.in
+++ b/layout/base/tests/chrome/Makefile.in
@@ -57,19 +57,16 @@ include $(topsrcdir)/config/rules.mk
 	bug551434_childframe.html \
 	test_chrome_content_integration.xul \
 	     chrome_content_integration_window.xul \
 	test_chrome_over_plugin.xul \
 	     chrome_over_plugin_window.xul \
 	test_default_background.xul \
 	     default_background_window.xul \
     test_leaf_layers_partition_browser_window.xul \
-    test_no_clip_iframe.xul \
-         no_clip_iframe_window.xul \
-         no_clip_iframe_subdoc.html \
 	test_printpreview.xul \
 	     printpreview_helper.xul \
 	test_printpreview_bug396024.xul \
 	     printpreview_bug396024_helper.xul \
 	test_printpreview_bug482976.xul \
 	     printpreview_bug482976_helper.xul \
     $(NULL)
 
deleted file mode 100644
--- a/layout/base/tests/chrome/no_clip_iframe_subdoc.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body style="margin:0; background:lime;">
-<div id="d" style="position:relative; top:-50px; width:150px; height:250px; background:yellow;"></div>
-<div id="p" style="margin-top:-50px; width:150px; height:50px;"></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/base/tests/chrome/no_clip_iframe_window.xul
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="runTests()">
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-
-  <div id="container" xmlns="http://www.w3.org/1999/xhtml" style="height:400px; overflow:auto; background:gray">
-    <div style="height:0">
-      <iframe type="content" id="f" src="no_clip_iframe_subdoc.html"
-       style="margin-top:50px; border:1px solid black; width:100px; height:100px;"/>
-    </div>
-    <div id="ref" style="background:gray;">
-      <div style="border:1px solid black; margin-top:50px; width:100px; height:100px;">
-        <div id="ref-d" style="background:lime; height:250px; width:150px;">
-          <div style="position:relative; top:-50px; width:150px; height:100%; background:yellow;"/>
-        </div>
-      </div>
-    </div>
-  </div>
-  <vbox flex="1"/>
-
-  <script type="application/javascript">
-  <![CDATA[
-    var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
-    for each (var name in imports) {
-      window[name] = window.opener.wrappedJSObject[name];
-    }
-
-    SimpleTest.waitForExplicitFinish();
-
-    var accumulatedRect = null;
-    var onpaint = function() {};
-
-    function paintListener(event) {
-      if (event.target != window)
-        return;
-      dump("got MozAfterPaint: " + event.boundingClientRect.left + "," + event.boundingClientRect.top + "," +
-           event.boundingClientRect.right + "," + event.boundingClientRect.bottom + "\n");
-      if (accumulatedRect) {
-        accumulatedRect[0] = Math.min(accumulatedRect[0], event.boundingClientRect.left);
-        accumulatedRect[1] = Math.min(accumulatedRect[1], event.boundingClientRect.top);
-        accumulatedRect[2] = Math.max(accumulatedRect[2], event.boundingClientRect.right);
-        accumulatedRect[3] = Math.max(accumulatedRect[3], event.boundingClientRect.bottom);
-      } else {
-        accumulatedRect = [event.boundingClientRect.left, event.boundingClientRect.top,
-                           event.boundingClientRect.right, event.boundingClientRect.bottom];
-      }
-      onpaint();
-    }
-    window.addEventListener("MozAfterPaint", paintListener, false);
-
-    function waitForAllPaintsFlushed(callback) {
-      document.documentElement.getBoundingClientRect();
-      var CI = Components.interfaces;
-      var utils = window.QueryInterface(CI.nsIInterfaceRequestor)
-                  .getInterface(CI.nsIDOMWindowUtils);
-      if (!utils.isMozAfterPaintPending) {
-        dump("done...\n");
-        var result = accumulatedRect;
-        accumulatedRect = null;
-        onpaint = function() {};
-        if (!result) {
-          result = [0,0,0,0];
-        }
-        callback(result[0], result[1], result[2], result[3]);
-        return;
-      }
-      dump("waiting for paint...\n");
-      onpaint = function() { waitForAllPaintsFlushed(callback); };
-    }
-
-    var Ci = Components.interfaces;
-    var frame = document.getElementById("f");
-    var fl = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
-    is(fl.clipSubdocument, true, "clipSubdocument should default to true");
-    fl.clipSubdocument = false;
-    is(fl.clipSubdocument, false, "clipSubdocument should have been set to false");
-
-    function runTests() {
-      var ref = document.getElementById("ref");
-      frame.contentWindow.scrollTo(0,0);
-
-      ref.style.visibility = "hidden";
-      var testCanvas = snapshotWindow(window);
-      ref.style.visibility = "";
-      var refCanvas = snapshotWindow(window);
-      var comparison = compareSnapshots(testCanvas, refCanvas, true);
-      ok(comparison[0], "Basic overflow drawing; got " + comparison[1] + ", expected " + comparison[2]);
-
-      document.getElementById("container").style.height = "200px";
-      ref.style.visibility = "hidden";
-      testCanvas = snapshotWindow(window);
-      ref.style.visibility = "";
-      refCanvas = snapshotWindow(window);
-      comparison = compareSnapshots(testCanvas, refCanvas, true);
-      ok(comparison[0], "Drawing with vertical scrollbar to show overflow area computation; got " +
-                        comparison[1] + ", expected " + comparison[2]);
-
-      frame.contentDocument.getElementById("d").style.height = "350px";
-      document.getElementById("ref-d").style.height = "350px";
-      ref.style.visibility = "hidden";
-      testCanvas = snapshotWindow(window);
-      ref.style.visibility = "";
-      refCanvas = snapshotWindow(window);
-      comparison = compareSnapshots(testCanvas, refCanvas, true);
-      ok(comparison[0], "testing dynamic overflow area change affecting scrollbar; got " +
-                        comparison[1] + ", expected " + comparison[2]);
-
-      // Now do invalidation tests
-      ref.style.visibility = "hidden";
-      document.getElementById("container").style.height = "400px";
-      waitForAllPaintsFlushed(function() {
-        dump("Scrolling\n");
-        frame.contentWindow.scrollTo(0,80);
-        waitForAllPaintsFlushed(function(x1, y1, x2, y2) {
-          ok(x1 <= 1 && x2 >= 151 && y1 <= 0 && y2 >= 400,
-             "Entire scrolled region is painted: " + x1 + "," + y1 + "," + x2 + "," + y2);
-          frame.contentDocument.getElementById("p").style.background = "cyan";
-          waitForAllPaintsFlushed(function(x1, y1, x2, y2) {
-            ok(x1 <= 1 && x2 >= 151 && y1 <= 271 && y2 >= 320,
-               "Entire updated region is painted: " + x1 + "," + y1 + "," + x2 + "," + y2);
-      
-            var tester = window.SimpleTest;
-            window.close();
-            tester.finish();
-          });
-        });
-      });
-    }
-  ]]>
-  </script>
-</window>
deleted file mode 100644
--- a/layout/base/tests/chrome/test_no_clip_iframe.xul
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
-  <!-- test results are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml">
-  </body>
-
-  <!-- test code goes here -->
-  <script type="application/javascript">
-  <![CDATA[
-    SimpleTest.waitForExplicitFinish();
-    // Run the test in a separate window so that the test runs as a chrome
-    // window
-    window.open("no_clip_iframe_window.xul", "no_clip_iframe",
-                "chrome,width=200,height=400");
-  ]]>
-  </script>
-</window>
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6434,27 +6434,23 @@ nsFrame::CreateAccessible()
 {
   return nsnull;
 }
 #endif
 
 NS_DECLARE_FRAME_PROPERTY(OverflowAreasProperty,
                           nsIFrame::DestroyOverflowAreas)
 
-bool
+void
 nsIFrame::ClearOverflowRects()
 {
-  if (mOverflow.mType == NS_FRAME_OVERFLOW_NONE) {
-    return false;
-  }
   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
     Properties().Delete(OverflowAreasProperty());
   }
   mOverflow.mType = NS_FRAME_OVERFLOW_NONE;
-  return true;
 }
 
 /** Create or retrieve the previously stored overflow area, if the frame does 
  * not overflow and no creation is required return nsnull.
  * @return pointer to the overflow area rectangle 
  */
 nsOverflowAreas*
 nsIFrame::GetOverflowAreasProperty()
@@ -6472,28 +6468,27 @@ nsIFrame::GetOverflowAreasProperty()
   overflow = new nsOverflowAreas;
   props.Set(OverflowAreasProperty(), overflow);
   return overflow;
 }
 
 /** Set the overflowArea rect, storing it as deltas or a separate rect
  * depending on its size in relation to the primary frame rect.
  */
-bool
+void
 nsIFrame::SetOverflowAreas(const nsOverflowAreas& aOverflowAreas)
 {
   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
     nsOverflowAreas *overflow =
       static_cast<nsOverflowAreas*>(Properties().Get(OverflowAreasProperty()));
-    bool changed = *overflow != aOverflowAreas;
     *overflow = aOverflowAreas;
 
     // Don't bother with converting to the deltas form if we already
     // have a property.
-    return changed;
+    return;
   }
 
   const nsRect& vis = aOverflowAreas.VisualOverflow();
   PRUint32 l = -vis.x, // left edge: positive delta is leftwards
            t = -vis.y, // top: positive is upwards
            r = vis.XMost() - mRect.width, // right: positive is rightwards
            b = vis.YMost() - mRect.height; // bottom: positive is downwards
   if (aOverflowAreas.ScrollableOverflow().IsEqualEdges(nsRect(nsPoint(0, 0), GetSize())) &&
@@ -6505,48 +6500,41 @@ nsIFrame::SetOverflowAreas(const nsOverf
       // set a frame as having no overflow in this function.  This is
       // because FinishAndStoreOverflow calls this function prior to
       // SetRect based on whether the overflow areas match aNewSize.
       // In the case where the overflow areas exactly match mRect but
       // do not match aNewSize, we need to store overflow in a property
       // so that our eventual SetRect/SetSize will know that it has to
       // reset our overflow areas.
       (l | t | r | b) != 0) {
-    VisualDeltas oldDeltas = mOverflow.mVisualDeltas;
     // It's a "small" overflow area so we store the deltas for each edge
     // directly in the frame, rather than allocating a separate rect.
     // If they're all zero, that's fine; we're setting things to
     // no-overflow.
     mOverflow.mVisualDeltas.mLeft   = l;
     mOverflow.mVisualDeltas.mTop    = t;
     mOverflow.mVisualDeltas.mRight  = r;
     mOverflow.mVisualDeltas.mBottom = b;
-    // There was no scrollable overflow before, and there isn't now.
-    return oldDeltas != mOverflow.mVisualDeltas;
   } else {
-    bool changed = !aOverflowAreas.ScrollableOverflow().IsEqualEdges(nsRect(nsPoint(0, 0), GetSize())) ||
-      !aOverflowAreas.VisualOverflow().IsEqualEdges(GetVisualOverflowFromDeltas());
-
     // it's a large overflow area that we need to store as a property
     mOverflow.mType = NS_FRAME_OVERFLOW_LARGE;
     nsOverflowAreas* overflow = GetOverflowAreasProperty();
     NS_ASSERTION(overflow, "should have created areas");
     *overflow = aOverflowAreas;
-    return changed;
   }
 }
 
 inline bool
 IsInlineFrame(nsIFrame *aFrame)
 {
   nsIAtom *type = aFrame->GetType();
   return type == nsGkAtoms::inlineFrame;
 }
 
-bool
+void 
 nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                                  nsSize aNewSize)
 {
   nsRect bounds(nsPoint(0, 0), aNewSize);
   // Store the passed in overflow area if we are a preserve-3d frame,
   // and it's not just the frame bounds.
   if (Preserves3D() && (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
                         !aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
@@ -6645,21 +6633,21 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
     }
     if (Preserves3DChildren()) {
       ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
     }
   }
 
   bool visualOverflowChanged =
     !GetVisualOverflowRect().IsEqualInterior(aOverflowAreas.VisualOverflow());
-  bool anyOverflowChanged;
+
   if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
-    anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
+    SetOverflowAreas(aOverflowAreas);
   } else {
-    anyOverflowChanged = ClearOverflowRects();
+    ClearOverflowRects();
   }
 
   if (visualOverflowChanged) {
     if (hasOutlineOrEffects) {
       // When there's an outline or box-shadow or SVG effects,
       // changes to those styles might require repainting of the old and new
       // overflow areas. Repainting of the old overflow area is handled in
       // nsCSSFrameConstructor::DoApplyRenderingChangeToTree in response
@@ -6694,18 +6682,16 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
       // If there is no transform now, then the container layer for
       // the transform will go away and the frame contents will change
       // ThebesLayers, forcing it to be invalidated, so it doesn't matter
       // that we didn't reach here.
       InvalidateLayer(aOverflowAreas.VisualOverflow(),
                       nsDisplayItem::TYPE_TRANSFORM);
     }
   }
-
-  return anyOverflowChanged;
 }
 
 /* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
  * the mRect value for their parents (since we use their transform, and transform
  * depends on this for transform-origin etc). These weren't necessarily correct
  * when we reflowed initially, so walk over all preserve-3d children and repeat the
  * overflow calculation.
  */
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -77,17 +77,16 @@
 #endif
 #include "nsBidiUtils.h"
 #include "nsFrameManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/dom/Element.h"
 #include "FrameLayerBuilder.h"
 #include "nsSMILKeySpline.h"
-#include "nsSubDocumentFrame.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 
 //----------nsHTMLScrollFrame-------------------------------------------
 
@@ -192,30 +191,26 @@ 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;
-      if (mInner.IsIgnoringViewportClipping()) {
-        parentDamage = damage;
+      // 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.
+      nsRect displayport;
+      bool usingDisplayport = nsLayoutUtils::GetDisplayPort(GetContent(),
+                                                              &displayport);
+      if (usingDisplayport) {
+        parentDamage.IntersectRect(damage, displayport);
       } else {
-        // 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.
-        nsRect displayport;
-        bool usingDisplayport = nsLayoutUtils::GetDisplayPort(GetContent(),
-                                                                &displayport);
-        if (usingDisplayport) {
-          parentDamage.IntersectRect(damage, displayport);
-        } else {
-          parentDamage.IntersectRect(damage, mInner.mScrollPort);
-        }
+        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
@@ -283,17 +278,17 @@ nsHTMLScrollFrame::InvalidateInternal(co
 
 struct ScrollReflowState {
   const nsHTMLReflowState& mReflowState;
   nsBoxLayoutState mBoxState;
   nsGfxScrollFrameInner::ScrollbarStyles mStyles;
   nsMargin mComputedBorder;
 
   // === Filled in by ReflowScrolledFrame ===
-  nsOverflowAreas mContentsOverflowAreas;
+  nsRect mContentsOverflowArea;
   bool mReflowedContentsWithHScrollbar;
   bool mReflowedContentsWithVScrollbar;
 
   // === Filled in when TryLayout succeeds ===
   // The size of the inside-border area
   nsSize mInsideBorderSize;
   // Whether we decided to show the horizontal scrollbar
   bool mShowHScrollbar;
@@ -427,18 +422,17 @@ nsHTMLScrollFrame::TryLayout(ScrollReflo
     NS_MAX(aKidMetrics->height, vScrollbarMinHeight);
   aState->mInsideBorderSize =
     ComputeInsideBorderSize(aState, desiredInsideBorderSize);
   nsSize scrollPortSize = nsSize(NS_MAX(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
                                  NS_MAX(0, aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
                                                                                 
   if (!aForce) {
     nsRect scrolledRect =
-      mInner.GetScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
-                                     scrollPortSize);
+      mInner.GetScrolledRectInternal(aState->mContentsOverflowArea, scrollPortSize);
     nscoord oneDevPixel = aState->mBoxState.PresContext()->DevPixelsToAppUnits(1);
 
     // If the style is HIDDEN then we already know that aAssumeHScroll is false
     if (aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
       bool wantHScrollbar =
         aState->mStyles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
         scrolledRect.XMost() >= scrollPortSize.width + oneDevPixel ||
         scrolledRect.x <= -oneDevPixel;
@@ -567,17 +561,17 @@ nsHTMLScrollFrame::ReflowScrolledFrame(S
   // setting their mOverflowArea. This is wrong because every frame should
   // always set mOverflowArea. In fact nsObjectFrame and nsFrameFrame don't
   // support the 'outline' property because of this. Rather than fix the world
   // right now, just fix up the overflow area if necessary. Note that we don't
   // check HasOverflowRect() because it could be set even though the
   // overflow area doesn't include the frame bounds.
   aMetrics->UnionOverflowAreasWithDesiredBounds();
 
-  aState->mContentsOverflowAreas = aMetrics->mOverflowAreas;
+  aState->mContentsOverflowArea = aMetrics->ScrollableOverflow();
   aState->mReflowedContentsWithHScrollbar = aAssumeHScroll;
   aState->mReflowedContentsWithVScrollbar = aAssumeVScroll;
   
   return rv;
 }
 
 bool
 nsHTMLScrollFrame::GuessHScrollbarNeeded(const ScrollReflowState& aState)
@@ -719,19 +713,17 @@ nsHTMLScrollFrame::PlaceScrollArea(const
 {
   nsIFrame *scrolledFrame = mInner.mScrolledFrame;
   // Set the x,y of the scrolled frame to the correct value
   scrolledFrame->SetPosition(mInner.mScrollPort.TopLeft() - aScrollPosition);
 
   nsRect scrolledArea;
   // Preserve the width or height of empty rects
   nsSize portSize = mInner.mScrollPort.Size();
-  nsRect scrolledRect =
-    mInner.GetScrolledRectInternal(aState.mContentsOverflowAreas.ScrollableOverflow(),
-                                   portSize);
+  nsRect scrolledRect = mInner.GetScrolledRectInternal(aState.mContentsOverflowArea, portSize);
   scrolledArea.UnionRectEdges(scrolledRect,
                               nsRect(nsPoint(0,0), portSize));
 
   // Store the new overflow area. Note that this changes where an outline
   // of the scrolled frame would be painted, but scrolled frames can't have
   // outlines (the outline would go on this scrollframe instead).
   // Using FinishAndStoreOverflow is needed so the overflow rect
   // gets set correctly.  It also messes with the overflow rect in the
@@ -928,20 +920,16 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
   }
 
   aDesiredSize.width = state.mInsideBorderSize.width +
     state.mComputedBorder.LeftRight();
   aDesiredSize.height = state.mInsideBorderSize.height +
     state.mComputedBorder.TopBottom();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
-  if (mInner.IsIgnoringViewportClipping()) {
-    aDesiredSize.mOverflowAreas.UnionWith(
-      state.mContentsOverflowAreas + mInner.mScrolledFrame->GetPosition());
-  }
 
   CheckInvalidateSizeChange(aDesiredSize);
 
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
 
   if (!InInitialReflow() && !mInner.mHadNonInitialReflow) {
     mInner.mHadNonInitialReflow = true;
   }
@@ -1694,25 +1682,16 @@ InvalidateFixedBackgroundFrames(nsIFrame
 
   nsRegion visibleRegion(aUpdateRect);
   list.ComputeVisibilityForRoot(&builder, &visibleRegion);
 
   InvalidateFixedBackgroundFramesFromList(&builder, aMovingFrame, list);
   list.DeleteAll();
 }
 
-bool nsGfxScrollFrameInner::IsIgnoringViewportClipping() const
-{
-  if (!mIsRoot)
-    return false;
-  nsSubDocumentFrame* subdocFrame = static_cast<nsSubDocumentFrame*>
-    (nsLayoutUtils::GetCrossDocParentFrame(mOuter->PresContext()->PresShell()->GetRootFrame()));
-  return subdocFrame && !subdocFrame->ShouldClipSubdocument();
-}
-
 bool nsGfxScrollFrameInner::IsAlwaysActive() const
 {
   // The root scrollframe for a non-chrome document which is the direct
   // child of a chrome document is always treated as "active".
   // XXX maybe we should extend this so that IFRAMEs which are fill the
   // entire viewport (like GMail!) are always active
   return mIsRoot && mOuter->PresContext()->IsRootContentDocument();
 }
@@ -1737,17 +1716,17 @@ void nsGfxScrollFrameInner::MarkActive()
   } else {
     if (!gScrollFrameActivityTracker) {
       gScrollFrameActivityTracker = new ScrollFrameActivityTracker();
     }
     gScrollFrameActivityTracker->AddObject(this);
   }
 }
 
-void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
+void nsGfxScrollFrameInner::ScrollVisual()
 {
   nsRootPresContext* rootPresContext = mOuter->PresContext()->GetRootPresContext();
   if (!rootPresContext) {
     return;
   }
 
   rootPresContext->RequestUpdatePluginGeometry(mOuter);
 
@@ -1764,25 +1743,19 @@ void nsGfxScrollFrameInner::ScrollVisual
       flags |= nsIFrame::INVALIDATE_NO_THEBES_LAYERS;
     }
   }
   if (canScrollWithBlitting) {
     MarkActive();
   }
 
   nsRect invalidateRect, displayport;
-  if (IsIgnoringViewportClipping()) {
-    nsRect visualOverflow = mScrolledFrame->GetVisualOverflowRect();
-    invalidateRect.UnionRect(visualOverflow + mScrolledFrame->GetPosition(),
-            visualOverflow + aOldScrolledFramePos);
-  } else {
-    invalidateRect =
-      (nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayport)) ?
-      displayport : mScrollPort;
-  }
+  invalidateRect =
+    (nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayport)) ?
+    displayport : mScrollPort;
 
   mOuter->InvalidateWithFlags(invalidateRect, flags);
 
   if (flags & nsIFrame::INVALIDATE_NO_THEBES_LAYERS) {
     nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(mOuter);
     nsRect update =
       GetScrollPortRect() + mOuter->GetOffsetToCrossDoc(displayRoot);
     update = update.ConvertAppUnitsRoundOut(
@@ -1842,23 +1815,22 @@ nsGfxScrollFrameInner::ScrollToImpl(nsPo
                "curPos.x not a multiple of device pixels");
   NS_ASSERTION(curPosDevPx.y*appUnitsPerDevPixel == curPos.y,
                "curPos.y not a multiple of device pixels");
 
   // notify the listeners.
   for (PRUint32 i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->ScrollPositionWillChange(pt.x, pt.y);
   }
-
-  nsPoint oldScrollFramePos = mScrolledFrame->GetPosition();
+  
   // Update frame position for scrolling
   mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
 
   // We pass in the amount to move visually
-  ScrollVisual(oldScrollFramePos);
+  ScrollVisual();
 
   presContext->PresShell()->SynthesizeMouseMove(true);
   UpdateScrollbarPosition();
   PostScrollEvent();
 
   // notify the listeners.
   for (PRUint32 i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->ScrollPositionDidChange(pt.x, pt.y);
@@ -1960,17 +1932,17 @@ nsGfxScrollFrameInner::BuildDisplayList(
 
   if (aBuilder->IsPaintingToWindow()) {
     mScrollPosAtLastPaint = GetScrollPosition();
     if (IsScrollingActive() && !CanScrollWithBlitting(mOuter)) {
       MarkInactive();
     }
   }
 
-  if (aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping()) {
+  if (aBuilder->GetIgnoreScrollFrame() == mOuter) {
     // Don't clip the scrolled child, and don't paint scrollbars/scrollcorner.
     // The scrolled frame shouldn't have its own background/border, so we
     // can just pass aLists directly.
     return mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame,
                                             aDirtyRect, aLists);
   }
 
   // We put scrollbars in their own layers when this is the root scroll
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -177,17 +177,17 @@ public:
   }
   nsRect GetScrollRange() const;
 
   nsPoint ClampAndRestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx) const;
   nsPoint ClampScrollPosition(const nsPoint& aPt) const;
   static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);
   void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode);
   void ScrollToImpl(nsPoint aScrollPosition);
-  void ScrollVisual(nsPoint aOldScrolledFramePosition);
+  void ScrollVisual();
   void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit,
                 nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow);
   void ScrollToRestoredPosition();
   nsSize GetLineScrollAmount() const;
   nsSize GetPageScrollAmount() const;
 
   nsPresState* SaveState(nsIStatefulFrame::SpecialStateID aStateID);
   void RestoreState(nsPresState* aState);
@@ -251,18 +251,16 @@ public:
   void AdjustScrollbarRectForResizer(nsIFrame* aFrame, nsPresContext* aPresContext,
                                      nsRect& aRect, bool aHasResizer, bool aVertical);
   // returns true if a resizer should be visible
   bool HasResizer() { return mResizerBox && !mCollapsedResizer; }
   void LayoutScrollbars(nsBoxLayoutState& aState,
                         const nsRect& aContentArea,
                         const nsRect& aOldScrollArea);
 
-  bool IsIgnoringViewportClipping() const;
-
   bool IsAlwaysActive() const;
   void MarkActive();
   void MarkInactive();
   nsExpirationState* GetExpirationState() { return &mActivityExpirationState; }
 
   // owning references to the nsIAnonymousContentCreator-built content
   nsCOMPtr<nsIContent> mHScrollbarContent;
   nsCOMPtr<nsIContent> mVScrollbarContent;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2269,40 +2269,38 @@ public:
    * @return the rect relative to this frame, before any CSS transforms have
    * been applied, i.e. in this frame's coordinate system
    */
   nsRect GetVisualOverflowRectRelativeToSelf() const;
 
   /**
    * Store the overflow area in the frame's mOverflow.mVisualDeltas
    * fields or as a frame property in the frame manager so that it can
-   * be retrieved later without reflowing the frame. Returns true if either of
-   * the overflow areas changed.
+   * be retrieved later without reflowing the frame.
    */
-  bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
+  void FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                               nsSize aNewSize);
 
-  bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
-    return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
-                                  nsSize(aMetrics->width, aMetrics->height));
+  void FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
+    FinishAndStoreOverflow(aMetrics->mOverflowAreas,
+                           nsSize(aMetrics->width, aMetrics->height));
   }
 
   /**
    * Returns whether the frame has an overflow rect that is different from
    * its border-box.
    */
   bool HasOverflowAreas() const {
     return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
   }
 
   /**
    * Removes any stored overflow rects (visual and scrollable) from the frame.
-   * Returns true if the overflow changed.
    */
-  bool ClearOverflowRects();
+  void ClearOverflowRects();
 
   /**
    * Determine whether borders should not be painted on certain sides of the
    * frame.
    */
   virtual PRIntn GetSkipSides() const { return 0; }
 
   /** Selection related calls
@@ -2819,34 +2817,24 @@ protected:
   // we store a set of four 1-byte deltas from the edges of mRect
   // rather than allocating a whole separate rectangle property.
   // Note that these are unsigned values, all measured "outwards"
   // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
   // our normal coordinate system.
   // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
   // delta values are not meaningful and the overflow area is stored
   // as a separate rect property.
-  struct VisualDeltas {
-    PRUint8 mLeft;
-    PRUint8 mTop;
-    PRUint8 mRight;
-    PRUint8 mBottom;
-    bool operator==(const VisualDeltas& aOther) const
-    {
-      return mLeft == aOther.mLeft && mTop == aOther.mTop &&
-             mRight == aOther.mRight && mBottom == aOther.mBottom;
-    }
-    bool operator!=(const VisualDeltas& aOther) const
-    {
-      return !(*this == aOther);
-    }
-  };
   union {
-    PRUint32     mType;
-    VisualDeltas mVisualDeltas;
+    PRUint32  mType;
+    struct {
+      PRUint8 mLeft;
+      PRUint8 mTop;
+      PRUint8 mRight;
+      PRUint8 mBottom;
+    } mVisualDeltas;
   } mOverflow;
 
   // Helpers
   /**
    * For frames that have top-level windows (top-level viewports,
    * comboboxes, menupoups) this function will invalidate the window.
    */
   void InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags);
@@ -2951,20 +2939,17 @@ private:
     // to cast away the unsigned-ness.
     return nsRect(-(PRInt32)mOverflow.mVisualDeltas.mLeft,
                   -(PRInt32)mOverflow.mVisualDeltas.mTop,
                   mRect.width + mOverflow.mVisualDeltas.mRight +
                                 mOverflow.mVisualDeltas.mLeft,
                   mRect.height + mOverflow.mVisualDeltas.mBottom +
                                  mOverflow.mVisualDeltas.mTop);
   }
-  /**
-   * Returns true if any overflow changed.
-   */
-  bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
+  void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const PRInt32 aAPD) const;
 
 #ifdef NS_DEBUG
 public:
   // Formerly nsIFrameDebug
   NS_IMETHOD  List(FILE* out, PRInt32 aIndent) const = 0;
   NS_IMETHOD  GetFrameName(nsAString& aResult) const = 0;
   NS_IMETHOD_(nsFrameState)  GetDebugStateBits() const = 0;
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -406,31 +406,28 @@ nsSubDocumentFrame::BuildDisplayList(nsD
     
     if (!addedLayer && presContext->IsRootContentDocument()) {
       // We always want top level content documents to be in their own layer.
       nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
         aBuilder, subdocRootFrame ? subdocRootFrame : this, &childItems);
       childItems.AppendToTop(layerItem);
     }
 
-    if (ShouldClipSubdocument()) {
-      nsDisplayClip* item =
+    nsDisplayList list;
+    // Clip children to the child root frame's rectangle
+    rv = list.AppendNewToTop(
         new (aBuilder) nsDisplayClip(aBuilder, this, &childItems,
-                                     subdocBoundsInParentUnits);
-      // Clip children to the child root frame's rectangle
-      childItems.AppendToTop(item);
-    }
+                                     subdocBoundsInParentUnits));
 
     if (mIsInline) {
-      WrapReplacedContentForBorderRadius(aBuilder, &childItems, aLists);
+      WrapReplacedContentForBorderRadius(aBuilder, &list, aLists);
     } else {
-      aLists.Content()->AppendToTop(&childItems);
+      aLists.Content()->AppendToTop(&list);
     }
   }
-
   // delete childItems in case of OOM
   childItems.DeleteAll();
 
   if (subdocRootFrame) {
     aBuilder->LeavePresShell(subdocRootFrame, dirty);
   }
 
   return rv;
@@ -615,24 +612,16 @@ nsSubDocumentFrame::Reflow(nsPresContext
   }
 
   if (mInnerView) {
     nsIViewManager* vm = mInnerView->GetViewManager();
     vm->MoveViewTo(mInnerView, offset.x, offset.y);
     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), true);
   }
 
-  aDesiredSize.SetOverflowAreasToDesiredBounds();
-  if (!ShouldClipSubdocument()) {
-    nsIFrame* subdocRootFrame = GetSubdocumentRootFrame();
-    if (subdocRootFrame) {
-      aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset);
-    }
-  }
-
   // Determine if we need to repaint our border, background or outline
   CheckInvalidateSizeChange(aDesiredSize);
 
   FinishAndStoreOverflow(&aDesiredSize);
 
   if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
     PresContext()->PresShell()->PostReflowCallback(this);
     mPostedReflowCallback = true;
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -119,22 +119,16 @@ public:
   void EndSwapDocShells(nsIFrame* aOther);
   nsIView* EnsureInnerView();
   nsIFrame* GetSubdocumentRootFrame();
 
   // nsIReflowCallback
   virtual bool ReflowFinished();
   virtual void ReflowCallbackCanceled();
 
-  bool ShouldClipSubdocument()
-  {
-    nsFrameLoader* frameLoader = FrameLoader();
-    return !frameLoader || frameLoader->ShouldClipSubdocument();
-  }
-
 protected:
   friend class AsyncFrameInit;
 
   // Helper method to look up the HTML marginwidth & marginheight attributes
   nsIntSize GetMarginAttributes();
 
   nsFrameLoader* FrameLoader();
 
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -42,17 +42,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsViewportFrame.h"
 #include "nsHTMLParts.h"
 #include "nsGkAtoms.h"
 #include "nsIScrollableFrame.h"
 #include "nsDisplayList.h"
 #include "FrameLayerBuilder.h"
-#include "nsSubDocumentFrame.h"
 #include "nsAbsoluteContainingBlock.h"
 
 using namespace mozilla;
 
 nsIFrame*
 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) ViewportFrame(aContext);
@@ -206,18 +205,16 @@ ViewportFrame::Reflow(nsPresContext*    
  
   // Reflow the main content first so that the placeholders of the
   // fixed-position frames will be in the right places on an initial
   // reflow.
   nscoord kidHeight = 0;
 
   nsresult rv = NS_OK;
   
-  aDesiredSize.SetOverflowAreasToDesiredBounds();
-
   if (mFrames.NotEmpty()) {
     // Deal with a non-incremental reflow or an incremental reflow
     // targeted at our one-and-only principal child frame.
     if (aReflowState.ShouldReflowAllKids() ||
         aReflowState.mFlags.mVResize ||
         NS_SUBTREE_DIRTY(mFrames.FirstChild())) {
       // Reflow our one-and-only principal child frame
       nsIFrame*           kidFrame = mFrames.FirstChild();
@@ -232,17 +229,16 @@ ViewportFrame::Reflow(nsPresContext*    
       rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
                        0, 0, 0, aStatus);
       kidHeight = kidDesiredSize.height;
 
       FinishReflowChild(kidFrame, aPresContext, nsnull, kidDesiredSize, 0, 0, 0);
     } else {
       kidHeight = mFrames.FirstChild()->GetSize().height;
     }
-    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
   }
 
   NS_ASSERTION(aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE,
                "shouldn't happen anymore");
 
   // Return the max size as our desired size
   aDesiredSize.width = aReflowState.availableWidth;
   // Being flowed initially at an unconstrained height means we should
@@ -251,49 +247,42 @@ ViewportFrame::Reflow(nsPresContext*    
                           ? aReflowState.ComputedHeight()
                           : kidHeight;
 
   // Make a copy of the reflow state and change the computed width and height
   // to reflect the available space for the fixed items
   nsHTMLReflowState reflowState(aReflowState);
   nsPoint offset = AdjustReflowStateForScrollbars(&reflowState);
 
+#ifdef DEBUG
   if (IsAbsoluteContainer()) {
     NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() ||
                  (offset.x == 0 && offset.y == 0),
                  "We don't handle correct positioning of fixed frames with "
                  "scrollbars in odd positions");
+  }
+#endif
 
+  if (IsAbsoluteContainer()) {
     // Just reflow all the fixed-pos frames.
     rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus,
                                               reflowState.ComputedWidth(),
                                               reflowState.ComputedHeight(),
                                               false, true, true, // XXX could be optimized
-                                              &aDesiredSize.mOverflowAreas);
+                                              nsnull /* ignore overflow */);
   }
 
   // If we were dirty then do a repaint
   if (GetStateBits() & NS_FRAME_IS_DIRTY) {
     nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height);
     Invalidate(damageRect);
   }
 
-  // Clipping is handled by the document container (e.g., nsSubDocumentFrame),
-  // so we don't need to change our overflow areas.
-  bool overflowChanged = FinishAndStoreOverflow(&aDesiredSize);
-  if (overflowChanged) {
-    // We may need to alert our container to get it to pick up the
-    // overflow change.
-    nsSubDocumentFrame* container = static_cast<nsSubDocumentFrame*>
-      (nsLayoutUtils::GetCrossDocParentFrame(this));
-    if (container && !container->ShouldClipSubdocument()) {
-      container->PresContext()->PresShell()->
-        FrameNeedsReflow(container, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
-    }
-  }
+  // XXX Should we do something to clip our children to this?
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv; 
 }
 
 nsIAtom*
 ViewportFrame::GetType() const