15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Eric Seidel <eric@webkit.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2011. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/graphics/SVGImage.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
32d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/animation/AnimationTimeline.h"
33e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/dom/NodeTraversal.h"
34c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#include "core/dom/shadow/ComposedTreeWalker.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/frame/FrameView.h"
36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h"
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/frame/Settings.h"
38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/loader/FrameLoadRequest.h"
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/page/Chrome.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/RenderStyle.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGRoot.h"
42323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "core/svg/SVGDocumentExtensions.h"
438abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include "core/svg/SVGFEImageElement.h"
44e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/svg/SVGImageElement.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGSVGElement.h"
46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/svg/animation/SMILTimeContainer.h"
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/graphics/SVGImageChromeClient.h"
48e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "platform/EventDispatchForbiddenScope.h"
49bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/LengthFunctions.h"
505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "platform/TraceEvent.h"
511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/IntRect.h"
52a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h"
53a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h"
5451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/graphics/ImageObserver.h"
55591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/PassRefPtr.h"
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGImage::SVGImage(ImageObserver* observer)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : Image(observer)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGImage::~SVGImage()
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_page) {
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Store m_page in a local variable, clearing m_page, so that SVGImageChromeClient knows we're destructed.
686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        OwnPtrWillBeRawPtr<Page> currentPage = m_page.release();
695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // Break both the loader and view references to the frame
706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        currentPage->willBeDestroyed();
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that page teardown destroyed the Chrome
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_chromeClient || !m_chromeClient->image());
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool SVGImage::isInSVGImage(const Node* node)
78e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
79f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ASSERT(node);
80e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
81f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    Page* page = node->document().page();
82e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (!page)
83e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return false;
84e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
85e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    return page->chrome().client().isSVGImageChromeClient();
86e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
87e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)bool SVGImage::currentFrameHasSingleSecurityOrigin() const
89e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
90e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (!m_page)
91e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return true;
92e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    LocalFrame* frame = toLocalFrame(m_page->mainFrame());
948abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
958abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    RELEASE_ASSERT(frame->document()->loadEventFinished());
968abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
97323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGSVGElement* rootElement = frame->document()->accessSVGExtensions().rootElement();
98e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (!rootElement)
99e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return true;
100e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
101e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // Don't allow foreignObject elements or images that are not known to be
102e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // single-origin since these can leak cross-origin information.
103c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    ComposedTreeWalker walker(rootElement);
104e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    while (Node* node = walker.get()) {
105d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isSVGForeignObjectElement(*node))
106e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return false;
107d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isSVGImageElement(*node)) {
108d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!toSVGImageElement(*node).currentFrameHasSingleSecurityOrigin())
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                return false;
110d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        } else if (isSVGFEImageElement(*node)) {
111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!toSVGFEImageElement(*node).currentFrameHasSingleSecurityOrigin())
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                return false;
11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
114e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        walker.next();
115e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    }
116e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
117e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // Because SVG image rendering disallows external resources and links, these
118e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // images effectively are restricted to a single security origin.
119e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    return true;
120e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
121e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
12207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic SVGSVGElement* svgRootElement(Page* page)
12307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
12407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!page)
12507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return 0;
1265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    LocalFrame* frame = toLocalFrame(page->mainFrame());
127323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return frame->document()->accessSVGExtensions().rootElement();
12807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
12907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGImage::setContainerSize(const IntSize& size)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!usesContainerSize())
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
13507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!rootElement)
137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FrameView* view = frameView();
140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    view->resize(this->containerSize());
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer());
143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!renderer)
144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    renderer->setContainerSize(size);
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)IntSize SVGImage::containerSize() const
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rootElement)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntSize();
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer());
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntSize();
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If a container size is available it has precedence.
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize containerSize = renderer->containerSize();
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!containerSize.isEmpty())
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return containerSize;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Assure that a container size is always given for a non-identity zoom level.
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(renderer->style()->effectiveZoom() == 1);
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    FloatSize intrinsicSize;
1675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    double intrinsicRatio = 0;
1685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    renderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (intrinsicSize.isEmpty() && intrinsicRatio) {
1715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (!intrinsicSize.width() && intrinsicSize.height())
1725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            intrinsicSize.setWidth(intrinsicSize.height() * intrinsicRatio);
1735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        else if (intrinsicSize.width() && !intrinsicSize.height())
1745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            intrinsicSize.setHeight(intrinsicSize.width() / intrinsicRatio);
1755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
1765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!intrinsicSize.isEmpty())
1785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return expandedIntSize(intrinsicSize);
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // As last resort, use CSS replaced element fallback size.
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IntSize(300, 150);
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect,
185a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatRect& srcRect, CompositeOperator compositeOp, blink::WebBlendMode blendMode)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_page)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1908abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // Temporarily disable the image observer to prevent changeInRect() calls due re-laying out the image.
1918abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ImageObserverDisabler imageObserverDisabler(this);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    IntSize roundedContainerSize = roundedIntSize(containerSize);
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setContainerSize(roundedContainerSize);
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatRect scaledSrc = srcRect;
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    scaledSrc.scale(1 / zoom);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Compensate for the container size rounding by adjusting the source rect.
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatSize adjustedSrcSize = scaledSrc.size();
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height());
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    scaledSrc.setSize(adjustedSrcSize);
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    draw(context, dstRect, scaledSrc, compositeOp, blendMode);
205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
207591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassRefPtr<NativeImageSkia> SVGImage::nativeImageForCurrentFrame()
20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
20953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!m_page)
210d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
212a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size());
213a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!buffer)
214d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
21553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
216a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    drawForContainer(buffer->context(), size(), 1, rect(), rect(), CompositeSourceOver, blink::WebBlendModeNormal);
21753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // FIXME: WK(Bug 113657): We should use DontCopyBackingStore here.
21953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return buffer->copyImage(CopyBackingStore)->nativeImageForCurrentFrame();
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
22153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& srcRect,
223a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& dstRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatRect zoomedContainerRect = FloatRect(FloatPoint(), containerSize);
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    zoomedContainerRect.scale(zoom);
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // The ImageBuffer size needs to be scaled to match the final resolution.
229521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // FIXME: No need to get the full CTM here, we just need the scale.
2305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // FIXME: See crbug.com/382491. This scale does not reflect compositor applied
2315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // scale factors, such a High DPI or device zoom.
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    AffineTransform transform = context->getCTM();
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatSize imageBufferScale = FloatSize(transform.xScale(), transform.yScale());
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(imageBufferScale.width());
235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(imageBufferScale.height());
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
237521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    FloatSize scaleWithoutCTM(scale.width() / imageBufferScale.width(), scale.height() / imageBufferScale.height());
238521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatRect imageBufferSize = zoomedContainerRect;
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    imageBufferSize.scale(imageBufferScale.width(), imageBufferScale.height());
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
242a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(imageBufferSize.size()));
243521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!buffer) // Failed to allocate buffer.
244521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
245a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
246a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, CompositeSourceOver, blink::WebBlendModeNormal);
247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled);
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Adjust the source rect and transform due to the image buffer's scaling.
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatRect scaledSrcRect = srcRect;
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    scaledSrcRect.scale(imageBufferScale.width(), imageBufferScale.height());
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    image->drawPattern(context, scaledSrcRect, scaleWithoutCTM, phase, compositeOp, dstRect, blendMode, repeatSpacing);
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
256a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, blink::WebBlendMode blendMode)
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_page)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    context->setCompositeOperation(compositeOp, blendMode);
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->clip(enclosingIntRect(dstRect));
26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool compositingRequiresTransparencyLayer = compositeOp != CompositeSourceOver || blendMode != blink::WebBlendModeNormal;
266d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float opacity = context->getNormalizedAlpha() / 255.f;
267d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool requiresTransparencyLayer = compositingRequiresTransparencyLayer || opacity < 1;
268d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (requiresTransparencyLayer) {
269d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        context->beginTransparencyLayer(opacity);
270d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (compositingRequiresTransparencyLayer)
271d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            context->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
27209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height());
2755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We can only draw the entire frame, clipped to the rect we want. So compute where the top left
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of the image would be if we were drawing without clipping, and translate accordingly.
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height());
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint destOffset = dstRect.location() - topLeftOffset;
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->translate(destOffset.x(), destOffset.y());
2825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    context->scale(scale.width(), scale.height());
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    FrameView* view = frameView();
285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    view->resize(containerSize());
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
287323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_url.isEmpty())
288323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        view->scrollToFragment(m_url);
289323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
290e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    view->updateLayoutAndStyleForPainting();
291591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    view->paint(context, enclosingIntRect(srcRect));
292aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    ASSERT(!view->needsLayout());
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (requiresTransparencyLayer)
295c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        context->endLayer();
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stateSaver.restore();
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (imageObserver())
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageObserver()->didDraw(this);
30107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
30207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Start any (SMIL) animations if needed. This will restart or continue
30307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // animations if preceded by calls to resetAnimation or stopAnimation
30407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // respectively.
30507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    startAnimation();
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderBox* SVGImage::embeddedContentBox() const
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
31007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rootElement)
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return toRenderBox(rootElement->renderer());
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FrameView* SVGImage::frameView() const
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_page)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return toLocalFrame(m_page->mainFrame())->view();
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
32607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rootElement)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicWidth = rootElement->intrinsicWidth();
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicHeight = rootElement->intrinsicHeight();
33209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (rootElement->preserveAspectRatio()->currentValue()->align() == SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    intrinsicRatio = rootElement->viewBox()->currentValue()->value().size();
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (intrinsicRatio.isEmpty() && intrinsicWidth.isFixed() && intrinsicHeight.isFixed())
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        intrinsicRatio = FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0));
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch// FIXME: support CatchUpAnimation = CatchUp.
34110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochvoid SVGImage::startAnimation(CatchUpAnimation)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
34307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
34407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!rootElement || !rootElement->animationsPaused())
345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    rootElement->unpauseAnimations();
347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGImage::stopAnimation()
350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
35107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!rootElement)
353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    rootElement->pauseAnimations();
355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGImage::resetAnimation()
358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
35907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
36007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!rootElement)
36107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return;
36207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    rootElement->pauseAnimations();
36307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    rootElement->setCurrentTime(0);
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
366d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool SVGImage::hasAnimations() const
367d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
36807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SVGSVGElement* rootElement = svgRootElement(m_page.get());
369d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!rootElement)
370d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
3715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return rootElement->timeContainer()->hasAnimations() || toLocalFrame(m_page->mainFrame())->document()->timeline().hasPendingUpdates();
372d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
373d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGImage::dataChanged(bool allDataReceived)
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
376197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    TRACE_EVENT0("blink", "SVGImage::dataChanged");
3771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Don't do anything if is an empty image.
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!data()->size())
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (allDataReceived) {
383d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // SVGImage will fire events (and the default C++ handlers run) but doesn't
384d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // actually allow script to run so it's fine to call into it. We allow this
385d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // since it means an SVG data url can synchronously load like other image
386d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // types.
387e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents;
388d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
38909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient;
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Page::PageClients pageClients;
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fillWithEmptyClients(pageClients);
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_chromeClient = adoptPtr(new SVGImageChromeClient(this));
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pageClients.chromeClient = m_chromeClient.get();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: If this SVG ends up loading itself, we might leak the world.
3973c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // The Cache code does not know about ImageResources holding Frames and
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // won't know to break the cycle.
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This will become an issue when SVGImage will be able to load other
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // SVGImage objects, but we're safe now, because SVGImage can only be
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // loaded by a top-level document.
402197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        OwnPtrWillBeRawPtr<Page> page;
403197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        {
404197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage");
405197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            page = adoptPtrWillBeNoop(new Page(pageClients));
406197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            page->settings().setScriptEnabled(false);
407197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            page->settings().setPluginsEnabled(false);
408197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            page->settings().setAcceleratedCompositingEnabled(false);
409197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
410197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
4117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        RefPtrWillBeRawPtr<LocalFrame> frame = nullptr;
412197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        {
413197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame");
414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            frame = LocalFrame::create(dummyFrameLoaderClient, &page->frameHost(), 0);
415197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            frame->setView(FrameView::create(frame.get()));
416197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            frame->init();
417197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
419f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        FrameLoader& loader = frame->loader();
420f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        loader.forceSandboxFlags(SandboxAll);
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        frame->view()->setScrollbarsSuppressed(true);
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        frame->view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars.
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        frame->view()->setTransparent(true); // SVG Images are transparent.
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
426d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_page = page.release();
427d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
428197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        TRACE_EVENT0("blink", "SVGImage::dataChanged::load");
4297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), AtomicString("image/svg+xml", AtomicString::ConstructFromLiteral),
4307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            AtomicString("UTF-8", AtomicString::ConstructFromLiteral), KURL(), ForceSynchronousLoad)));
431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Set the intrinsic size before a container size is available.
432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        m_intrinsicSize = containerSize();
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_page;
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String SVGImage::filenameExtension() const
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "svg";
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
444