1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2008, 2010 Apple Inc. All rights reserved.
5 * Copyright (C) 2011 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB.  If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#ifndef HTMLLinkElement_h
25#define HTMLLinkElement_h
26
27#include "core/css/CSSStyleSheet.h"
28#include "core/dom/DOMSettableTokenList.h"
29#include "core/dom/IconURL.h"
30#include "core/fetch/ResourceOwner.h"
31#include "core/fetch/StyleSheetResource.h"
32#include "core/fetch/StyleSheetResourceClient.h"
33#include "core/html/HTMLElement.h"
34#include "core/html/LinkRelAttribute.h"
35#include "core/html/LinkResource.h"
36#include "core/loader/LinkLoader.h"
37#include "core/loader/LinkLoaderClient.h"
38
39namespace blink {
40
41class DocumentFragment;
42class HTMLLinkElement;
43class KURL;
44class LinkImport;
45
46template<typename T> class EventSender;
47typedef EventSender<HTMLLinkElement> LinkEventSender;
48
49//
50// LinkStyle handles dynaically change-able link resources, which is
51// typically @rel="stylesheet".
52//
53// It could be @rel="shortcut icon" or soething else though. Each of
54// types might better be handled by a separate class, but dynamically
55// changing @rel makes it harder to move such a design so we are
56// sticking current way so far.
57//
58class LinkStyle FINAL : public LinkResource, ResourceOwner<StyleSheetResource> {
59    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
60public:
61    static PassOwnPtrWillBeRawPtr<LinkStyle> create(HTMLLinkElement* owner);
62
63    explicit LinkStyle(HTMLLinkElement* owner);
64    virtual ~LinkStyle();
65
66    virtual Type type() const OVERRIDE { return Style; }
67    virtual void process() OVERRIDE;
68    virtual void ownerRemoved() OVERRIDE;
69    virtual bool hasLoaded() const OVERRIDE { return m_loadedSheet; }
70    virtual void trace(Visitor*) OVERRIDE;
71
72    void startLoadingDynamicSheet();
73    void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred);
74    bool sheetLoaded();
75
76    void setDisabledState(bool);
77    void setSheetTitle(const String&);
78
79    bool styleSheetIsLoading() const;
80    bool hasSheet() const { return m_sheet; }
81    bool isDisabled() const { return m_disabledState == Disabled; }
82    bool isEnabledViaScript() const { return m_disabledState == EnabledViaScript; }
83    bool isUnset() const { return m_disabledState == Unset; }
84
85    CSSStyleSheet* sheet() const { return m_sheet.get(); }
86
87private:
88    // From StyleSheetResourceClient
89    virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource*) OVERRIDE;
90
91    enum DisabledState {
92        Unset,
93        EnabledViaScript,
94        Disabled
95    };
96
97    enum PendingSheetType {
98        None,
99        NonBlocking,
100        Blocking
101    };
102
103    void clearSheet();
104    void addPendingSheet(PendingSheetType);
105    void removePendingSheet();
106    Document& document();
107
108    RefPtrWillBeMember<CSSStyleSheet> m_sheet;
109    DisabledState m_disabledState;
110    PendingSheetType m_pendingSheetType;
111    bool m_loading;
112    bool m_firedLoad;
113    bool m_loadedSheet;
114};
115
116
117class HTMLLinkElement FINAL : public HTMLElement, public LinkLoaderClient {
118    DEFINE_WRAPPERTYPEINFO();
119public:
120    static PassRefPtrWillBeRawPtr<HTMLLinkElement> create(Document&, bool createdByParser);
121    virtual ~HTMLLinkElement();
122
123    KURL href() const;
124    const AtomicString& rel() const;
125    String media() const { return m_media; }
126    String typeValue() const { return m_type; }
127    const LinkRelAttribute& relAttribute() const { return m_relAttribute; }
128
129    const AtomicString& type() const;
130
131    IconType iconType() const;
132
133    // the icon sizes as parsed from the HTML attribute
134    const Vector<IntSize>& iconSizes() const;
135
136    bool async() const;
137
138    CSSStyleSheet* sheet() const { return linkStyle() ? linkStyle()->sheet() : 0; }
139    Document* import() const;
140
141    bool styleSheetIsLoading() const;
142
143    bool isImport() const { return linkImport(); }
144    bool isDisabled() const { return linkStyle() && linkStyle()->isDisabled(); }
145    bool isEnabledViaScript() const { return linkStyle() && linkStyle()->isEnabledViaScript(); }
146    void enableIfExitTransitionStyle();
147
148    DOMSettableTokenList* sizes() const;
149
150    void dispatchPendingEvent(LinkEventSender*);
151    void scheduleEvent();
152    void dispatchEventImmediately();
153    static void dispatchPendingLoadEvents();
154
155    // From LinkLoaderClient
156    virtual bool shouldLoadLink() OVERRIDE;
157
158    // For LinkStyle
159    bool loadLink(const String& type, const KURL&);
160    bool isAlternate() const { return linkStyle()->isUnset() && m_relAttribute.isAlternate(); }
161    bool shouldProcessStyle() { return linkResourceToProcess() && linkStyle(); }
162    bool isCreatedByParser() const { return m_createdByParser; }
163
164    // Parse the icon size attribute into |iconSizes|, make this method public
165    // visible for testing purpose.
166    static void parseSizesAttribute(const AtomicString& value, Vector<IntSize>& iconSizes);
167
168    virtual void trace(Visitor*) OVERRIDE;
169
170private:
171    virtual void attributeWillChange(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue) OVERRIDE;
172    virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
173
174    LinkStyle* linkStyle() const;
175    LinkImport* linkImport() const;
176    LinkResource* linkResourceToProcess();
177
178    void process();
179    static void processCallback(Node*);
180
181    // From Node and subclassses
182    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
183    virtual void removedFrom(ContainerNode*) OVERRIDE;
184    virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
185    virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE;
186    virtual const QualifiedName& subResourceAttributeName() const OVERRIDE;
187    virtual bool sheetLoaded() OVERRIDE;
188    virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) OVERRIDE;
189    virtual void startLoadingDynamicSheet() OVERRIDE;
190    virtual void finishParsingChildren() OVERRIDE;
191
192    // From LinkLoaderClient
193    virtual void linkLoaded() OVERRIDE;
194    virtual void linkLoadingErrored() OVERRIDE;
195    virtual void didStartLinkPrerender() OVERRIDE;
196    virtual void didStopLinkPrerender() OVERRIDE;
197    virtual void didSendLoadForLinkPrerender() OVERRIDE;
198    virtual void didSendDOMContentLoadedForLinkPrerender() OVERRIDE;
199
200private:
201    HTMLLinkElement(Document&, bool createdByParser);
202
203    OwnPtrWillBeMember<LinkResource> m_link;
204    LinkLoader m_linkLoader;
205
206    String m_type;
207    String m_media;
208    RefPtrWillBeMember<DOMSettableTokenList> m_sizes;
209    Vector<IntSize> m_iconSizes;
210    LinkRelAttribute m_relAttribute;
211
212    bool m_createdByParser;
213    bool m_isInShadowTree;
214};
215
216} // namespace blink
217
218#endif // HTMLLinkElement_h
219