1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) 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 39 namespace WebCore { 40 41 class DocumentFragment; 42 class HTMLLinkElement; 43 class KURL; 44 class LinkImport; 45 46 template<typename T> class EventSender; 47 typedef 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 // 58 class LinkStyle FINAL : public LinkResource, ResourceOwner<StyleSheetResource> { 59 WTF_MAKE_FAST_ALLOCATED; 60 public: 61 static PassOwnPtr<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 71 void startLoadingDynamicSheet(); 72 void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred); 73 bool sheetLoaded(); 74 75 void setDisabledState(bool); 76 void setSheetTitle(const String&); 77 78 bool styleSheetIsLoading() const; 79 bool hasSheet() const { return m_sheet; } 80 bool isDisabled() const { return m_disabledState == Disabled; } 81 bool isEnabledViaScript() const { return m_disabledState == EnabledViaScript; } 82 bool isUnset() const { return m_disabledState == Unset; } 83 84 CSSStyleSheet* sheet() const { return m_sheet.get(); } 85 86 private: 87 // From ResourceClient 88 virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource*) OVERRIDE; 89 90 enum DisabledState { 91 Unset, 92 EnabledViaScript, 93 Disabled 94 }; 95 96 enum PendingSheetType { 97 None, 98 NonBlocking, 99 Blocking 100 }; 101 102 enum RemovePendingSheetNotificationType { 103 RemovePendingSheetNotifyImmediately, 104 RemovePendingSheetNotifyLater 105 }; 106 107 void clearSheet(); 108 void addPendingSheet(PendingSheetType); 109 void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately); 110 Document& document(); 111 112 RefPtr<CSSStyleSheet> m_sheet; 113 DisabledState m_disabledState; 114 PendingSheetType m_pendingSheetType; 115 bool m_loading; 116 bool m_firedLoad; 117 bool m_loadedSheet; 118 }; 119 120 121 class HTMLLinkElement FINAL : public HTMLElement, public LinkLoaderClient { 122 public: 123 static PassRefPtr<HTMLLinkElement> create(Document&, bool createdByParser); 124 virtual ~HTMLLinkElement(); 125 126 KURL href() const; 127 const AtomicString& rel() const; 128 String media() const { return m_media; } 129 String typeValue() const { return m_type; } 130 const LinkRelAttribute& relAttribute() const { return m_relAttribute; } 131 132 virtual String target() const; 133 134 const AtomicString& type() const; 135 136 IconType iconType() const; 137 138 // the icon size string as parsed from the HTML attribute 139 String iconSizes() const; 140 141 CSSStyleSheet* sheet() const { return linkStyle() ? linkStyle()->sheet() : 0; } 142 Document* import() const; 143 144 bool styleSheetIsLoading() const; 145 146 bool isDisabled() const { return linkStyle() && linkStyle()->isDisabled(); } 147 bool isEnabledViaScript() const { return linkStyle() && linkStyle()->isEnabledViaScript(); } 148 DOMSettableTokenList* sizes() const; 149 150 void dispatchPendingEvent(LinkEventSender*); 151 void scheduleEvent(); 152 static void dispatchPendingLoadEvents(); 153 154 // From LinkLoaderClient 155 virtual bool shouldLoadLink() OVERRIDE; 156 157 // For LinkStyle 158 bool loadLink(const String& type, const KURL& url) { return m_linkLoader.loadLink(m_relAttribute, type, url, document()); } 159 bool isAlternate() const { return linkStyle()->isUnset() && m_relAttribute.isAlternate(); } 160 bool shouldProcessStyle() { return linkResourceToProcess() && linkStyle(); } 161 162 private: 163 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; 164 165 LinkStyle* linkStyle() const; 166 LinkImport* linkImport() const; 167 LinkResource* linkResourceToProcess(); 168 169 void process(); 170 static void processCallback(Node*); 171 172 // From Node and subclassses 173 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 174 virtual void removedFrom(ContainerNode*) OVERRIDE; 175 virtual bool isURLAttribute(const Attribute&) const OVERRIDE; 176 virtual bool sheetLoaded() OVERRIDE; 177 virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) OVERRIDE; 178 virtual void startLoadingDynamicSheet() OVERRIDE; 179 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const OVERRIDE; 180 virtual void finishParsingChildren(); 181 182 // From LinkLoaderClient 183 virtual void linkLoaded() OVERRIDE; 184 virtual void linkLoadingErrored() OVERRIDE; 185 virtual void didStartLinkPrerender() OVERRIDE; 186 virtual void didStopLinkPrerender() OVERRIDE; 187 virtual void didSendLoadForLinkPrerender() OVERRIDE; 188 virtual void didSendDOMContentLoadedForLinkPrerender() OVERRIDE; 189 190 private: 191 HTMLLinkElement(Document&, bool createdByParser); 192 193 OwnPtr<LinkResource> m_link; 194 LinkLoader m_linkLoader; 195 196 String m_type; 197 String m_media; 198 RefPtr<DOMSettableTokenList> m_sizes; 199 LinkRelAttribute m_relAttribute; 200 201 bool m_createdByParser; 202 bool m_isInShadowTree; 203 int m_beforeLoadRecurseCount; 204 }; 205 206 DEFINE_NODE_TYPE_CASTS(HTMLLinkElement, hasTagName(HTMLNames::linkTag)); 207 208 } //namespace 209 210 #endif 211