OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 } | 156 } |
157 | 157 |
158 FloatRect VisualViewport::visibleRect() const { | 158 FloatRect VisualViewport::visibleRect() const { |
159 return FloatRect(location(), visibleSize()); | 159 return FloatRect(location(), visibleSize()); |
160 } | 160 } |
161 | 161 |
162 FloatRect VisualViewport::visibleRectInDocument() const { | 162 FloatRect VisualViewport::visibleRectInDocument() const { |
163 if (!mainFrame() || !mainFrame()->view()) | 163 if (!mainFrame() || !mainFrame()->view()) |
164 return FloatRect(); | 164 return FloatRect(); |
165 | 165 |
166 FloatPoint viewLocation = FloatPoint( | 166 FloatPoint viewLocation = |
167 mainFrame()->view()->getScrollableArea()->scrollPositionDouble()); | 167 FloatPoint(mainFrame()->view()->getScrollableArea()->scrollOffset()); |
168 return FloatRect(viewLocation, visibleSize()); | 168 return FloatRect(viewLocation, visibleSize()); |
169 } | 169 } |
170 | 170 |
171 FloatRect VisualViewport::mainViewToViewportCSSPixels( | 171 FloatRect VisualViewport::mainViewToViewportCSSPixels( |
172 const FloatRect& rect) const { | 172 const FloatRect& rect) const { |
173 // Note, this is in CSS Pixels so we don't apply scale. | 173 // Note, this is in CSS Pixels so we don't apply scale. |
174 FloatRect rectInViewport = rect; | 174 FloatRect rectInViewport = rect; |
175 rectInViewport.moveBy(-location()); | 175 rectInViewport.moveBy(-location()); |
176 return rectInViewport; | 176 return rectInViewport; |
177 } | 177 } |
178 | 178 |
179 FloatPoint VisualViewport::viewportCSSPixelsToRootFrame( | 179 FloatPoint VisualViewport::viewportCSSPixelsToRootFrame( |
180 const FloatPoint& point) const { | 180 const FloatPoint& point) const { |
181 // Note, this is in CSS Pixels so we don't apply scale. | 181 // Note, this is in CSS Pixels so we don't apply scale. |
182 FloatPoint pointInRootFrame = point; | 182 FloatPoint pointInRootFrame = point; |
183 pointInRootFrame.moveBy(location()); | 183 pointInRootFrame.moveBy(location()); |
184 return pointInRootFrame; | 184 return pointInRootFrame; |
185 } | 185 } |
186 | 186 |
187 void VisualViewport::setLocation(const FloatPoint& newLocation) { | 187 void VisualViewport::setLocation(const FloatPoint& newLocation) { |
188 setScaleAndLocation(m_scale, newLocation); | 188 setScaleAndLocation(m_scale, newLocation); |
189 } | 189 } |
190 | 190 |
191 void VisualViewport::move(const FloatPoint& delta) { | 191 void VisualViewport::move(const ScrollOffset& delta) { |
192 setLocation(m_offset + delta); | 192 setLocation(FloatPoint(m_offset + delta)); |
193 } | |
194 | |
195 void VisualViewport::move(const FloatSize& delta) { | |
196 setLocation(m_offset + delta); | |
197 } | 193 } |
198 | 194 |
199 void VisualViewport::setScale(float scale) { | 195 void VisualViewport::setScale(float scale) { |
200 setScaleAndLocation(scale, m_offset); | 196 setScaleAndLocation(scale, FloatPoint(m_offset)); |
201 } | 197 } |
202 | 198 |
203 double VisualViewport::scrollLeft() { | 199 float VisualViewport::scrollLeft() { |
204 if (!mainFrame()) | 200 if (!mainFrame()) |
205 return 0; | 201 return 0; |
206 | 202 |
207 updateStyleAndLayoutIgnorePendingStylesheets(); | 203 updateStyleAndLayoutIgnorePendingStylesheets(); |
208 | 204 |
209 return adjustScrollForAbsoluteZoom(visibleRect().x(), | 205 return adjustScrollForAbsoluteZoom(visibleRect().x(), |
210 mainFrame()->pageZoomFactor()); | 206 mainFrame()->pageZoomFactor()); |
211 } | 207 } |
212 | 208 |
213 double VisualViewport::scrollTop() { | 209 float VisualViewport::scrollTop() { |
214 if (!mainFrame()) | 210 if (!mainFrame()) |
215 return 0; | 211 return 0; |
216 | 212 |
217 updateStyleAndLayoutIgnorePendingStylesheets(); | 213 updateStyleAndLayoutIgnorePendingStylesheets(); |
218 | 214 |
219 return adjustScrollForAbsoluteZoom(visibleRect().y(), | 215 return adjustScrollForAbsoluteZoom(visibleRect().y(), |
220 mainFrame()->pageZoomFactor()); | 216 mainFrame()->pageZoomFactor()); |
221 } | 217 } |
222 | 218 |
223 double VisualViewport::clientWidth() { | 219 float VisualViewport::clientWidth() { |
224 if (!mainFrame()) | 220 if (!mainFrame()) |
225 return 0; | 221 return 0; |
226 | 222 |
227 updateStyleAndLayoutIgnorePendingStylesheets(); | 223 updateStyleAndLayoutIgnorePendingStylesheets(); |
228 | 224 |
229 double width = adjustScrollForAbsoluteZoom(visibleSize().width(), | 225 float width = adjustScrollForAbsoluteZoom(visibleSize().width(), |
230 mainFrame()->pageZoomFactor()); | 226 mainFrame()->pageZoomFactor()); |
231 return width - mainFrame()->view()->verticalScrollbarWidth() / m_scale; | 227 return width - mainFrame()->view()->verticalScrollbarWidth() / m_scale; |
232 } | 228 } |
233 | 229 |
234 double VisualViewport::clientHeight() { | 230 float VisualViewport::clientHeight() { |
235 if (!mainFrame()) | 231 if (!mainFrame()) |
236 return 0; | 232 return 0; |
237 | 233 |
238 updateStyleAndLayoutIgnorePendingStylesheets(); | 234 updateStyleAndLayoutIgnorePendingStylesheets(); |
239 | 235 |
240 double height = adjustScrollForAbsoluteZoom(visibleSize().height(), | 236 float height = adjustScrollForAbsoluteZoom(visibleSize().height(), |
241 mainFrame()->pageZoomFactor()); | 237 mainFrame()->pageZoomFactor()); |
242 return height - mainFrame()->view()->horizontalScrollbarHeight() / m_scale; | 238 return height - mainFrame()->view()->horizontalScrollbarHeight() / m_scale; |
243 } | 239 } |
244 | 240 |
245 double VisualViewport::pageScale() { | 241 double VisualViewport::pageScale() { |
246 updateStyleAndLayoutIgnorePendingStylesheets(); | 242 updateStyleAndLayoutIgnorePendingStylesheets(); |
247 | 243 |
248 return m_scale; | 244 return m_scale; |
249 } | 245 } |
250 | 246 |
251 void VisualViewport::setScaleAndLocation(float scale, | 247 void VisualViewport::setScaleAndLocation(float scale, |
252 const FloatPoint& location) { | 248 const FloatPoint& location) { |
253 if (didSetScaleOrLocation(scale, location)) | 249 if (didSetScaleOrLocation(scale, location)) |
254 notifyRootFrameViewport(); | 250 notifyRootFrameViewport(); |
255 } | 251 } |
256 | 252 |
257 bool VisualViewport::didSetScaleOrLocation(float scale, | 253 bool VisualViewport::didSetScaleOrLocation(float scale, |
258 const FloatPoint& location) { | 254 const FloatPoint& location) { |
259 if (!mainFrame()) | 255 if (!mainFrame()) |
260 return false; | 256 return false; |
261 | 257 |
262 bool valuesChanged = false; | 258 bool valuesChanged = false; |
263 | 259 |
264 if (scale != m_scale) { | 260 if (scale != m_scale) { |
265 m_scale = scale; | 261 m_scale = scale; |
266 valuesChanged = true; | 262 valuesChanged = true; |
267 frameHost().chromeClient().pageScaleFactorChanged(); | 263 frameHost().chromeClient().pageScaleFactorChanged(); |
268 enqueueResizeEvent(); | 264 enqueueResizeEvent(); |
269 } | 265 } |
270 | 266 |
271 FloatPoint clampedOffset(clampOffsetToBoundaries(location)); | 267 ScrollOffset clampedOffset = clampScrollOffset(toScrollOffset(location)); |
272 | 268 |
273 if (clampedOffset != m_offset) { | 269 if (clampedOffset != m_offset) { |
274 m_offset = clampedOffset; | 270 m_offset = clampedOffset; |
275 scrollAnimator().setCurrentPosition(m_offset); | 271 scrollAnimator().setCurrentOffset(m_offset); |
276 | 272 |
277 // SVG runs with accelerated compositing disabled so no ScrollingCoordinator
. | 273 // SVG runs with accelerated compositing disabled so no ScrollingCoordinator
. |
278 if (ScrollingCoordinator* coordinator = | 274 if (ScrollingCoordinator* coordinator = |
279 frameHost().page().scrollingCoordinator()) | 275 frameHost().page().scrollingCoordinator()) |
280 coordinator->scrollableAreaScrollLayerDidChange(this); | 276 coordinator->scrollableAreaScrollLayerDidChange(this); |
281 | 277 |
282 if (!frameHost().settings().inertVisualViewport()) { | 278 if (!frameHost().settings().inertVisualViewport()) { |
283 if (Document* document = mainFrame()->document()) | 279 if (Document* document = mainFrame()->document()) |
284 document->enqueueScrollEventForNode(document); | 280 document->enqueueScrollEventForNode(document); |
285 } | 281 } |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } | 491 } |
496 | 492 |
497 bool VisualViewport::scrollAnimatorEnabled() const { | 493 bool VisualViewport::scrollAnimatorEnabled() const { |
498 return frameHost().settings().scrollAnimatorEnabled(); | 494 return frameHost().settings().scrollAnimatorEnabled(); |
499 } | 495 } |
500 | 496 |
501 HostWindow* VisualViewport::getHostWindow() const { | 497 HostWindow* VisualViewport::getHostWindow() const { |
502 return &frameHost().chromeClient(); | 498 return &frameHost().chromeClient(); |
503 } | 499 } |
504 | 500 |
505 DoubleRect VisualViewport::visibleContentRectDouble( | |
506 IncludeScrollbarsInRect) const { | |
507 return visibleRect(); | |
508 } | |
509 | |
510 IntRect VisualViewport::visibleContentRect( | |
511 IncludeScrollbarsInRect scrollbarInclusion) const { | |
512 return enclosingIntRect(visibleContentRectDouble(scrollbarInclusion)); | |
513 } | |
514 | |
515 bool VisualViewport::shouldUseIntegerScrollOffset() const { | 501 bool VisualViewport::shouldUseIntegerScrollOffset() const { |
516 LocalFrame* frame = mainFrame(); | 502 LocalFrame* frame = mainFrame(); |
517 if (frame && frame->settings() && | 503 if (frame && frame->settings() && |
518 !frame->settings()->preferCompositingToLCDTextEnabled()) | 504 !frame->settings()->preferCompositingToLCDTextEnabled()) |
519 return true; | 505 return true; |
520 | 506 |
521 return ScrollableArea::shouldUseIntegerScrollOffset(); | 507 return ScrollableArea::shouldUseIntegerScrollOffset(); |
522 } | 508 } |
523 | 509 |
524 void VisualViewport::setScrollPosition(const DoublePoint& scrollPoint, | 510 void VisualViewport::setScrollOffset(const ScrollOffset& offset, |
525 ScrollType scrollType, | 511 ScrollType scrollType, |
526 ScrollBehavior scrollBehavior) { | 512 ScrollBehavior scrollBehavior) { |
527 // We clamp the position here, because the ScrollAnimator may otherwise be | 513 // We clamp the offset here, because the ScrollAnimator may otherwise be |
528 // set to a non-clamped position by ScrollableArea::setScrollPosition, | 514 // set to a non-clamped offset by ScrollableArea::setScrollOffset, |
529 // which may lead to incorrect scrolling behavior in RootFrameViewport down | 515 // which may lead to incorrect scrolling behavior in RootFrameViewport down |
530 // the line. | 516 // the line. |
531 // TODO(eseckler): Solve this instead by ensuring that ScrollableArea and | 517 // TODO(eseckler): Solve this instead by ensuring that ScrollableArea and |
532 // ScrollAnimator are kept in sync. This requires that ScrollableArea always | 518 // ScrollAnimator are kept in sync. This requires that ScrollableArea always |
533 // stores fractional offsets and that truncation happens elsewhere, see | 519 // stores fractional offsets and that truncation happens elsewhere, see |
534 // crbug.com/626315. | 520 // crbug.com/626315. |
535 DoublePoint newScrollPosition = clampScrollPosition(scrollPoint); | 521 ScrollOffset newScrollOffset = clampScrollOffset(offset); |
536 ScrollableArea::setScrollPosition(newScrollPosition, scrollType, | 522 ScrollableArea::setScrollOffset(newScrollOffset, scrollType, scrollBehavior); |
537 scrollBehavior); | |
538 } | 523 } |
539 | 524 |
540 int VisualViewport::scrollSize(ScrollbarOrientation orientation) const { | 525 int VisualViewport::scrollSize(ScrollbarOrientation orientation) const { |
541 IntSize scrollDimensions = maximumScrollPosition() - minimumScrollPosition(); | 526 IntSize scrollDimensions = |
| 527 maximumScrollOffsetInt() - minimumScrollOffsetInt(); |
542 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() | 528 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() |
543 : scrollDimensions.height(); | 529 : scrollDimensions.height(); |
544 } | 530 } |
545 | 531 |
546 IntPoint VisualViewport::minimumScrollPosition() const { | 532 IntSize VisualViewport::minimumScrollOffsetInt() const { |
547 return IntPoint(); | 533 return IntSize(); |
548 } | 534 } |
549 | 535 |
550 IntPoint VisualViewport::maximumScrollPosition() const { | 536 IntSize VisualViewport::maximumScrollOffsetInt() const { |
551 return flooredIntPoint(maximumScrollPositionDouble()); | 537 return flooredIntSize(maximumScrollOffset()); |
552 } | 538 } |
553 | 539 |
554 DoublePoint VisualViewport::maximumScrollPositionDouble() const { | 540 ScrollOffset VisualViewport::maximumScrollOffset() const { |
555 if (!mainFrame()) | 541 if (!mainFrame()) |
556 return IntPoint(); | 542 return ScrollOffset(); |
557 | 543 |
558 // TODO(bokan): We probably shouldn't be storing the bounds in a float. crbug.
com/470718. | 544 // TODO(bokan): We probably shouldn't be storing the bounds in a float. crbug.
com/470718. |
559 FloatSize frameViewSize(contentsSize()); | 545 FloatSize frameViewSize(contentsSize()); |
560 | 546 |
561 if (m_topControlsAdjustment) { | 547 if (m_topControlsAdjustment) { |
562 float minScale = | 548 float minScale = |
563 frameHost().pageScaleConstraintsSet().finalConstraints().minimumScale; | 549 frameHost().pageScaleConstraintsSet().finalConstraints().minimumScale; |
564 frameViewSize.expand(0, m_topControlsAdjustment / minScale); | 550 frameViewSize.expand(0, m_topControlsAdjustment / minScale); |
565 } | 551 } |
566 | 552 |
567 frameViewSize.scale(m_scale); | 553 frameViewSize.scale(m_scale); |
568 frameViewSize = FloatSize(flooredIntSize(frameViewSize)); | 554 frameViewSize = FloatSize(flooredIntSize(frameViewSize)); |
569 | 555 |
570 FloatSize viewportSize(m_size); | 556 FloatSize viewportSize(m_size); |
571 viewportSize.expand(0, ceilf(m_topControlsAdjustment)); | 557 viewportSize.expand(0, ceilf(m_topControlsAdjustment)); |
572 | 558 |
573 FloatSize maxPosition = frameViewSize - viewportSize; | 559 FloatSize maxPosition = frameViewSize - viewportSize; |
574 maxPosition.scale(1 / m_scale); | 560 maxPosition.scale(1 / m_scale); |
575 return DoublePoint(maxPosition); | 561 return ScrollOffset(maxPosition); |
576 } | 562 } |
577 | 563 |
578 IntPoint VisualViewport::clampDocumentOffsetAtScale(const IntPoint& offset, | 564 IntPoint VisualViewport::clampDocumentOffsetAtScale(const IntPoint& offset, |
579 float scale) { | 565 float scale) { |
580 if (!mainFrame() || !mainFrame()->view()) | 566 if (!mainFrame() || !mainFrame()->view()) |
581 return IntPoint(); | 567 return IntPoint(); |
582 | 568 |
583 FrameView* view = mainFrame()->view(); | 569 FrameView* view = mainFrame()->view(); |
584 | 570 |
585 FloatSize scaledSize(m_size); | 571 FloatSize scaledSize(m_size); |
586 scaledSize.scale(1 / scale); | 572 scaledSize.scale(1 / scale); |
587 | 573 |
588 IntPoint visualViewportMax = | 574 IntSize visualViewportMax = |
589 flooredIntPoint(FloatSize(contentsSize()) - scaledSize); | 575 flooredIntSize(FloatSize(contentsSize()) - scaledSize); |
590 IntPoint max = view->maximumScrollPosition() + visualViewportMax; | 576 IntSize max = view->maximumScrollOffsetInt() + visualViewportMax; |
591 IntPoint min = | 577 IntSize min = |
592 view->minimumScrollPosition(); // VisualViewportMin should be (0, 0) | 578 view->minimumScrollOffsetInt(); // VisualViewportMin should be (0, 0) |
593 | 579 |
594 IntPoint clamped = offset; | 580 IntSize clamped = toIntSize(offset); |
595 clamped = clamped.shrunkTo(max); | 581 clamped = clamped.shrunkTo(max); |
596 clamped = clamped.expandedTo(min); | 582 clamped = clamped.expandedTo(min); |
597 return clamped; | 583 return IntPoint(clamped); |
598 } | 584 } |
599 | 585 |
600 void VisualViewport::setTopControlsAdjustment(float adjustment) { | 586 void VisualViewport::setTopControlsAdjustment(float adjustment) { |
601 m_topControlsAdjustment = adjustment; | 587 m_topControlsAdjustment = adjustment; |
602 } | 588 } |
603 | 589 |
604 IntRect VisualViewport::scrollableAreaBoundingBox() const { | 590 IntRect VisualViewport::scrollableAreaBoundingBox() const { |
605 // This method should return the bounding box in the parent view's coordinate | 591 // This method should return the bounding box in the parent view's coordinate |
606 // space; however, VisualViewport technically isn't a child of any Frames. | 592 // space; however, VisualViewport technically isn't a child of any Frames. |
607 // Nonetheless, the VisualViewport always occupies the entire main frame so ju
st | 593 // Nonetheless, the VisualViewport always occupies the entire main frame so ju
st |
608 // return that. | 594 // return that. |
609 LocalFrame* frame = mainFrame(); | 595 LocalFrame* frame = mainFrame(); |
610 | 596 |
611 if (!frame || !frame->view()) | 597 if (!frame || !frame->view()) |
612 return IntRect(); | 598 return IntRect(); |
613 | 599 |
614 return frame->view()->frameRect(); | 600 return frame->view()->frameRect(); |
615 } | 601 } |
616 | 602 |
617 IntSize VisualViewport::contentsSize() const { | 603 IntSize VisualViewport::contentsSize() const { |
618 LocalFrame* frame = mainFrame(); | 604 LocalFrame* frame = mainFrame(); |
619 | 605 |
620 if (!frame || !frame->view()) | 606 if (!frame || !frame->view()) |
621 return IntSize(); | 607 return IntSize(); |
622 | 608 |
623 return frame->view()->visibleContentRect(IncludeScrollbars).size(); | 609 return frame->view()->visibleContentRect(IncludeScrollbars).size(); |
624 } | 610 } |
625 | 611 |
626 void VisualViewport::updateScrollPosition(const DoublePoint& position, | 612 void VisualViewport::updateScrollOffset(const ScrollOffset& position, |
627 ScrollType scrollType) { | 613 ScrollType scrollType) { |
628 if (didSetScaleOrLocation(m_scale, toFloatPoint(position)) && | 614 if (didSetScaleOrLocation(m_scale, FloatPoint(position)) && |
629 scrollType != AnchoringScroll) | 615 scrollType != AnchoringScroll) |
630 notifyRootFrameViewport(); | 616 notifyRootFrameViewport(); |
631 } | 617 } |
632 | 618 |
633 GraphicsLayer* VisualViewport::layerForContainer() const { | 619 GraphicsLayer* VisualViewport::layerForContainer() const { |
634 return m_innerViewportContainerLayer.get(); | 620 return m_innerViewportContainerLayer.get(); |
635 } | 621 } |
636 | 622 |
637 GraphicsLayer* VisualViewport::layerForScrolling() const { | 623 GraphicsLayer* VisualViewport::layerForScrolling() const { |
638 return m_innerViewportScrollLayer.get(); | 624 return m_innerViewportScrollLayer.get(); |
(...skipping 21 matching lines...) Expand all Loading... |
660 return frameHost().page().mainFrame() && | 646 return frameHost().page().mainFrame() && |
661 frameHost().page().mainFrame()->isLocalFrame() | 647 frameHost().page().mainFrame()->isLocalFrame() |
662 ? frameHost().page().deprecatedLocalMainFrame() | 648 ? frameHost().page().deprecatedLocalMainFrame() |
663 : 0; | 649 : 0; |
664 } | 650 } |
665 | 651 |
666 Widget* VisualViewport::getWidget() { | 652 Widget* VisualViewport::getWidget() { |
667 return mainFrame()->view(); | 653 return mainFrame()->view(); |
668 } | 654 } |
669 | 655 |
670 FloatPoint VisualViewport::clampOffsetToBoundaries(const FloatPoint& offset) { | |
671 FloatPoint clampedOffset(offset); | |
672 clampedOffset = | |
673 clampedOffset.shrunkTo(FloatPoint(maximumScrollPositionDouble())); | |
674 clampedOffset = | |
675 clampedOffset.expandedTo(FloatPoint(minimumScrollPositionDouble())); | |
676 return clampedOffset; | |
677 } | |
678 | |
679 void VisualViewport::clampToBoundaries() { | 656 void VisualViewport::clampToBoundaries() { |
680 setLocation(m_offset); | 657 setLocation(FloatPoint(m_offset)); |
681 } | 658 } |
682 | 659 |
683 FloatRect VisualViewport::viewportToRootFrame( | 660 FloatRect VisualViewport::viewportToRootFrame( |
684 const FloatRect& rectInViewport) const { | 661 const FloatRect& rectInViewport) const { |
685 FloatRect rectInRootFrame = rectInViewport; | 662 FloatRect rectInRootFrame = rectInViewport; |
686 rectInRootFrame.scale(1 / scale()); | 663 rectInRootFrame.scale(1 / scale()); |
687 rectInRootFrame.moveBy(location()); | 664 rectInRootFrame.moveBy(location()); |
688 return rectInRootFrame; | 665 return rectInRootFrame; |
689 } | 666 } |
690 | 667 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 } else if (graphicsLayer == m_rootTransformLayer.get()) { | 815 } else if (graphicsLayer == m_rootTransformLayer.get()) { |
839 name = "Root Transform Layer"; | 816 name = "Root Transform Layer"; |
840 } else { | 817 } else { |
841 ASSERT_NOT_REACHED(); | 818 ASSERT_NOT_REACHED(); |
842 } | 819 } |
843 | 820 |
844 return name; | 821 return name; |
845 } | 822 } |
846 | 823 |
847 } // namespace blink | 824 } // namespace blink |
OLD | NEW |