1/*
2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22#include "SVGExternalResourcesRequired.h"
23
24#include "Attr.h"
25#include "SVGElement.h"
26#include "SVGNames.h"
27
28namespace WebCore {
29
30bool SVGExternalResourcesRequired::parseAttribute(const QualifiedName& name, const AtomicString& value)
31{
32    if (name == SVGNames::externalResourcesRequiredAttr) {
33        setExternalResourcesRequiredBaseValue(value == "true");
34        return true;
35    }
36
37    return false;
38}
39
40bool SVGExternalResourcesRequired::isKnownAttribute(const QualifiedName& attrName)
41{
42    return attrName == SVGNames::externalResourcesRequiredAttr;
43}
44
45void SVGExternalResourcesRequired::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
46{
47    supportedAttributes.add(SVGNames::externalResourcesRequiredAttr);
48}
49
50bool SVGExternalResourcesRequired::handleAttributeChange(SVGElement* targetElement, const QualifiedName& attrName)
51{
52    ASSERT(targetElement);
53    if (!isKnownAttribute(attrName))
54        return false;
55    if (!targetElement->inDocument())
56        return true;
57
58    // Handle dynamic updates of the 'externalResourcesRequired' attribute. Only possible case: changing from 'true' to 'false'
59    // causes an immediate dispatch of the SVGLoad event. If the attribute value was 'false' before inserting the script element
60    // in the document, the SVGLoad event has already been dispatched.
61    if (!externalResourcesRequiredBaseValue() && !haveFiredLoadEvent() && !isParserInserted()) {
62        setHaveFiredLoadEvent(true);
63        ASSERT(targetElement->haveLoadedRequiredResources());
64
65        targetElement->sendSVGLoadEventIfPossible();
66    }
67
68    return true;
69}
70
71void SVGExternalResourcesRequired::dispatchLoadEvent(SVGElement* targetElement)
72{
73    bool externalResourcesRequired = externalResourcesRequiredBaseValue();
74
75    if (isParserInserted())
76        ASSERT(externalResourcesRequired != haveFiredLoadEvent());
77    else if (haveFiredLoadEvent())
78        return;
79
80    // HTML and SVG differ completely in the 'onload' event handling of <script> elements.
81    // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwise an error event.
82    // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
83    // is set to 'false', otherwise it dispatches the 'SVGLoad' event just after loading the remote resource.
84    if (!externalResourcesRequired)
85        return;
86
87    ASSERT(!haveFiredLoadEvent());
88
89    // Dispatch SVGLoad event
90    setHaveFiredLoadEvent(true);
91    ASSERT(targetElement->haveLoadedRequiredResources());
92
93    targetElement->sendSVGLoadEventIfPossible();
94}
95
96void SVGExternalResourcesRequired::insertedIntoDocument(SVGElement* targetElement)
97{
98    if (isParserInserted())
99        return;
100
101    // Eventually send SVGLoad event now for the dynamically inserted script element.
102    if (externalResourcesRequiredBaseValue())
103        return;
104    setHaveFiredLoadEvent(true);
105    targetElement->sendSVGLoadEventIfPossibleAsynchronously();
106}
107
108void SVGExternalResourcesRequired::finishParsingChildren()
109{
110    // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
111    if (!externalResourcesRequiredBaseValue())
112        setHaveFiredLoadEvent(true);
113}
114
115bool SVGExternalResourcesRequired::haveLoadedRequiredResources() const
116{
117    return !externalResourcesRequiredBaseValue() || haveFiredLoadEvent();
118}
119
120}
121