OSDN Git Service

Merge Webkit at r70949: Initial merge by git.
[android-x86/external-webkit.git] / WebCore / page / FrameView.cpp
index 1508e07..7bc29d5 100644 (file)
@@ -29,9 +29,9 @@
 
 #include "AXObjectCache.h"
 #include "CSSStyleSelector.h"
+#include "CachedResourceLoader.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
-#include "DocLoader.h"
 #include "EventHandler.h"
 #include "FloatRect.h"
 #include "FocusController.h"
@@ -44,7 +44,8 @@
 #include "HTMLFrameElement.h"
 #include "HTMLFrameSetElement.h"
 #include "HTMLNames.h"
-#include "InspectorTimelineAgent.h"
+#include "HTMLPlugInImageElement.h"
+#include "InspectorInstrumentation.h"
 #include "OverflowEvent.h"
 #include "RenderEmbeddedObject.h"
 #include "RenderLayer.h"
@@ -119,17 +120,6 @@ struct ScheduledEvent : Noncopyable {
     RefPtr<Node> m_eventTarget;
 };
 
-static inline float parentZoomFactor(Frame* frame)
-{
-    Frame* parent = frame->tree()->parent();
-    if (!parent)
-        return 1;
-    FrameView* parentView = parent->view();
-    if (!parentView)
-        return 1;
-    return parentView->zoomFactor();
-}
-
 FrameView::FrameView(Frame* frame)
     : m_frame(frame)
     , m_canHaveScrollbars(true)
@@ -137,6 +127,8 @@ FrameView::FrameView(Frame* frame)
     , m_fixedObjectCount(0)
     , m_layoutTimer(this, &FrameView::layoutTimerFired)
     , m_layoutRoot(0)
+    , m_hasPendingPostLayoutTasks(false)
+    , m_inSynchronousPostLayout(false)
     , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
     , m_isTransparent(false)
     , m_baseBackgroundColor(Color::white)
@@ -151,7 +143,6 @@ FrameView::FrameView(Frame* frame)
     , m_deferSetNeedsLayouts(0)
     , m_setNeedsLayoutWasDeferred(false)
     , m_scrollCorner(0)
-    , m_zoomFactor(parentZoomFactor(frame))
 {
     init();
 }
@@ -173,7 +164,7 @@ PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize
 
 FrameView::~FrameView()
 {
-    if (m_postLayoutTasksTimer.isActive()) {
+    if (m_hasPendingPostLayoutTasks) {
         m_postLayoutTasksTimer.stop();
         m_scheduledEvents.clear();
         m_enqueueEvents = 0;
@@ -212,7 +203,9 @@ void FrameView::reset()
     m_delayedLayout = false;
     m_doFullRepaint = true;
     m_layoutSchedulingEnabled = true;
-    m_midLayout = false;
+    m_inLayout = false;
+    m_inSynchronousPostLayout = false;
+    m_hasPendingPostLayoutTasks = false;
     m_layoutCount = 0;
     m_nestedLayoutCount = 0;
     m_postLayoutTasksTimer.stop();
@@ -284,11 +277,11 @@ void FrameView::detachCustomScrollbars()
         return;
 
     Scrollbar* horizontalBar = horizontalScrollbar();
-    if (horizontalBar && horizontalBar->isCustomScrollbar() && !toRenderScrollbar(horizontalBar)->owningRenderer()->isRenderPart())
+    if (horizontalBar && horizontalBar->isCustomScrollbar())
         setHasHorizontalScrollbar(false);
 
     Scrollbar* verticalBar = verticalScrollbar();
-    if (verticalBar && verticalBar->isCustomScrollbar() && !toRenderScrollbar(verticalBar)->owningRenderer()->isRenderPart())
+    if (verticalBar && verticalBar->isCustomScrollbar())
         setHasVerticalScrollbar(false);
 
     if (m_scrollCorner) {
@@ -337,6 +330,22 @@ void FrameView::invalidateRect(const IntRect& rect)
     renderer->repaintRectangle(repaintRect);
 }
 
+void FrameView::setFrameRect(const IntRect& newRect)
+{
+    IntRect oldRect = frameRect();
+    if (newRect == oldRect)
+        return;
+
+    ScrollView::setFrameRect(newRect);
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (RenderView* root = m_frame->contentRenderer()) {
+        if (root->usesCompositing())
+            root->compositor()->frameViewDidChangeSize();
+    }
+#endif
+}
+
 void FrameView::setMarginWidth(int w)
 {
     // make it update the rendering area when set
@@ -378,9 +387,9 @@ void FrameView::updateCanHaveScrollbars()
     ScrollbarMode vMode;
     scrollbarModes(hMode, vMode);
     if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
-        m_canHaveScrollbars = false;
+        setCanHaveScrollbars(false);
     else
-        m_canHaveScrollbars = true;
+        setCanHaveScrollbars(true);
 }
 
 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
@@ -401,7 +410,7 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio
     // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
     RenderPart* frameRenderer = m_frame->ownerRenderer();
     if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
-        return RenderScrollbar::createCustomScrollbar(this, orientation, frameRenderer);
+        return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
     
     // Nobody set a custom style, so we just use a native scrollbar.
     return ScrollView::createScrollbar(orientation);
@@ -477,6 +486,58 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
     m_viewportRenderer = o;
 }
 
+void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
+{
+    if (m_canHaveScrollbars) {
+        hMode = ScrollbarAuto;
+        vMode = ScrollbarAuto;
+    } else {
+        hMode = ScrollbarAlwaysOff;
+        vMode = ScrollbarAlwaysOff;
+    }
+    
+    if (!m_layoutRoot) {
+        Document* document = m_frame->document();
+        Node* documentElement = document->documentElement();
+        RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
+        Node* body = document->body();
+        if (body && body->renderer()) {
+            if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
+#if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
+                body->renderer()->setChildNeedsLayout(true);
+                vMode = ScrollbarAlwaysOff;
+                hMode = ScrollbarAlwaysOff;
+#endif
+            } else if (body->hasTagName(bodyTag)) {
+                // It's sufficient to just check the X overflow,
+                // since it's illegal to have visible in only one direction.
+                RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
+                applyOverflowToViewport(o, hMode, vMode);
+            }
+        } else if (rootRenderer) {
+#if ENABLE(SVG)
+            if (documentElement->isSVGElement()) {
+                if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
+                    rootRenderer->setChildNeedsLayout(true);
+            } else
+                applyOverflowToViewport(rootRenderer, hMode, vMode);
+#else
+            applyOverflowToViewport(rootRenderer, hMode, vMode);
+#endif
+        }
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+        if (m_firstLayout && !document->ownerElement())
+            printf("Elapsed time before first layout: %d\n", document->elapsedTime());
+#endif
+    }
+    
+    HTMLFrameOwnerElement* owner = m_frame->ownerElement();
+    if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
+        hMode = ScrollbarAlwaysOff;
+        vMode = ScrollbarAlwaysOff;
+    }     
+}
+    
 #if USE(ACCELERATED_COMPOSITING)
 void FrameView::updateCompositingLayers()
 {
@@ -486,10 +547,6 @@ void FrameView::updateCompositingLayers()
 
     // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
     view->compositor()->cacheAcceleratedCompositingFlags();
-    
-    if (!view->usesCompositing())
-        return;
-
     view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
 }
 
@@ -515,8 +572,11 @@ bool FrameView::hasCompositedContent() const
 void FrameView::enterCompositingMode()
 {
 #if USE(ACCELERATED_COMPOSITING)
-    if (RenderView* view = m_frame->contentRenderer())
-        return view->compositor()->enableCompositingMode();
+    if (RenderView* view = m_frame->contentRenderer()) {
+        view->compositor()->enableCompositingMode();
+        if (!needsLayout())
+            view->compositor()->scheduleCompositingLayerUpdate();
+    }
 #endif
 }
 
@@ -538,10 +598,10 @@ bool FrameView::syncCompositingStateRecursive()
     if (!contentRenderer)
         return true;    // We don't want to keep trying to update layers if we have no renderer.
 
-    if (m_layoutTimer.isActive()) {
-        // Don't sync layers if there's a layout pending.
+    // If we sync compositing layers when a layout is pending, we may cause painting of compositing
+    // layer content to occur before layout has happened, which will cause paintContents() to bail.
+    if (needsLayout())
         return false;
-    }
     
     if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
         rootLayer->syncCompositingState();
@@ -596,7 +656,7 @@ RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
 
 void FrameView::layout(bool allowSubtree)
 {
-    if (m_midLayout)
+    if (m_inLayout)
         return;
 
     m_layoutTimer.stop();
@@ -618,10 +678,7 @@ void FrameView::layout(bool allowSubtree)
     if (isPainting())
         return;
 
-#if ENABLE(INSPECTOR)    
-    if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
-        timelineAgent->willLayout();
-#endif
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
 
     if (!allowSubtree && m_layoutRoot) {
         m_layoutRoot->markContainingBlocksForLayout(false);
@@ -629,34 +686,28 @@ void FrameView::layout(bool allowSubtree)
     }
 
     ASSERT(m_frame->view() == this);
-    // This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a
-    // gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful 
-    // failure instead.  
-    if (m_frame->view() != this)
-        return;
 
     Document* document = m_frame->document();
 
     m_layoutSchedulingEnabled = false;
 
-    if (!m_nestedLayoutCount && m_postLayoutTasksTimer.isActive()) {
+    if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
         // This is a new top-level layout. If there are any remaining tasks from the previous
         // layout, finish them now.
+        m_inSynchronousPostLayout = true;
         m_postLayoutTasksTimer.stop();
         performPostLayoutTasks();
+        m_inSynchronousPostLayout = false;
     }
 
     // Viewport-dependent media queries may cause us to need completely different style information.
     // Check that here.
     if (document->styleSelector()->affectedByViewportChange())
-        document->updateStyleSelector();
+        document->styleSelectorChanged(RecalcStyleImmediately);
 
     // Always ensure our style info is up-to-date.  This can happen in situations where
     // the layout beats any sort of style recalc update that needs to occur.
-    if (m_frame->needsReapplyStyles())
-        m_frame->reapplyStyles();
-    else if (document->childNeedsStyleRecalc())
-        document->recalcStyle();
+    document->updateStyleIfNeeded();
     
     bool subtree = m_layoutRoot;
 
@@ -681,49 +732,8 @@ void FrameView::layout(bool allowSubtree)
 
     ScrollbarMode hMode;
     ScrollbarMode vMode;
-    if (m_canHaveScrollbars) {
-        hMode = ScrollbarAuto;
-        vMode = ScrollbarAuto;
-    } else {
-        hMode = ScrollbarAlwaysOff;
-        vMode = ScrollbarAlwaysOff;
-    }
-
-    if (!subtree) {
-        Node* documentElement = document->documentElement();
-        RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
-        Node* body = document->body();
-        if (body && body->renderer()) {
-            if (body->hasTagName(framesetTag) && !m_frame->settings()->frameFlatteningEnabled()) {
-#if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
-                body->renderer()->setChildNeedsLayout(true);
-                vMode = ScrollbarAlwaysOff;
-                hMode = ScrollbarAlwaysOff;
-#endif
-            } else if (body->hasTagName(bodyTag)) {
-                if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewHeight())
-                    body->renderer()->setChildNeedsLayout(true);
-                // It's sufficient to just check the X overflow,
-                // since it's illegal to have visible in only one direction.
-                RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
-                applyOverflowToViewport(o, hMode, vMode);
-            }
-        } else if (rootRenderer) {
-#if ENABLE(SVG)
-            if (documentElement->isSVGElement()) {
-                if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
-                    rootRenderer->setChildNeedsLayout(true);
-            } else
-                applyOverflowToViewport(rootRenderer, hMode, vMode);
-#else
-            applyOverflowToViewport(rootRenderer, hMode, vMode);
-#endif
-        }
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
-        if (m_firstLayout && !document->ownerElement())
-            printf("Elapsed time before first layout: %d\n", document->elapsedTime());
-#endif
-    }
+    
+    calculateScrollbarModesForLayout(hMode, vMode);
 
     m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
 
@@ -758,8 +768,17 @@ void FrameView::layout(bool allowSubtree)
 
         m_size = IntSize(layoutWidth(), layoutHeight());
 
-        if (oldSize != m_size)
+        if (oldSize != m_size) {
             m_doFullRepaint = true;
+            if (!m_firstLayout) {
+                RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
+                RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
+                if (bodyRenderer && bodyRenderer->stretchesToViewport())
+                    bodyRenderer->setChildNeedsLayout(true);
+                else if (rootRenderer && rootRenderer->stretchesToViewport())
+                    rootRenderer->setChildNeedsLayout(true);
+            }
+        }
     }
 
     RenderLayer* layer = root->enclosingLayer();
@@ -775,21 +794,21 @@ void FrameView::layout(bool allowSubtree)
             view->disableLayoutState();
     }
         
-    m_midLayout = true;
+    m_inLayout = true;
     beginDeferredRepaints();
     root->layout();
     endDeferredRepaints();
-    m_midLayout = false;
+    m_inLayout = false;
 
     if (subtree) {
         RenderView* view = root->view();
-        view->popLayoutState();
+        view->popLayoutState(root);
         if (disableLayoutState)
             view->enableLayoutState();
     }
     m_layoutRoot = 0;
 
-    m_frame->selection()->setNeedsLayout();
+    m_frame->selection()->setCaretRectNeedsUpdate();
     m_frame->selection()->updateAppearance();
    
     m_layoutSchedulingEnabled = true;
@@ -813,7 +832,7 @@ void FrameView::layout(bool allowSubtree)
     
     m_layoutCount++;
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
     if (AXObjectCache::accessibilityEnabled())
         root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
 #endif
@@ -833,27 +852,32 @@ void FrameView::layout(bool allowSubtree)
         updateOverflowStatus(layoutWidth() < contentsWidth(),
                              layoutHeight() < contentsHeight());
 
-    if (!m_postLayoutTasksTimer.isActive()) {
-        // Calls resumeScheduledEvents()
-        performPostLayoutTasks();
+    if (!m_hasPendingPostLayoutTasks) {
+        if (!m_inSynchronousPostLayout) {
+            m_inSynchronousPostLayout = true;
+            // Calls resumeScheduledEvents()
+            performPostLayoutTasks();
+            m_inSynchronousPostLayout = false;
+        }
 
-        if (!m_postLayoutTasksTimer.isActive() && needsLayout()) {
-            // Post-layout widget updates or an event handler made us need layout again.
-            // Lay out again, but this time defer widget updates and event dispatch until after
-            // we return.
+        if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
+            // If we need layout or are already in a synchronous call to postLayoutTasks(), 
+            // defer widget updates and event dispatch until after we return. postLayoutTasks()
+            // can make us need to update again, and we can get stuck in a nasty cycle unless
+            // we call it through the timer here.
+            m_hasPendingPostLayoutTasks = true;
             m_postLayoutTasksTimer.startOneShot(0);
-            pauseScheduledEvents();
-            layout();
+            if (needsLayout()) {
+                pauseScheduledEvents();
+                layout();
+            }
         }
     } else {
         resumeScheduledEvents();
         ASSERT(m_enqueueEvents);
     }
 
-#if ENABLE(INSPECTOR)
-    if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
-        timelineAgent->didLayout();
-#endif
+    InspectorInstrumentation::didLayout(cookie);
 
     m_nestedLayoutCount--;
 }
@@ -1003,6 +1027,24 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect
     return false;
 }
 
+void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
+        if (frameRenderer->containerForRepaint()) {
+            IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
+                         frameRenderer->borderTop() + frameRenderer->paddingTop(),
+                         visibleWidth(), visibleHeight());
+            frameRenderer->repaintRectangle(rect);
+            return;
+        }
+    }
+#endif
+
+    ScrollView::scrollContentsSlowPath(updateRect);
+}
+
+// Note that this gets called at painting time.
 void FrameView::setIsOverlapped(bool isOverlapped)
 {
     if (isOverlapped == m_isOverlapped)
@@ -1013,10 +1055,15 @@ void FrameView::setIsOverlapped(bool isOverlapped)
     
 #if USE(ACCELERATED_COMPOSITING)
     // Overlap can affect compositing tests, so if it changes, we need to trigger
-    // a recalcStyle in the parent document.
+    // a layer update in the parent document.
     if (hasCompositedContent()) {
-        if (Element* ownerElement = m_frame->document()->ownerElement())
-            ownerElement->setNeedsStyleRecalc(SyntheticStyleChange);
+        if (Frame* parentFrame = m_frame->tree()->parent()) {
+            if (RenderView* parentView = parentFrame->contentRenderer()) {
+                RenderLayerCompositor* compositor = parentView->compositor();
+                compositor->setCompositingLayersNeedRebuild();
+                compositor->scheduleCompositingLayerUpdate();
+            }
+        }
     }
 #endif    
 }
@@ -1099,11 +1146,11 @@ bool FrameView::scrollToAnchor(const String& name)
 
 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
     // TODO(andreip): check with Grace if this is correct.
-    android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(true);
+    android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
 #endif
     maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
-    android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(false);
+    android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
 #endif
     return true;
 }
@@ -1133,10 +1180,22 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint)
     m_inProgrammaticScroll = wasInProgrammaticScroll;
 }
 
+void FrameView::scrollPositionChangedViaPlatformWidget()
+{
+    repaintFixedElementsAfterScrolling();
+    scrollPositionChanged();
+}
+
 void FrameView::scrollPositionChanged()
 {
     frame()->eventHandler()->sendScrollEvent();
-    repaintFixedElementsAfterScrolling();
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (RenderView* root = m_frame->contentRenderer()) {
+        if (root->usesCompositing())
+            root->compositor()->frameViewDidScroll(scrollPosition());
+    }
+#endif
 }
 
 void FrameView::repaintFixedElementsAfterScrolling()
@@ -1148,18 +1207,10 @@ void FrameView::repaintFixedElementsAfterScrolling()
             root->updateWidgetPositions();
             root->layer()->updateRepaintRectsAfterScroll();
 #if USE(ACCELERATED_COMPOSITING)
-            if (root->usesCompositing())
-                root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
+            root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
 #endif
         }
     }
-
-#if USE(ACCELERATED_COMPOSITING)
-    if (RenderView* root = m_frame->contentRenderer()) {
-        if (root->usesCompositing())
-            root->compositor()->updateContentLayerScrollPosition(scrollPosition());
-    }
-#endif
 }
 
 HostWindow* FrameView::hostWindow() const
@@ -1268,7 +1319,7 @@ void FrameView::checkStopDelayingDeferredRepaints()
         return;
 
     Document* document = m_frame->document();
-    if (document && (document->parsing() || document->docLoader()->requestCount()))
+    if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
         return;
     
     m_deferredRepaintTimer.stop();
@@ -1303,7 +1354,7 @@ void FrameView::doDeferredRepaints()
 void FrameView::updateDeferredRepaintDelay()
 {
     Document* document = m_frame->document();
-    if (!document || (!document->parsing() && !document->docLoader()->requestCount())) {
+    if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
         m_deferredRepaintDelay = s_deferredRepaintDelay;
         return;
     }
@@ -1372,7 +1423,7 @@ void FrameView::scheduleRelayout()
 
     // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
     // Also invalidate parent frame starting from the owner element of this frame.
-    if (m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
+    if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
         if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
             m_frame->ownerRenderer()->setNeedsLayout(true, true);
     }
@@ -1450,12 +1501,9 @@ bool FrameView::needsLayout() const
     if (!m_frame)
         return false;
     RenderView* root = m_frame->contentRenderer();
-    Document* document = m_frame->document();
     return layoutPending()
         || (root && root->needsLayout())
         || m_layoutRoot
-        || (document && document->childNeedsStyleRecalc()) // can occur when using WebKit ObjC interface
-        || m_frame->needsReapplyStyles()
         || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
 }
 
@@ -1472,6 +1520,8 @@ void FrameView::setNeedsLayout()
 
 void FrameView::unscheduleRelayout()
 {
+    m_postLayoutTasksTimer.stop();
+
     if (!m_layoutTimer.isActive())
         return;
 
@@ -1580,6 +1630,37 @@ void FrameView::scrollToAnchor()
     m_maintainScrollPositionAnchor = anchorNode;
 }
 
+void FrameView::updateWidget(RenderEmbeddedObject* object)
+{
+    ASSERT(!object->node() || object->node()->isElementNode());
+    Element* ownerElement = static_cast<Element*>(object->node());
+    // The object may have already been destroyed (thus node cleared),
+    // but FrameView holds a manual ref, so it won't have been deleted.
+    ASSERT(m_widgetUpdateSet->contains(object));
+    if (!ownerElement)
+        return;
+
+    // No need to update if it's already crashed or known to be missing.
+    if (object->pluginCrashedOrWasMissing())
+        return;
+
+    // FIXME: This could turn into a real virtual dispatch if we defined
+    // updateWidget(bool) on HTMLElement.
+    if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
+        static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(false);
+    // FIXME: It is not clear that Media elements need or want this updateWidget() call.
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
+        static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(false);
+#endif
+    else
+        ASSERT_NOT_REACHED();
+
+    // Caution: it's possible the object was destroyed again, since loading a
+    // plugin may run any arbitrary javascript.
+    object->updateWidgetPosition();
+}
+
 bool FrameView::updateWidgets()
 {
     if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
@@ -1598,11 +1679,7 @@ bool FrameView::updateWidgets()
 
     for (size_t i = 0; i < size; ++i) {
         RenderEmbeddedObject* object = objects[i];
-
-        // The object may have been destroyed, but our manual ref() keeps the object from being deleted.
-        object->updateWidget(false);
-        object->updateWidgetPosition();
-
+        updateWidget(object);
         m_widgetUpdateSet->remove(object);
     }
 
@@ -1615,6 +1692,8 @@ bool FrameView::updateWidgets()
     
 void FrameView::performPostLayoutTasks()
 {
+    m_hasPendingPostLayoutTasks = false;
+
     if (m_firstLayoutCallbackPending) {
         m_firstLayoutCallbackPending = false;
         m_frame->loader()->didFirstLayout();
@@ -1708,7 +1787,7 @@ IntRect FrameView::windowClipRect(bool clipToContents) const
 
     // Set our clip rect to be our contents.
     IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
-    if (!m_frame || !m_frame->document()->ownerElement())
+    if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
         return clipRect;
 
     // Take our owner element and get the clip rect from the enclosing layer.
@@ -1750,7 +1829,14 @@ void FrameView::valueChanged(Scrollbar* bar)
     IntSize offset = scrollOffset();
     ScrollView::valueChanged(bar);
     if (offset != scrollOffset())
-        frame()->eventHandler()->sendScrollEvent();
+        scrollPositionChanged();
+    frame()->loader()->client()->didChangeScrollOffset();
+}
+
+void FrameView::valueChanged(const IntSize& scrollDelta)
+{
+    ScrollView::valueChanged(scrollDelta);
+    frame()->eventHandler()->sendScrollEvent();
     frame()->loader()->client()->didChangeScrollOffset();
 }
 
@@ -1764,7 +1850,7 @@ void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rec
 
 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
 {
-    tickmarks = frame()->document()->renderedRectsForMarkers(DocumentMarker::TextMatch);
+    tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
 }
 
 IntRect FrameView::windowResizerRect() const
@@ -1915,10 +2001,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
     if (!frame())
         return;
 
-#if ENABLE(INSPECTOR)
-    if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
-        timelineAgent->willPaint(rect);
-#endif
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
 
     Document* document = frame()->document();
 
@@ -1938,7 +2021,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
         fillWithRed = true;
     
     if (fillWithRed)
-        p->fillRect(rect, Color(0xFF, 0, 0), DeviceColorSpace);
+        p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
 #endif
 
     bool isTopLevelPainter = !sCurrentPaintTimeStamp;
@@ -1947,7 +2030,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
     
     RenderView* contentRenderer = frame()->contentRenderer();
     if (!contentRenderer) {
-        LOG_ERROR("called Frame::paint with nil renderer");
+        LOG_ERROR("called FrameView::paint with nil renderer");
         return;
     }
 
@@ -1971,7 +2054,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
 
     PaintBehavior oldPaintBehavior = m_paintBehavior;
     if (m_paintBehavior == PaintBehaviorNormal)
-        document->invalidateRenderedRectsForMarkersInRect(rect);
+        document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
 
     if (document->printing())
         m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
@@ -1992,10 +2075,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
     if (isTopLevelPainter)
         sCurrentPaintTimeStamp = 0;
 
-#if ENABLE(INSPECTOR)
-    if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
-        timelineAgent->didPaint();
-#endif
+    InspectorInstrumentation::didPaint(cookie);
 }
 
 void FrameView::setPaintBehavior(PaintBehavior behavior)
@@ -2018,7 +2098,7 @@ void FrameView::setNodeToDraw(Node* node)
     m_nodeToDraw = node;
 }
 
-void FrameView::layoutIfNeededRecursive()
+void FrameView::updateLayoutAndStyleIfNeededRecursive()
 {
     // We have to crawl our entire tree looking for any FrameViews that need
     // layout and make sure they are up to date.
@@ -2029,6 +2109,8 @@ void FrameView::layoutIfNeededRecursive()
     // region but then become included later by the second frame adding rects to the dirty region
     // when it lays out.
 
+    m_frame->document()->updateStyleIfNeeded();
+
     if (needsLayout())
         layout();
 
@@ -2037,10 +2119,10 @@ void FrameView::layoutIfNeededRecursive()
     for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
         Widget* widget = (*current).get();
         if (widget->isFrameView())
-            static_cast<FrameView*>(widget)->layoutIfNeededRecursive();
+            static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
     }
 
-    // layoutIfNeededRecursive is called when we need to make sure layout is up-to-date before
+    // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
     // painting, so we need to flush out any deferred repaints too.
     flushDeferredRepaints();
 }
@@ -2056,44 +2138,43 @@ void FrameView::flushDeferredRepaints()
 void FrameView::forceLayout(bool allowSubtree)
 {
     layout(allowSubtree);
-    // We cannot unschedule a pending relayout, since the force can be called with
-    // a tiny rectangle from a drawRect update.  By unscheduling we in effect
-    // "validate" and stop the necessary full repaint from occurring.  Basically any basic
-    // append/remove DHTML is broken by this call.  For now, I have removed the optimization
-    // until we have a better invalidation stategy. -dwh
-    //unscheduleRelayout();
 }
 
-void FrameView::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool _adjustViewSize)
+void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
 {
     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
     // the state of things before and after the layout
     RenderView *root = toRenderView(m_frame->document()->renderer());
     if (root) {
-        // This magic is basically copied from khtmlview::print
-        int pageW = (int)ceilf(minPageWidth);
+        int pageW = ceilf(pageSize.width());
         root->setWidth(pageW);
+        root->setPageHeight(pageSize.height());
         root->setNeedsLayoutAndPrefWidthsRecalc();
         forceLayout();
 
-        // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
-        // maximum page width, we will lay out to the maximum page width and clip extra content.
+        // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
+        // page width when shrunk, we will lay out at maximum shrink and clip extra content.
         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
         // implementation should not do this!
         int rightmostPos = root->rightmostPosition();
-        if (rightmostPos > minPageWidth) {
-            pageW = std::min(rightmostPos, (int)ceilf(maxPageWidth));
+        if (rightmostPos > pageSize.width()) {
+            pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
+            if (pageSize.height())
+                root->setPageHeight(pageW / pageSize.width() * pageSize.height());
             root->setWidth(pageW);
             root->setNeedsLayoutAndPrefWidthsRecalc();
             forceLayout();
+            int docHeight = root->bottomLayoutOverflow();
+            root->clearLayoutOverflow();
+            root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
         }
     }
 
-    if (_adjustViewSize)
+    if (shouldAdjustViewSize)
         adjustViewSize();
 }
 
-void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
+void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
 {
     RenderView* root = m_frame->contentRenderer();
     if (root) {
@@ -2101,10 +2182,12 @@ void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom
         GraphicsContext context((PlatformGraphicsContext*)0);
         root->setTruncatedAt((int)floorf(oldBottom));
         IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
+        root->setPrintRect(dirtyRect);
         root->layer()->paint(&context, dirtyRect);
         *newBottom = root->bestTruncatedAt();
         if (*newBottom == 0)
             *newBottom = oldBottom;
+        root->setPrintRect(IntRect());
     } else
         *newBottom = oldBottom;
 }
@@ -2247,75 +2330,6 @@ IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
     return parentPoint;
 }
 
-bool FrameView::shouldApplyTextZoom() const
-{
-    if (m_zoomFactor == 1)
-        return false;
-    if (!m_frame)
-        return false;
-    Page* page = m_frame->page();
-    return page && page->settings()->zoomMode() == ZoomTextOnly;
-}
-
-bool FrameView::shouldApplyPageZoom() const
-{
-    if (m_zoomFactor == 1)
-        return false;
-    if (!m_frame)
-        return false;
-    Page* page = m_frame->page();
-    return page && page->settings()->zoomMode() == ZoomPage;
-}
-
-void FrameView::setZoomFactor(float percent, ZoomMode mode)
-{
-    if (!m_frame)
-        return;
-
-    Page* page = m_frame->page();
-    if (!page)
-        return;
-
-    if (m_zoomFactor == percent && page->settings()->zoomMode() == mode)
-        return;
-
-    Document* document = m_frame->document();
-    if (!document)
-        return;
-
-#if ENABLE(SVG)
-    // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
-    // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
-    if (document->isSVGDocument()) {
-        if (!static_cast<SVGDocument*>(document)->zoomAndPanEnabled())
-            return;
-        if (document->renderer())
-            document->renderer()->setNeedsLayout(true);
-    }
-#endif
-
-    if (mode == ZoomPage) {
-        // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
-        IntPoint scrollPosition = this->scrollPosition();
-        float percentDifference = (percent / m_zoomFactor);
-        setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
-    }
-
-    m_zoomFactor = percent;
-    page->settings()->setZoomMode(mode);
-
-    document->recalcStyle(Node::Force);
-
-    for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
-        if (FrameView* childView = child->view())
-            childView->setZoomFactor(m_zoomFactor, mode);
-    }
-
-    if (document->renderer() && document->renderer()->needsLayout() && didFirstLayout())
-        layout();
-}
-
-
 // Normal delay
 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
 {