| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/PaintLayer.h" | 5 #include "core/paint/PaintLayer.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutBoxModelObject.h" | 7 #include "core/layout/LayoutBoxModelObject.h" |
| 8 #include "core/layout/LayoutTestHelper.h" | 8 #include "core/layout/LayoutTestHelper.h" |
| 9 #include "core/layout/LayoutView.h" | 9 #include "core/layout/LayoutView.h" |
| 10 #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h" |
| 10 | 11 |
| 11 namespace blink { | 12 namespace blink { |
| 12 | 13 |
| 13 using PaintLayerTest = RenderingTest; | 14 typedef std::pair<bool, bool> SlimmingPaintAndRootLayerScrolling; |
| 15 class PaintLayerTest |
| 16 : public ::testing::WithParamInterface<SlimmingPaintAndRootLayerScrolling>, |
| 17 private ScopedSlimmingPaintV2ForTest, |
| 18 private ScopedRootLayerScrollingForTest, |
| 19 public RenderingTest { |
| 20 public: |
| 21 PaintLayerTest() |
| 22 : ScopedSlimmingPaintV2ForTest(GetParam().first), |
| 23 ScopedRootLayerScrollingForTest(GetParam().second), |
| 24 RenderingTest(SingleChildFrameLoaderClient::create()) {} |
| 25 }; |
| 14 | 26 |
| 15 TEST_F(PaintLayerTest, CompositedBoundsAbsPosGrandchild) { | 27 SlimmingPaintAndRootLayerScrolling foo[] = { |
| 28 SlimmingPaintAndRootLayerScrolling(false, false), |
| 29 SlimmingPaintAndRootLayerScrolling(true, false), |
| 30 SlimmingPaintAndRootLayerScrolling(false, true), |
| 31 SlimmingPaintAndRootLayerScrolling(true, true)}; |
| 32 |
| 33 INSTANTIATE_TEST_CASE_P(All, PaintLayerTest, ::testing::ValuesIn(foo)); |
| 34 |
| 35 TEST_P(PaintLayerTest, CompositedBoundsAbsPosGrandchild) { |
| 36 // TODO(chrishtr): fix this test for SPv2 |
| 37 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 38 return; |
| 39 |
| 16 setBodyInnerHTML( | 40 setBodyInnerHTML( |
| 17 " <div id='parent'><div id='absposparent'><div id='absposchild'>" | 41 " <div id='parent'><div id='absposparent'><div id='absposchild'>" |
| 18 " </div></div></div>" | 42 " </div></div></div>" |
| 19 "<style>" | 43 "<style>" |
| 20 " #parent { position: absolute; z-index: 0; overflow: hidden;" | 44 " #parent { position: absolute; z-index: 0; overflow: hidden;" |
| 21 " background: lightgray; width: 150px; height: 150px;" | 45 " background: lightgray; width: 150px; height: 150px;" |
| 22 " will-change: transform; }" | 46 " will-change: transform; }" |
| 23 " #absposparent { position: absolute; z-index: 0; }" | 47 " #absposparent { position: absolute; z-index: 0; }" |
| 24 " #absposchild { position: absolute; top: 0px; left: 0px; height: 200px;" | 48 " #absposchild { position: absolute; top: 0px; left: 0px; height: 200px;" |
| 25 " width: 200px; background: lightblue; }</style>"); | 49 " width: 200px; background: lightblue; }</style>"); |
| 26 | 50 |
| 27 PaintLayer* parentLayer = | 51 PaintLayer* parentLayer = |
| 28 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); | 52 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); |
| 29 // Since "absposchild" is clipped by "parent", it should not expand the | 53 // Since "absposchild" is clipped by "parent", it should not expand the |
| 30 // composited bounds for "parent" beyond its intrinsic size of 150x150. | 54 // composited bounds for "parent" beyond its intrinsic size of 150x150. |
| 31 EXPECT_EQ(LayoutRect(0, 0, 150, 150), | 55 EXPECT_EQ(LayoutRect(0, 0, 150, 150), |
| 32 parentLayer->boundingBoxForCompositing()); | 56 parentLayer->boundingBoxForCompositing()); |
| 33 } | 57 } |
| 34 | 58 |
| 35 TEST_F(PaintLayerTest, PaintingExtentReflection) { | 59 TEST_P(PaintLayerTest, PaintingExtentReflection) { |
| 36 setBodyInnerHTML( | 60 setBodyInnerHTML( |
| 37 "<div id='target' style='background-color: blue; position: absolute;" | 61 "<div id='target' style='background-color: blue; position: absolute;" |
| 38 " width: 110px; height: 120px; top: 40px; left: 60px;" | 62 " width: 110px; height: 120px; top: 40px; left: 60px;" |
| 39 " -webkit-box-reflect: below 3px'>" | 63 " -webkit-box-reflect: below 3px'>" |
| 40 "</div>"); | 64 "</div>"); |
| 41 | 65 |
| 42 PaintLayer* layer = | 66 PaintLayer* layer = |
| 43 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); | 67 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 44 EXPECT_EQ( | 68 EXPECT_EQ( |
| 45 LayoutRect(60, 40, 110, 243), | 69 LayoutRect(60, 40, 110, 243), |
| 46 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); | 70 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); |
| 47 } | 71 } |
| 48 | 72 |
| 49 TEST_F(PaintLayerTest, PaintingExtentReflectionWithTransform) { | 73 TEST_P(PaintLayerTest, PaintingExtentReflectionWithTransform) { |
| 50 setBodyInnerHTML( | 74 setBodyInnerHTML( |
| 51 "<div id='target' style='background-color: blue; position: absolute;" | 75 "<div id='target' style='background-color: blue; position: absolute;" |
| 52 " width: 110px; height: 120px; top: 40px; left: 60px;" | 76 " width: 110px; height: 120px; top: 40px; left: 60px;" |
| 53 " -webkit-box-reflect: below 3px; transform: translateX(30px)'>" | 77 " -webkit-box-reflect: below 3px; transform: translateX(30px)'>" |
| 54 "</div>"); | 78 "</div>"); |
| 55 | 79 |
| 56 PaintLayer* layer = | 80 PaintLayer* layer = |
| 57 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); | 81 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 58 EXPECT_EQ( | 82 EXPECT_EQ( |
| 59 LayoutRect(90, 40, 110, 243), | 83 LayoutRect(90, 40, 110, 243), |
| 60 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); | 84 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); |
| 61 } | 85 } |
| 62 | 86 |
| 63 TEST_F(PaintLayerTest, CompositedScrollingNoNeedsRepaint) { | 87 TEST_P(PaintLayerTest, ScrollsWithViewportRelativePosition) { |
| 88 setBodyInnerHTML("<div id='target' style='position: relative'></div>"); |
| 89 |
| 90 PaintLayer* layer = |
| 91 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 92 EXPECT_FALSE(layer->sticksToViewport()); |
| 93 } |
| 94 |
| 95 TEST_P(PaintLayerTest, ScrollsWithViewportFixedPosition) { |
| 96 setBodyInnerHTML("<div id='target' style='position: fixed'></div>"); |
| 97 |
| 98 PaintLayer* layer = |
| 99 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 100 EXPECT_TRUE(layer->sticksToViewport()); |
| 101 } |
| 102 |
| 103 TEST_P(PaintLayerTest, ScrollsWithViewportFixedPositionInsideTransform) { |
| 104 // We don't intend to launch SPv2 without root layer scrolling, so skip this |
| 105 // test in that configuration because it's broken. |
| 106 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
| 107 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) |
| 108 return; |
| 109 setBodyInnerHTML( |
| 110 "<div style='transform: translateZ(0)'>" |
| 111 " <div id='target' style='position: fixed'></div>" |
| 112 "</div>" |
| 113 "<div style='width: 10px; height: 1000px'></div>"); |
| 114 PaintLayer* layer = |
| 115 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 116 EXPECT_FALSE(layer->sticksToViewport()); |
| 117 } |
| 118 |
| 119 TEST_P(PaintLayerTest, |
| 120 ScrollsWithViewportFixedPositionInsideTransformNoScroll) { |
| 121 setBodyInnerHTML( |
| 122 "<div style='transform: translateZ(0)'>" |
| 123 " <div id='target' style='position: fixed'></div>" |
| 124 "</div>"); |
| 125 PaintLayer* layer = |
| 126 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 127 |
| 128 // In SPv2 mode, we correctly determine that the frame doesn't scroll at all, |
| 129 // and so return true. |
| 130 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 131 EXPECT_TRUE(layer->sticksToViewport()); |
| 132 else |
| 133 EXPECT_FALSE(layer->sticksToViewport()); |
| 134 } |
| 135 |
| 136 TEST_P(PaintLayerTest, ScrollsWithViewportStickyPosition) { |
| 137 setBodyInnerHTML( |
| 138 "<div style='transform: translateZ(0)'>" |
| 139 " <div id='target' style='position: sticky'></div>" |
| 140 "</div>"); |
| 141 |
| 142 PaintLayer* layer = |
| 143 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 144 EXPECT_TRUE(layer->sticksToViewport()); |
| 145 } |
| 146 |
| 147 TEST_P(PaintLayerTest, ScrollsWithViewportStickyPositionInsideScroller) { |
| 148 setBodyInnerHTML( |
| 149 "<div style='overflow:scroll; width: 100px; height: 100px;'>" |
| 150 " <div id='target' style='position: sticky'></div>" |
| 151 " <div style='width: 50px; height: 1000px;'></div>" |
| 152 "</div>"); |
| 153 |
| 154 PaintLayer* layer = |
| 155 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 156 EXPECT_FALSE(layer->sticksToViewport()); |
| 157 } |
| 158 |
| 159 TEST_P(PaintLayerTest, CompositedScrollingNoNeedsRepaint) { |
| 160 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 161 return; |
| 162 |
| 64 enableCompositing(); | 163 enableCompositing(); |
| 65 setBodyInnerHTML( | 164 setBodyInnerHTML( |
| 66 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll;" | 165 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll;" |
| 67 " will-change: transform'>" | 166 " will-change: transform'>" |
| 68 " <div id='content' style='position: relative; background: blue;" | 167 " <div id='content' style='position: relative; background: blue;" |
| 69 " width: 2000px; height: 2000px'></div>" | 168 " width: 2000px; height: 2000px'></div>" |
| 70 "</div>"); | 169 "</div>"); |
| 71 | 170 |
| 72 PaintLayer* scrollLayer = | 171 PaintLayer* scrollLayer = |
| 73 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); | 172 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); |
| 74 EXPECT_EQ(PaintsIntoOwnBacking, scrollLayer->compositingState()); | 173 EXPECT_EQ(PaintsIntoOwnBacking, scrollLayer->compositingState()); |
| 75 | 174 |
| 76 PaintLayer* contentLayer = | 175 PaintLayer* contentLayer = |
| 77 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); | 176 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); |
| 78 EXPECT_EQ(NotComposited, contentLayer->compositingState()); | 177 EXPECT_EQ(NotComposited, contentLayer->compositingState()); |
| 79 EXPECT_EQ(LayoutPoint(), contentLayer->location()); | 178 EXPECT_EQ(LayoutPoint(), contentLayer->location()); |
| 80 | 179 |
| 81 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), | 180 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), |
| 82 ProgrammaticScroll); | 181 ProgrammaticScroll); |
| 83 document().view()->updateAllLifecyclePhasesExceptPaint(); | 182 document().view()->updateAllLifecyclePhasesExceptPaint(); |
| 84 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); | 183 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); |
| 85 EXPECT_FALSE(contentLayer->needsRepaint()); | 184 EXPECT_FALSE(contentLayer->needsRepaint()); |
| 86 EXPECT_FALSE(scrollLayer->needsRepaint()); | 185 EXPECT_FALSE(scrollLayer->needsRepaint()); |
| 87 document().view()->updateAllLifecyclePhases(); | 186 document().view()->updateAllLifecyclePhases(); |
| 88 } | 187 } |
| 89 | 188 |
| 90 TEST_F(PaintLayerTest, NonCompositedScrollingNeedsRepaint) { | 189 TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) { |
| 91 setBodyInnerHTML( | 190 setBodyInnerHTML( |
| 92 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll'>" | 191 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll'>" |
| 93 " <div id='content' style='position: relative; background: blue;" | 192 " <div id='content' style='position: relative; background: blue;" |
| 94 " width: 2000px; height: 2000px'></div>" | 193 " width: 2000px; height: 2000px'></div>" |
| 95 "</div>"); | 194 "</div>"); |
| 96 | 195 |
| 97 PaintLayer* scrollLayer = | 196 PaintLayer* scrollLayer = |
| 98 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); | 197 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); |
| 99 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); | 198 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); |
| 100 | 199 |
| 101 PaintLayer* contentLayer = | 200 PaintLayer* contentLayer = |
| 102 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); | 201 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); |
| 103 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); | 202 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); |
| 104 EXPECT_EQ(LayoutPoint(), contentLayer->location()); | 203 EXPECT_EQ(LayoutPoint(), contentLayer->location()); |
| 105 | 204 |
| 106 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), | 205 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), |
| 107 ProgrammaticScroll); | 206 ProgrammaticScroll); |
| 108 document().view()->updateAllLifecyclePhasesExceptPaint(); | 207 document().view()->updateAllLifecyclePhasesExceptPaint(); |
| 109 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); | 208 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); |
| 110 EXPECT_TRUE(contentLayer->needsRepaint()); | 209 EXPECT_TRUE(contentLayer->needsRepaint()); |
| 111 EXPECT_TRUE(scrollLayer->needsRepaint()); | 210 EXPECT_TRUE(scrollLayer->needsRepaint()); |
| 112 document().view()->updateAllLifecyclePhases(); | 211 document().view()->updateAllLifecyclePhases(); |
| 113 } | 212 } |
| 114 | 213 |
| 115 TEST_F(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) { | 214 TEST_P(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) { |
| 116 setBodyInnerHTML( | 215 setBodyInnerHTML( |
| 117 "<div id='stacking-grandparent' style='isolation: isolate'>" | 216 "<div id='stacking-grandparent' style='isolation: isolate'>" |
| 118 " <div id='stacking-parent' style='isolation: isolate'>" | 217 " <div id='stacking-parent' style='isolation: isolate'>" |
| 119 " <div id='non-stacking-parent' style='position:relative'>" | 218 " <div id='non-stacking-parent' style='position:relative'>" |
| 120 " <div id='blend-mode' style='mix-blend-mode: overlay'>" | 219 " <div id='blend-mode' style='mix-blend-mode: overlay'>" |
| 121 " </div>" | 220 " </div>" |
| 122 " </div>" | 221 " </div>" |
| 123 " </div>" | 222 " </div>" |
| 124 "</div>"); | 223 "</div>"); |
| 125 PaintLayer* stackingGrandparent = | 224 PaintLayer* stackingGrandparent = |
| 126 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-grandparent")) | 225 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-grandparent")) |
| 127 ->layer(); | 226 ->layer(); |
| 128 PaintLayer* stackingParent = | 227 PaintLayer* stackingParent = |
| 129 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-parent")) | 228 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-parent")) |
| 130 ->layer(); | 229 ->layer(); |
| 131 PaintLayer* parent = | 230 PaintLayer* parent = |
| 132 toLayoutBoxModelObject(getLayoutObjectByElementId("non-stacking-parent")) | 231 toLayoutBoxModelObject(getLayoutObjectByElementId("non-stacking-parent")) |
| 133 ->layer(); | 232 ->layer(); |
| 134 | 233 |
| 135 EXPECT_TRUE(parent->hasNonIsolatedDescendantWithBlendMode()); | 234 EXPECT_TRUE(parent->hasNonIsolatedDescendantWithBlendMode()); |
| 136 EXPECT_TRUE(stackingParent->hasNonIsolatedDescendantWithBlendMode()); | 235 EXPECT_TRUE(stackingParent->hasNonIsolatedDescendantWithBlendMode()); |
| 137 EXPECT_FALSE(stackingGrandparent->hasNonIsolatedDescendantWithBlendMode()); | 236 EXPECT_FALSE(stackingGrandparent->hasNonIsolatedDescendantWithBlendMode()); |
| 138 | 237 |
| 139 EXPECT_FALSE(parent->hasDescendantWithClipPath()); | 238 EXPECT_FALSE(parent->hasDescendantWithClipPath()); |
| 140 EXPECT_TRUE(parent->hasVisibleDescendant()); | 239 EXPECT_TRUE(parent->hasVisibleDescendant()); |
| 141 } | 240 } |
| 142 | 241 |
| 143 TEST_F(PaintLayerTest, HasDescendantWithClipPath) { | 242 TEST_P(PaintLayerTest, HasDescendantWithClipPath) { |
| 144 setBodyInnerHTML( | 243 setBodyInnerHTML( |
| 145 "<div id='parent' style='position:relative'>" | 244 "<div id='parent' style='position:relative'>" |
| 146 " <div id='clip-path' style='clip-path: circle(50px at 0 100px)'>" | 245 " <div id='clip-path' style='clip-path: circle(50px at 0 100px)'>" |
| 147 " </div>" | 246 " </div>" |
| 148 "</div>"); | 247 "</div>"); |
| 149 PaintLayer* parent = | 248 PaintLayer* parent = |
| 150 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); | 249 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); |
| 151 PaintLayer* clipPath = | 250 PaintLayer* clipPath = |
| 152 toLayoutBoxModelObject(getLayoutObjectByElementId("clip-path"))->layer(); | 251 toLayoutBoxModelObject(getLayoutObjectByElementId("clip-path"))->layer(); |
| 153 | 252 |
| 154 EXPECT_TRUE(parent->hasDescendantWithClipPath()); | 253 EXPECT_TRUE(parent->hasDescendantWithClipPath()); |
| 155 EXPECT_FALSE(clipPath->hasDescendantWithClipPath()); | 254 EXPECT_FALSE(clipPath->hasDescendantWithClipPath()); |
| 156 | 255 |
| 157 EXPECT_FALSE(parent->hasNonIsolatedDescendantWithBlendMode()); | 256 EXPECT_FALSE(parent->hasNonIsolatedDescendantWithBlendMode()); |
| 158 EXPECT_TRUE(parent->hasVisibleDescendant()); | 257 EXPECT_TRUE(parent->hasVisibleDescendant()); |
| 159 } | 258 } |
| 160 | 259 |
| 161 TEST_F(PaintLayerTest, HasVisibleDescendant) { | 260 TEST_P(PaintLayerTest, HasVisibleDescendant) { |
| 162 enableCompositing(); | 261 enableCompositing(); |
| 163 setBodyInnerHTML( | 262 setBodyInnerHTML( |
| 164 "<div id='invisible' style='position:relative'>" | 263 "<div id='invisible' style='position:relative'>" |
| 165 " <div id='visible' style='visibility: visible; position: relative'>" | 264 " <div id='visible' style='visibility: visible; position: relative'>" |
| 166 " </div>" | 265 " </div>" |
| 167 "</div>"); | 266 "</div>"); |
| 168 PaintLayer* invisible = | 267 PaintLayer* invisible = |
| 169 toLayoutBoxModelObject(getLayoutObjectByElementId("invisible"))->layer(); | 268 toLayoutBoxModelObject(getLayoutObjectByElementId("invisible"))->layer(); |
| 170 PaintLayer* visible = | 269 PaintLayer* visible = |
| 171 toLayoutBoxModelObject(getLayoutObjectByElementId("visible"))->layer(); | 270 toLayoutBoxModelObject(getLayoutObjectByElementId("visible"))->layer(); |
| 172 | 271 |
| 173 EXPECT_TRUE(invisible->hasVisibleDescendant()); | 272 EXPECT_TRUE(invisible->hasVisibleDescendant()); |
| 174 EXPECT_FALSE(visible->hasVisibleDescendant()); | 273 EXPECT_FALSE(visible->hasVisibleDescendant()); |
| 175 | 274 |
| 176 EXPECT_FALSE(invisible->hasNonIsolatedDescendantWithBlendMode()); | 275 EXPECT_FALSE(invisible->hasNonIsolatedDescendantWithBlendMode()); |
| 177 EXPECT_FALSE(invisible->hasDescendantWithClipPath()); | 276 EXPECT_FALSE(invisible->hasDescendantWithClipPath()); |
| 178 } | 277 } |
| 179 | 278 |
| 180 } // namespace blink | 279 } // namespace blink |
| OLD | NEW |