Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: Source/core/frame/FrameView.cpp

Issue 306413002: Rename Repaint to Paint Invalidation Part 2 (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase to master Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org> 3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org> 4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org> 5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) 7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved. 9 * Copyright (C) 2009 Google Inc. All rights reserved.
10 * 10 *
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 87
88 using namespace HTMLNames; 88 using namespace HTMLNames;
89 89
90 double FrameView::s_currentFrameTimeStamp = 0.0; 90 double FrameView::s_currentFrameTimeStamp = 0.0;
91 bool FrameView::s_inPaintContents = false; 91 bool FrameView::s_inPaintContents = false;
92 92
93 // The maximum number of updateWidgets iterations that should be done before ret urning. 93 // The maximum number of updateWidgets iterations that should be done before ret urning.
94 static const unsigned maxUpdateWidgetsIterations = 2; 94 static const unsigned maxUpdateWidgetsIterations = 2;
95 static const double resourcePriorityUpdateDelayAfterScroll = 0.250; 95 static const double resourcePriorityUpdateDelayAfterScroll = 0.250;
96 96
97 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLay er* layer, bool isRelayoutingSubtree, bool didFullRepaint) 97 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLay er* layer, bool isRelayoutingSubtree, bool didFullPaintInvalidation)
98 { 98 {
99 RenderLayer::UpdateLayerPositionsFlags flags = didFullRepaint ? RenderLayer: :NeedsFullRepaintInBacking : RenderLayer::CheckForRepaint; 99 RenderLayer::UpdateLayerPositionsFlags flags = didFullPaintInvalidation ? Re nderLayer::NeedsFullRepaintInBacking : RenderLayer::CheckForRepaint;
100 100
101 if (isRelayoutingSubtree && (layer->isPaginated() || layer->enclosingPaginat ionLayer())) 101 if (isRelayoutingSubtree && (layer->isPaginated() || layer->enclosingPaginat ionLayer()))
102 flags |= RenderLayer::UpdatePagination; 102 flags |= RenderLayer::UpdatePagination;
103 103
104 return flags; 104 return flags;
105 } 105 }
106 106
107 class FrameViewLayoutStateMaintainer { 107 class FrameViewLayoutStateMaintainer {
108 WTF_MAKE_NONCOPYABLE(FrameViewLayoutStateMaintainer); 108 WTF_MAKE_NONCOPYABLE(FrameViewLayoutStateMaintainer);
109 public: 109 public:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 141 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
142 , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired) 142 , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired)
143 , m_isTransparent(false) 143 , m_isTransparent(false)
144 , m_baseBackgroundColor(Color::white) 144 , m_baseBackgroundColor(Color::white)
145 , m_mediaType("screen") 145 , m_mediaType("screen")
146 , m_overflowStatusDirty(true) 146 , m_overflowStatusDirty(true)
147 , m_viewportRenderer(0) 147 , m_viewportRenderer(0)
148 , m_wasScrolledByUser(false) 148 , m_wasScrolledByUser(false)
149 , m_inProgrammaticScroll(false) 149 , m_inProgrammaticScroll(false)
150 , m_safeToPropagateScrollToParent(true) 150 , m_safeToPropagateScrollToParent(true)
151 , m_isTrackingRepaints(false) 151 , m_isTrackingPaintInvalidations(false)
152 , m_scrollCorner(0) 152 , m_scrollCorner(0)
153 , m_shouldAutoSize(false) 153 , m_shouldAutoSize(false)
154 , m_inAutoSize(false) 154 , m_inAutoSize(false)
155 , m_didRunAutosize(false) 155 , m_didRunAutosize(false)
156 , m_hasSoftwareFilters(false) 156 , m_hasSoftwareFilters(false)
157 , m_visibleContentScaleFactor(1) 157 , m_visibleContentScaleFactor(1)
158 , m_inputEventsScaleFactorForEmulation(1) 158 , m_inputEventsScaleFactorForEmulation(1)
159 , m_layoutSizeFixedToFrameSize(true) 159 , m_layoutSizeFixedToFrameSize(true)
160 , m_didScrollTimer(this, &FrameView::didScrollTimerFired) 160 , m_didScrollTimer(this, &FrameView::didScrollTimerFired)
161 { 161 {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 ownerElement->setWidget(nullptr); 213 ownerElement->setWidget(nullptr);
214 } 214 }
215 215
216 void FrameView::reset() 216 void FrameView::reset()
217 { 217 {
218 m_cannotBlitToWindow = false; 218 m_cannotBlitToWindow = false;
219 m_isOverlapped = false; 219 m_isOverlapped = false;
220 m_contentIsOpaque = false; 220 m_contentIsOpaque = false;
221 m_hasPendingLayout = false; 221 m_hasPendingLayout = false;
222 m_layoutSubtreeRoot = 0; 222 m_layoutSubtreeRoot = 0;
223 m_doFullRepaint = false; 223 m_doFullPaintInvalidation = false;
224 m_layoutSchedulingEnabled = true; 224 m_layoutSchedulingEnabled = true;
225 m_inPerformLayout = false; 225 m_inPerformLayout = false;
226 m_canInvalidatePaintDuringPerformLayout = false; 226 m_canInvalidatePaintDuringPerformLayout = false;
227 m_inSynchronousPostLayout = false; 227 m_inSynchronousPostLayout = false;
228 m_layoutCount = 0; 228 m_layoutCount = 0;
229 m_nestedLayoutCount = 0; 229 m_nestedLayoutCount = 0;
230 m_postLayoutTasksTimer.stop(); 230 m_postLayoutTasksTimer.stop();
231 m_updateWidgetsTimer.stop(); 231 m_updateWidgetsTimer.stop();
232 m_firstLayout = true; 232 m_firstLayout = true;
233 m_firstLayoutCallbackPending = false; 233 m_firstLayoutCallbackPending = false;
234 m_wasScrolledByUser = false; 234 m_wasScrolledByUser = false;
235 m_safeToPropagateScrollToParent = true; 235 m_safeToPropagateScrollToParent = true;
236 m_lastViewportSize = IntSize(); 236 m_lastViewportSize = IntSize();
237 m_lastZoomFactor = 1.0f; 237 m_lastZoomFactor = 1.0f;
238 m_isTrackingRepaints = false; 238 m_isTrackingPaintInvalidations = false;
239 m_trackedRepaintRects.clear(); 239 m_trackedPaintInvalidationRects.clear();
240 m_lastPaintTime = 0; 240 m_lastPaintTime = 0;
241 m_paintBehavior = PaintBehaviorNormal; 241 m_paintBehavior = PaintBehaviorNormal;
242 m_isPainting = false; 242 m_isPainting = false;
243 m_visuallyNonEmptyCharacterCount = 0; 243 m_visuallyNonEmptyCharacterCount = 0;
244 m_visuallyNonEmptyPixelCount = 0; 244 m_visuallyNonEmptyPixelCount = 0;
245 m_isVisuallyNonEmpty = false; 245 m_isVisuallyNonEmpty = false;
246 m_firstVisuallyNonEmptyLayoutCallbackPending = true; 246 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
247 m_maintainScrollPositionAnchor = nullptr; 247 m_maintainScrollPositionAnchor = nullptr;
248 m_viewportConstrainedObjects.clear(); 248 m_viewportConstrainedObjects.clear();
249 } 249 }
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 if (!parent()) { 349 if (!parent()) {
350 if (HostWindow* window = hostWindow()) 350 if (HostWindow* window = hostWindow())
351 window->invalidateContentsAndRootView(rect); 351 window->invalidateContentsAndRootView(rect);
352 return; 352 return;
353 } 353 }
354 354
355 RenderPart* renderer = m_frame->ownerRenderer(); 355 RenderPart* renderer = m_frame->ownerRenderer();
356 if (!renderer) 356 if (!renderer)
357 return; 357 return;
358 358
359 IntRect repaintRect = rect; 359 IntRect paintInavlidationRect = rect;
Julien - ping for review 2014/06/03 01:00:20 typo: paintIn*va*lidationRect
dsinclair 2014/06/03 14:06:18 Done.
360 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), 360 paintInavlidationRect.move(renderer->borderLeft() + renderer->paddingLeft(),
361 renderer->borderTop() + renderer->paddingTop()); 361 renderer->borderTop() + renderer->paddingTop());
362 renderer->repaintRectangle(repaintRect); 362 renderer->repaintRectangle(paintInavlidationRect);
363 } 363 }
364 364
365 void FrameView::setFrameRect(const IntRect& newRect) 365 void FrameView::setFrameRect(const IntRect& newRect)
366 { 366 {
367 IntRect oldRect = frameRect(); 367 IntRect oldRect = frameRect();
368 if (newRect == oldRect) 368 if (newRect == oldRect)
369 return; 369 return;
370 370
371 // Autosized font sizes depend on the width of the viewing area. 371 // Autosized font sizes depend on the width of the viewing area.
372 bool autosizerNeedsUpdating = false; 372 bool autosizerNeedsUpdating = false;
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 800
801 // FIXME (crbug.com/256657): Do not do two layouts for text autosizing. 801 // FIXME (crbug.com/256657): Do not do two layouts for text autosizing.
802 rootForThisLayout->layout(); 802 rootForThisLayout->layout();
803 gatherDebugLayoutRects(rootForThisLayout); 803 gatherDebugLayoutRects(rootForThisLayout);
804 804
805 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllIma geResourcePriorities(); 805 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllIma geResourcePriorities();
806 806
807 TextAutosizer* textAutosizer = frame().document()->textAutosizer(); 807 TextAutosizer* textAutosizer = frame().document()->textAutosizer();
808 bool autosized; 808 bool autosized;
809 { 809 {
810 AllowPaintInvalidationScope repaintAllowed(this); 810 AllowPaintInvalidationScope paintInvalidationAllowed(this);
811 autosized = textAutosizer && textAutosizer->processSubtree(rootForThisLa yout); 811 autosized = textAutosizer && textAutosizer->processSubtree(rootForThisLa yout);
812 } 812 }
813 813
814 if (autosized && rootForThisLayout->needsLayout()) { 814 if (autosized && rootForThisLayout->needsLayout()) {
815 TRACE_EVENT0("webkit", "2nd layout due to Text Autosizing"); 815 TRACE_EVENT0("webkit", "2nd layout due to Text Autosizing");
816 UseCounter::count(*frame().document(), UseCounter::TextAutosizingLayout) ; 816 UseCounter::count(*frame().document(), UseCounter::TextAutosizingLayout) ;
817 rootForThisLayout->layout(); 817 rootForThisLayout->layout();
818 gatherDebugLayoutRects(rootForThisLayout); 818 gatherDebugLayoutRects(rootForThisLayout);
819 } 819 }
820 820
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 calculateScrollbarModesForLayoutAndSetViewportRenderer(hMode, vMode); 920 calculateScrollbarModesForLayoutAndSetViewportRenderer(hMode, vMode);
921 921
922 if (!inSubtreeLayout) { 922 if (!inSubtreeLayout) {
923 // Now set our scrollbar state for the layout. 923 // Now set our scrollbar state for the layout.
924 ScrollbarMode currentHMode = horizontalScrollbarMode(); 924 ScrollbarMode currentHMode = horizontalScrollbarMode();
925 ScrollbarMode currentVMode = verticalScrollbarMode(); 925 ScrollbarMode currentVMode = verticalScrollbarMode();
926 926
927 if (m_firstLayout) { 927 if (m_firstLayout) {
928 setScrollbarsSuppressed(true); 928 setScrollbarsSuppressed(true);
929 929
930 m_doFullRepaint = true; 930 m_doFullPaintInvalidation = true;
931 m_firstLayout = false; 931 m_firstLayout = false;
932 m_firstLayoutCallbackPending = true; 932 m_firstLayoutCallbackPending = true;
933 m_lastViewportSize = layoutSize(IncludeScrollbars); 933 m_lastViewportSize = layoutSize(IncludeScrollbars);
934 m_lastZoomFactor = rootForThisLayout->style()->zoom(); 934 m_lastZoomFactor = rootForThisLayout->style()->zoom();
935 935
936 // Set the initial vMode to AlwaysOn if we're auto. 936 // Set the initial vMode to AlwaysOn if we're auto.
937 if (vMode == ScrollbarAuto) 937 if (vMode == ScrollbarAuto)
938 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. 938 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
939 // Set the initial hMode to AlwaysOff if we're auto. 939 // Set the initial hMode to AlwaysOff if we're auto.
940 if (hMode == ScrollbarAuto) 940 if (hMode == ScrollbarAuto)
(...skipping 11 matching lines...) Expand all
952 952
953 if (oldSize != m_size && !m_firstLayout) { 953 if (oldSize != m_size && !m_firstLayout) {
954 RenderBox* rootRenderer = document->documentElement() ? document ->documentElement()->renderBox() : 0; 954 RenderBox* rootRenderer = document->documentElement() ? document ->documentElement()->renderBox() : 0;
955 RenderBox* bodyRenderer = rootRenderer && document->body() ? doc ument->body()->renderBox() : 0; 955 RenderBox* bodyRenderer = rootRenderer && document->body() ? doc ument->body()->renderBox() : 0;
956 if (bodyRenderer && bodyRenderer->stretchesToViewport()) 956 if (bodyRenderer && bodyRenderer->stretchesToViewport())
957 bodyRenderer->setChildNeedsLayout(); 957 bodyRenderer->setChildNeedsLayout();
958 else if (rootRenderer && rootRenderer->stretchesToViewport()) 958 else if (rootRenderer && rootRenderer->stretchesToViewport())
959 rootRenderer->setChildNeedsLayout(); 959 rootRenderer->setChildNeedsLayout();
960 } 960 }
961 961
962 // We need to set m_doFullRepaint before triggering layout as Render Object::checkForRepaint 962 // We need to set m_doFullPaintInvalidation before triggering layout as RenderObject::checkForRepaint
963 // checks the boolean to disable local repaints. 963 // checks the boolean to disable local paint invalidations.
964 m_doFullRepaint |= renderView()->shouldDoFullRepaintForNextLayout(); 964 m_doFullPaintInvalidation |= renderView()->shouldDoFullRepaintForNex tLayout();
965 } 965 }
966 966
967 layer = rootForThisLayout->enclosingLayer(); 967 layer = rootForThisLayout->enclosingLayer();
968 968
969 performLayout(rootForThisLayout, inSubtreeLayout); 969 performLayout(rootForThisLayout, inSubtreeLayout);
970 970
971 m_layoutSubtreeRoot = 0; 971 m_layoutSubtreeRoot = 0;
972 } // Reset m_layoutSchedulingEnabled to its previous value. 972 } // Reset m_layoutSchedulingEnabled to its previous value.
973 973
974 if (!inSubtreeLayout && !toRenderView(rootForThisLayout)->document().printin g()) 974 if (!inSubtreeLayout && !toRenderView(rootForThisLayout)->document().printin g())
975 adjustViewSize(); 975 adjustViewSize();
976 976
977 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPos itionFlags(layer, inSubtreeLayout, m_doFullRepaint)); 977 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPos itionFlags(layer, inSubtreeLayout, m_doFullPaintInvalidation));
978 renderView()->compositor()->setNeedsCompositingUpdate(CompositingUpdateAfter Layout); 978 renderView()->compositor()->setNeedsCompositingUpdate(CompositingUpdateAfter Layout);
979 979
980 m_layoutCount++; 980 m_layoutCount++;
981 981
982 if (AXObjectCache* cache = rootForThisLayout->document().axObjectCache()) { 982 if (AXObjectCache* cache = rootForThisLayout->document().axObjectCache()) {
983 const KURL& url = rootForThisLayout->document().url(); 983 const KURL& url = rootForThisLayout->document().url();
984 if (url.isValid() && !url.isAboutBlankURL()) 984 if (url.isValid() && !url.isAboutBlankURL())
985 cache->handleLayoutComplete(rootForThisLayout); 985 cache->handleLayoutComplete(rootForThisLayout);
986 } 986 }
987 updateAnnotatedRegions(); 987 updateAnnotatedRegions();
988 988
989 ASSERT(!rootForThisLayout->needsLayout()); 989 ASSERT(!rootForThisLayout->needsLayout());
990 990
991 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) 991 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
992 updateOverflowStatus(layoutSize().width() < contentsWidth(), layoutSize( ).height() < contentsHeight()); 992 updateOverflowStatus(layoutSize().width() < contentsWidth(), layoutSize( ).height() < contentsHeight());
993 993
994 scheduleOrPerformPostLayoutTasks(); 994 scheduleOrPerformPostLayoutTasks();
995 995
996 TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", " endData", InspectorLayoutEvent::endData(rootForThisLayout)); 996 TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", " endData", InspectorLayoutEvent::endData(rootForThisLayout));
997 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeli ne migrates to tracing. 997 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeli ne migrates to tracing.
998 InspectorInstrumentation::didLayout(cookie, rootForThisLayout); 998 InspectorInstrumentation::didLayout(cookie, rootForThisLayout);
999 999
1000 m_nestedLayoutCount--; 1000 m_nestedLayoutCount--;
1001 if (m_nestedLayoutCount) 1001 if (m_nestedLayoutCount)
1002 return; 1002 return;
1003 1003
1004 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) { 1004 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
1005 invalidateTree(rootForThisLayout); 1005 invalidateTree(rootForThisLayout);
1006 } else if (m_doFullRepaint) { 1006 } else if (m_doFullPaintInvalidation) {
1007 // FIXME: This isn't really right, since the RenderView doesn't fully en compass 1007 // FIXME: This isn't really right, since the RenderView doesn't fully en compass
1008 // the visibleContentRect(). It just happens to work out most of the tim e, 1008 // the visibleContentRect(). It just happens to work out most of the tim e,
1009 // since first layouts and printing don't have you scrolled anywhere. 1009 // since first layouts and printing don't have you scrolled anywhere.
1010 renderView()->repaint(); 1010 renderView()->repaint();
1011 } 1011 }
1012 1012
1013 m_doFullRepaint = false; 1013 m_doFullPaintInvalidation = false;
1014 1014
1015 #ifndef NDEBUG 1015 #ifndef NDEBUG
1016 // Post-layout assert that nobody was re-marked as needing layout during lay out. 1016 // Post-layout assert that nobody was re-marked as needing layout during lay out.
1017 document->renderView()->assertSubtreeIsLaidOut(); 1017 document->renderView()->assertSubtreeIsLaidOut();
1018 #endif 1018 #endif
1019 1019
1020 // FIXME: It should be not possible to remove the FrameView from the frame/p age during layout 1020 // FIXME: It should be not possible to remove the FrameView from the frame/p age during layout
1021 // however m_inPerformLayout is not set for most of this function, so none o f our RELEASE_ASSERTS 1021 // however m_inPerformLayout is not set for most of this function, so none o f our RELEASE_ASSERTS
1022 // in LocalFrame/Page will fire. One of the post-layout tasks is disconnecti ng the LocalFrame from 1022 // in LocalFrame/Page will fire. One of the post-layout tasks is disconnecti ng the LocalFrame from
1023 // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.ht ml 1023 // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.ht ml
1024 // necessitating this check here. 1024 // necessitating this check here.
1025 // ASSERT(frame()->page()); 1025 // ASSERT(frame()->page());
1026 if (frame().page()) 1026 if (frame().page())
1027 frame().page()->chrome().client().layoutUpdated(m_frame.get()); 1027 frame().page()->chrome().client().layoutUpdated(m_frame.get());
1028 } 1028 }
1029 1029
1030 // The plan is to move to compositor-queried repainting, in which case this 1030 // The plan is to move to compositor-queried paint invalidation, in which case t his
1031 // method would setNeedsRedraw on the GraphicsLayers with invalidations and 1031 // method would setNeedsRedraw on the GraphicsLayers with invalidations and
1032 // let the compositor pick which to actually draw. 1032 // let the compositor pick which to actually draw.
1033 // See http://crbug.com/306706 1033 // See http://crbug.com/306706
1034 void FrameView::invalidateTree(RenderObject* root) 1034 void FrameView::invalidateTree(RenderObject* root)
1035 { 1035 {
1036 ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled()); 1036 ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
1037 ASSERT(!root->needsLayout()); 1037 ASSERT(!root->needsLayout());
1038 // We should only repaint for the outer most layout. This works as 1038 // We should only invalidate paints for the outer most layout. This works as
1039 // we continue to track repaint rects until this function is called. 1039 // we continue to track paint invalidation rects until this function is call ed.
1040 ASSERT(!m_nestedLayoutCount); 1040 ASSERT(!m_nestedLayoutCount);
1041 1041
1042 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "FrameView::re paintTree", 1042 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "FrameView::in validateTree",
1043 "root", TRACE_STR_COPY(root->debugName().ascii().data())); 1043 "root", TRACE_STR_COPY(root->debugName().ascii().data()));
1044 1044
1045 // FIXME: really, we're in the repaint phase here, and the compositing queri es are legal. 1045 // FIXME: really, we're in the paint invalidation phase here, and the compos iting queries are legal.
1046 // Until those states are fully fledged, I'll just disable the ASSERTS. 1046 // Until those states are fully fledged, I'll just disable the ASSERTS.
1047 DisableCompositingQueryAsserts compositingQueryAssertsDisabler; 1047 DisableCompositingQueryAsserts compositingQueryAssertsDisabler;
1048 1048
1049 RootLayoutStateScope rootLayoutStateScope(*root); 1049 RootLayoutStateScope rootLayoutStateScope(*root);
1050 1050
1051 root->invalidateTreeAfterLayout(*root->containerForRepaint()); 1051 root->invalidateTreeAfterLayout(*root->containerForRepaint());
1052 1052
1053 // Repaint the frameviews scrollbars if needed 1053 // Invalidate the paint of the frameviews scrollbars if needed
1054 if (hasVerticalBarDamage()) 1054 if (hasVerticalBarDamage())
1055 invalidateRect(verticalBarDamage()); 1055 invalidateRect(verticalBarDamage());
1056 if (hasHorizontalBarDamage()) 1056 if (hasHorizontalBarDamage())
1057 invalidateRect(horizontalBarDamage()); 1057 invalidateRect(horizontalBarDamage());
1058 resetScrollbarDamage(); 1058 resetScrollbarDamage();
1059 } 1059 }
1060 1060
1061 DocumentLifecycle& FrameView::lifecycle() const 1061 DocumentLifecycle& FrameView::lifecycle() const
1062 { 1062 {
1063 return m_frame->document()->lifecycle(); 1063 return m_frame->document()->lifecycle();
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 if (FrameView* view = child->view()) 1365 if (FrameView* view = child->view())
1366 view->scrollContentsIfNeededRecursive(); 1366 view->scrollContentsIfNeededRecursive();
1367 } 1367 }
1368 } 1368 }
1369 1369
1370 void FrameView::scrollContentsIfNeeded() 1370 void FrameView::scrollContentsIfNeeded()
1371 { 1371 {
1372 bool didScroll = !pendingScrollDelta().isZero(); 1372 bool didScroll = !pendingScrollDelta().isZero();
1373 ScrollView::scrollContentsIfNeeded(); 1373 ScrollView::scrollContentsIfNeeded();
1374 if (didScroll) 1374 if (didScroll)
1375 updateFixedElementRepaintRectsAfterScroll(); 1375 updateFixedElementPaintInvalidationRectsAfterScroll();
1376 } 1376 }
1377 1377
1378 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect & rectToScroll, const IntRect& clipRect) 1378 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect & rectToScroll, const IntRect& clipRect)
1379 { 1379 {
1380 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty() ) { 1380 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty() ) {
1381 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1381 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1382 return true; 1382 return true;
1383 } 1383 }
1384 1384
1385 const bool isCompositedContentLayer = contentsInCompositedLayer(); 1385 const bool isCompositedContentLayer = contentsInCompositedLayer();
1386 1386
1387 // Get the rects of the fixed objects visible in the rectToScroll 1387 // Get the rects of the fixed objects visible in the rectToScroll
1388 Region regionToUpdate; 1388 Region regionToUpdate;
1389 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObje cts->end(); 1389 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObje cts->end();
1390 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrained Objects->begin(); it != end; ++it) { 1390 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrained Objects->begin(); it != end; ++it) {
1391 RenderObject* renderer = *it; 1391 RenderObject* renderer = *it;
1392 // m_viewportConstrainedObjects should not contain non-viewport constrai ned objects. 1392 // m_viewportConstrainedObjects should not contain non-viewport constrai ned objects.
1393 ASSERT(renderer->style()->hasViewportConstrainedPosition()); 1393 ASSERT(renderer->style()->hasViewportConstrainedPosition());
1394 1394
1395 // Fixed items should always have layers. 1395 // Fixed items should always have layers.
1396 ASSERT(renderer->hasLayer()); 1396 ASSERT(renderer->hasLayer());
1397 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); 1397 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1398 1398
1399 // Layers that paint into their ancestor or into a grouped backing will still need 1399 // Layers that paint into their ancestor or into a grouped backing will still need
1400 // to apply a repaint invalidation. If the layer paints into its own bac king, then 1400 // to apply a paint invalidation. If the layer paints into its own backi ng, then
1401 // it does not need repainting just to scroll. 1401 // it does not need paint invalidation just to scroll.
1402 if (layer->compositingState() == PaintsIntoOwnBacking) 1402 if (layer->compositingState() == PaintsIntoOwnBacking)
1403 continue; 1403 continue;
1404 1404
1405 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotC ompositedForBoundsOutOfView 1405 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotC ompositedForBoundsOutOfView
1406 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::N otCompositedForNoVisibleContent) { 1406 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::N otCompositedForNoVisibleContent) {
1407 // Don't invalidate for invisible fixed layers. 1407 // Don't invalidate for invisible fixed layers.
1408 continue; 1408 continue;
1409 } 1409 }
1410 1410
1411 if (layer->hasAncestorWithFilterOutsets()) { 1411 if (layer->hasAncestorWithFilterOutsets()) {
1412 // If the fixed layer has a blur/drop-shadow filter applied on at le ast one of its parents, we cannot 1412 // If the fixed layer has a blur/drop-shadow filter applied on at le ast one of its parents, we cannot
1413 // scroll using the fast path, otherwise the outsets of the filter w ill be moved around the page. 1413 // scroll using the fast path, otherwise the outsets of the filter w ill be moved around the page.
1414 return false; 1414 return false;
1415 } 1415 }
1416 1416
1417 IntRect updateRect = pixelSnappedIntRect(layer->repainter().repaintRectI ncludingNonCompositingDescendants()); 1417 IntRect updateRect = pixelSnappedIntRect(layer->repainter().repaintRectI ncludingNonCompositingDescendants());
1418 1418
1419 RenderLayer* enclosingCompositingLayer = layer->enclosingCompositingLaye r(ExcludeSelf); 1419 RenderLayer* enclosingCompositingLayer = layer->enclosingCompositingLaye r(ExcludeSelf);
1420 if (enclosingCompositingLayer && !enclosingCompositingLayer->renderer()- >isRenderView()) { 1420 if (enclosingCompositingLayer && !enclosingCompositingLayer->renderer()- >isRenderView()) {
1421 // If the fixed-position layer is contained by a composited layer th at is not its containing block, 1421 // If the fixed-position layer is contained by a composited layer th at is not its containing block,
1422 // then we have to invalidate that enclosing layer, not the RenderVi ew. 1422 // then we have to invalidate that enclosing layer, not the RenderVi ew.
1423 // FIXME: Why do we need to issue this invalidation? Won't the fixed position element just scroll 1423 // FIXME: Why do we need to issue this invalidation? Won't the fixed position element just scroll
1424 // with the enclosing layer. 1424 // with the enclosing layer.
1425 updateRect.moveBy(scrollPosition()); 1425 updateRect.moveBy(scrollPosition());
1426 IntRect previousRect = updateRect; 1426 IntRect previousRect = updateRect;
1427 previousRect.move(scrollDelta); 1427 previousRect.move(scrollDelta);
1428 updateRect.unite(previousRect); 1428 updateRect.unite(previousRect);
1429 enclosingCompositingLayer->repainter().setBackingNeedsRepaintInRect( updateRect); 1429 enclosingCompositingLayer->repainter().setBackingNeedsRepaintInRect( updateRect);
1430 } else { 1430 } else {
1431 // Coalesce the repaints that will be issued to the renderView. 1431 // Coalesce the paint invalidations that will be issued to the rende rView.
1432 updateRect = contentsToRootView(updateRect); 1432 updateRect = contentsToRootView(updateRect);
1433 if (!isCompositedContentLayer && clipsRepaints()) 1433 if (!isCompositedContentLayer && clipsPaintInvalidations())
1434 updateRect.intersect(rectToScroll); 1434 updateRect.intersect(rectToScroll);
1435 if (!updateRect.isEmpty()) 1435 if (!updateRect.isEmpty())
1436 regionToUpdate.unite(updateRect); 1436 regionToUpdate.unite(updateRect);
1437 } 1437 }
1438 } 1438 }
1439 1439
1440 // 1) scroll 1440 // 1) scroll
1441 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 1441 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1442 1442
1443 // 2) update the area of fixed objects that has been invalidated 1443 // 2) update the area of fixed objects that has been invalidated
1444 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects(); 1444 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1445 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size(); 1445 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1446 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) { 1446 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1447 IntRect updateRect = subRectsToUpdate[i]; 1447 IntRect updateRect = subRectsToUpdate[i];
1448 IntRect scrolledRect = updateRect; 1448 IntRect scrolledRect = updateRect;
1449 scrolledRect.move(-scrollDelta); 1449 scrolledRect.move(-scrollDelta);
1450 updateRect.unite(scrolledRect); 1450 updateRect.unite(scrolledRect);
1451 if (isCompositedContentLayer) { 1451 if (isCompositedContentLayer) {
1452 updateRect = rootViewToContents(updateRect); 1452 updateRect = rootViewToContents(updateRect);
1453 ASSERT(renderView()); 1453 ASSERT(renderView());
1454 renderView()->layer()->repainter().setBackingNeedsRepaintInRect(upda teRect); 1454 renderView()->layer()->repainter().setBackingNeedsRepaintInRect(upda teRect);
1455 continue; 1455 continue;
1456 } 1456 }
1457 if (clipsRepaints()) 1457 if (clipsPaintInvalidations())
1458 updateRect.intersect(rectToScroll); 1458 updateRect.intersect(rectToScroll);
1459 hostWindow()->invalidateContentsAndRootView(updateRect); 1459 hostWindow()->invalidateContentsAndRootView(updateRect);
1460 } 1460 }
1461 1461
1462 return true; 1462 return true;
1463 } 1463 }
1464 1464
1465 void FrameView::scrollContentsSlowPath(const IntRect& updateRect) 1465 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1466 { 1466 {
1467 if (contentsInCompositedLayer()) { 1467 if (contentsInCompositedLayer()) {
(...skipping 27 matching lines...) Expand all
1495 1495
1496 void FrameView::restoreScrollbar() 1496 void FrameView::restoreScrollbar()
1497 { 1497 {
1498 setScrollbarsSuppressed(false); 1498 setScrollbarsSuppressed(false);
1499 } 1499 }
1500 1500
1501 bool FrameView::scrollToFragment(const KURL& url) 1501 bool FrameView::scrollToFragment(const KURL& url)
1502 { 1502 {
1503 // If our URL has no ref, then we have no place we need to jump to. 1503 // If our URL has no ref, then we have no place we need to jump to.
1504 // OTOH If CSS target was set previously, we want to set it to 0, recalc 1504 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1505 // and possibly repaint because :target pseudo class may have been 1505 // and possibly paint invalidation because :target pseudo class may have bee n
1506 // set (see bug 11321). 1506 // set (see bug 11321).
1507 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) 1507 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1508 return false; 1508 return false;
1509 1509
1510 String fragmentIdentifier = url.fragmentIdentifier(); 1510 String fragmentIdentifier = url.fragmentIdentifier();
1511 if (scrollToAnchor(fragmentIdentifier)) 1511 if (scrollToAnchor(fragmentIdentifier))
1512 return true; 1512 return true;
1513 1513
1514 // Try again after decoding the ref, based on the document's encoding. 1514 // Try again after decoding the ref, based on the document's encoding.
1515 if (m_frame->document()->encoding().isValid()) 1515 if (m_frame->document()->encoding().isValid())
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 if (RenderView* renderView = this->renderView()) 1689 if (RenderView* renderView = this->renderView())
1690 renderView->layer()->updateLayerPositionsAfterDocumentScroll(); 1690 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1691 } 1691 }
1692 1692
1693 // Compositing layers may change after scrolling. 1693 // Compositing layers may change after scrolling.
1694 // FIXME: Maybe no longer needed after we land squashing and kill overlap te sting? 1694 // FIXME: Maybe no longer needed after we land squashing and kill overlap te sting?
1695 if (RenderView* renderView = this->renderView()) 1695 if (RenderView* renderView = this->renderView())
1696 renderView->compositor()->setNeedsCompositingUpdate(CompositingUpdateOnS croll); 1696 renderView->compositor()->setNeedsCompositingUpdate(CompositingUpdateOnS croll);
1697 } 1697 }
1698 1698
1699 void FrameView::updateFixedElementRepaintRectsAfterScroll() 1699 void FrameView::updateFixedElementPaintInvalidationRectsAfterScroll()
1700 { 1700 {
1701 if (!hasViewportConstrainedObjects()) 1701 if (!hasViewportConstrainedObjects())
1702 return; 1702 return;
1703 1703
1704 // Update the repaint rects for fixed elements after scrolling and invalidat ion to reflect 1704 // Update the paint invalidation rects for fixed elements after scrolling an d invalidation to reflect
1705 // the new scroll position. 1705 // the new scroll position.
1706 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObje cts->end(); 1706 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObje cts->end();
1707 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrained Objects->begin(); it != end; ++it) { 1707 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrained Objects->begin(); it != end; ++it) {
1708 RenderObject* renderer = *it; 1708 RenderObject* renderer = *it;
1709 // m_viewportConstrainedObjects should not contain non-viewport constrai ned objects. 1709 // m_viewportConstrainedObjects should not contain non-viewport constrai ned objects.
1710 ASSERT(renderer->style()->hasViewportConstrainedPosition()); 1710 ASSERT(renderer->style()->hasViewportConstrainedPosition());
1711 1711
1712 // Fixed items should always have layers. 1712 // Fixed items should always have layers.
1713 ASSERT(renderer->hasLayer()); 1713 ASSERT(renderer->hasLayer());
1714 1714
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 } 1749 }
1750 1750
1751 HostWindow* FrameView::hostWindow() const 1751 HostWindow* FrameView::hostWindow() const
1752 { 1752 {
1753 Page* page = frame().page(); 1753 Page* page = frame().page();
1754 if (!page) 1754 if (!page)
1755 return 0; 1755 return 0;
1756 return &page->chrome(); 1756 return &page->chrome();
1757 } 1757 }
1758 1758
1759 void FrameView::repaintContentRectangle(const IntRect& r) 1759 void FrameView::invalidatedContentRectangleForPaint(const IntRect& r)
1760 { 1760 {
1761 ASSERT(repaintAllowed()); 1761 ASSERT(paintInvalidationAllowed());
Julien - ping for review 2014/06/03 01:00:20 I didn't catch that earlier but this should have a
dsinclair 2014/06/03 14:06:18 Done.
1762 ASSERT(!m_frame->ownerElement()); 1762 ASSERT(!m_frame->ownerElement());
1763 1763
1764 if (m_isTrackingRepaints) { 1764 if (m_isTrackingPaintInvalidations) {
1765 IntRect repaintRect = r; 1765 IntRect paintInvalidationRect = r;
1766 repaintRect.move(-scrollOffset()); 1766 paintInvalidationRect.move(-scrollOffset());
1767 m_trackedRepaintRects.append(repaintRect); 1767 m_trackedPaintInvalidationRects.append(paintInvalidationRect);
1768 // FIXME: http://crbug.com/368518. Eventually, repaintContentRectangle 1768 // FIXME: http://crbug.com/368518. Eventually, invalidateContentRectangl eForPaint
1769 // is going away entirely once all layout tests are FCM. In the short 1769 // is going away entirely once all layout tests are FCM. In the short
1770 // term, no code should be tracking non-composited FrameView repaints. 1770 // term, no code should be tracking non-composited FrameView paint inval idations.
1771 RELEASE_ASSERT_NOT_REACHED(); 1771 RELEASE_ASSERT_NOT_REACHED();
1772 } 1772 }
1773 1773
1774 ScrollView::repaintContentRectangle(r); 1774 ScrollView::invalidatedContentRectangleForPaint(r);
1775 } 1775 }
1776 1776
1777 void FrameView::contentsResized() 1777 void FrameView::contentsResized()
1778 { 1778 {
1779 if (m_frame->isMainFrame() && m_frame->document()) { 1779 if (m_frame->isMainFrame() && m_frame->document()) {
1780 if (FastTextAutosizer* textAutosizer = m_frame->document()->fastTextAuto sizer()) 1780 if (FastTextAutosizer* textAutosizer = m_frame->document()->fastTextAuto sizer())
1781 textAutosizer->updatePageInfoInAllFrames(); 1781 textAutosizer->updatePageInfoInAllFrames();
1782 } 1782 }
1783 1783
1784 ScrollView::contentsResized(); 1784 ScrollView::contentsResized();
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
3111 -renderer->borderTop() - renderer->paddingTop()); 3111 -renderer->borderTop() - renderer->paddingTop());
3112 return point; 3112 return point;
3113 } 3113 }
3114 3114
3115 return Widget::convertFromContainingView(parentPoint); 3115 return Widget::convertFromContainingView(parentPoint);
3116 } 3116 }
3117 3117
3118 return parentPoint; 3118 return parentPoint;
3119 } 3119 }
3120 3120
3121 void FrameView::setTracksRepaints(bool trackRepaints) 3121 void FrameView::setTracksPaintInvalidations(bool trackPaintInvalidations)
3122 { 3122 {
3123 if (trackRepaints == m_isTrackingRepaints) 3123 if (trackPaintInvalidations == m_isTrackingPaintInvalidations)
3124 return; 3124 return;
3125 3125
3126 for (LocalFrame* frame = m_frame->tree().top(); frame; frame = frame->tree() .traverseNext()) { 3126 for (LocalFrame* frame = m_frame->tree().top(); frame; frame = frame->tree() .traverseNext()) {
3127 if (RenderView* renderView = frame->contentRenderer()) 3127 if (RenderView* renderView = frame->contentRenderer())
3128 renderView->compositor()->setTracksRepaints(trackRepaints); 3128 renderView->compositor()->setTracksRepaints(trackPaintInvalidations) ;
3129 } 3129 }
3130 3130
3131 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), 3131 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
3132 "FrameView::setTracksRepaints", "enabled", trackRepaints); 3132 "FrameView::setTracksPaintInvalidations", "enabled", trackPaintInvalidat ions);
3133 3133
3134 resetTrackedRepaints(); 3134 resetTrackedPaintInvalidations();
3135 m_isTrackingRepaints = trackRepaints; 3135 m_isTrackingPaintInvalidations = trackPaintInvalidations;
3136 } 3136 }
3137 3137
3138 void FrameView::resetTrackedRepaints() 3138 void FrameView::resetTrackedPaintInvalidations()
3139 { 3139 {
3140 m_trackedRepaintRects.clear(); 3140 m_trackedPaintInvalidationRects.clear();
3141 if (RenderView* renderView = this->renderView()) 3141 if (RenderView* renderView = this->renderView())
3142 renderView->compositor()->resetTrackedRepaintRects(); 3142 renderView->compositor()->resetTrackedRepaintRects();
3143 } 3143 }
3144 3144
3145 String FrameView::trackedRepaintRectsAsText() const 3145 String FrameView::trackedPaintInvalidationRectsAsText() const
3146 { 3146 {
3147 TextStream ts; 3147 TextStream ts;
3148 if (!m_trackedRepaintRects.isEmpty()) { 3148 if (!m_trackedPaintInvalidationRects.isEmpty()) {
3149 ts << "(repaint rects\n"; 3149 ts << "(repaint rects\n";
3150 for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i) 3150 for (size_t i = 0; i < m_trackedPaintInvalidationRects.size(); ++i)
3151 ts << " (rect " << m_trackedRepaintRects[i].x() << " " << m_tracked RepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_track edRepaintRects[i].height() << ")\n"; 3151 ts << " (rect " << m_trackedPaintInvalidationRects[i].x() << " " << m_trackedPaintInvalidationRects[i].y() << " " << m_trackedPaintInvalidationRect s[i].width() << " " << m_trackedPaintInvalidationRects[i].height() << ")\n";
3152 ts << ")\n"; 3152 ts << ")\n";
3153 } 3153 }
3154 return ts.release(); 3154 return ts.release();
3155 } 3155 }
3156 3156
3157 void FrameView::addResizerArea(RenderBox& resizerBox) 3157 void FrameView::addResizerArea(RenderBox& resizerBox)
3158 { 3158 {
3159 if (!m_resizerAreas) 3159 if (!m_resizerAreas)
3160 m_resizerAreas = adoptPtr(new ResizerAreaSet); 3160 m_resizerAreas = adoptPtr(new ResizerAreaSet);
3161 m_resizerAreas->add(&resizerBox); 3161 m_resizerAreas->add(&resizerBox);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3276 void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation o rientation) 3276 void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation o rientation)
3277 { 3277 {
3278 ScrollableArea::willRemoveScrollbar(scrollbar, orientation); 3278 ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
3279 if (AXObjectCache* cache = axObjectCache()) { 3279 if (AXObjectCache* cache = axObjectCache()) {
3280 cache->remove(scrollbar); 3280 cache->remove(scrollbar);
3281 cache->handleScrollbarUpdate(this); 3281 cache->handleScrollbarUpdate(this);
3282 } 3282 }
3283 } 3283 }
3284 3284
3285 } // namespace WebCore 3285 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698