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/IconURL.h" 29 #include "core/html/DOMSettableTokenList.h" 30 #include "core/html/HTMLElement.h" 31 #include "core/html/LinkRelAttribute.h" 32 #include "core/html/LinkResource.h" 33 #include "core/loader/LinkLoader.h" 34 #include "core/loader/LinkLoaderClient.h" 35 #include "core/loader/cache/ResourcePtr.h" 36 #include "core/loader/cache/StyleSheetResourceClient.h" 37 38 namespace WebCore { 39 40 class DocumentFragment; 41 class HTMLLinkElement; 42 class KURL; 43 class LinkImport; 44 45 template<typename T> class EventSender; 46 typedef EventSender<HTMLLinkElement> LinkEventSender; 47 48 // 49 // LinkStyle handles dynaically change-able link resources, which is 50 // typically @rel="stylesheet". 51 // 52 // It could be @rel="shortcut icon" or soething else though. Each of 53 // types might better be handled by a separate class, but dynamically 54 // changing @rel makes it harder to move such a design so we are 55 // sticking current way so far. 56 // 57 class LinkStyle FINAL : public LinkResource, StyleSheetResourceClient { 58 WTF_MAKE_FAST_ALLOCATED; 59 public: 60 static PassRefPtr<LinkStyle> create(HTMLLinkElement* owner); 61 62 explicit LinkStyle(HTMLLinkElement* owner); 63 virtual ~LinkStyle(); 64 65 virtual Type type() const OVERRIDE { return Style; } 66 virtual void process() OVERRIDE; 67 virtual void ownerRemoved() OVERRIDE; 68 virtual bool hasLoaded() const OVERRIDE { return m_loadedSheet; } 69 70 void startLoadingDynamicSheet(); 71 void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred); 72 bool sheetLoaded(); 73 74 void setDisabledState(bool); 75 void setSheetTitle(const String&); 76 77 bool styleSheetIsLoading() const; 78 bool hasSheet() const { return m_sheet; } 79 bool isDisabled() const { return m_disabledState == Disabled; } 80 bool isEnabledViaScript() const { return m_disabledState == EnabledViaScript; } 81 bool isUnset() const { return m_disabledState == Unset; } 82 83 CSSStyleSheet* sheet() const { return m_sheet.get(); } 84 85 private: 86 // From ResourceClient 87 virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource*); 88 89 enum DisabledState { 90 Unset, 91 EnabledViaScript, 92 Disabled 93 }; 94 95 enum PendingSheetType { 96 None, 97 NonBlocking, 98 Blocking 99 }; 100 101 enum RemovePendingSheetNotificationType { 102 RemovePendingSheetNotifyImmediately, 103 RemovePendingSheetNotifyLater 104 }; 105 106 void clearSheet(); 107 void addPendingSheet(PendingSheetType); 108 void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately); 109 Document* document(); 110 111 ResourcePtr<CSSStyleSheetResource> m_resource; 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(const QualifiedName&, Document*, bool createdByParser); 124 virtual ~HTMLLinkElement(); 125 126 KURL href() const; 127 String 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 String 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 void setSizes(const String&); 149 DOMSettableTokenList* sizes() const; 150 151 void dispatchPendingEvent(LinkEventSender*); 152 void scheduleEvent(); 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& url) { return m_linkLoader.loadLink(m_relAttribute, type, url, document()); } 160 bool isAlternate() const { return linkStyle()->isUnset() && m_relAttribute.isAlternate(); } 161 bool shouldProcessStyle() { return linkResourceToProcess() && linkStyle(); } 162 163 private: 164 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; 165 166 LinkStyle* linkStyle() const; 167 LinkImport* linkImport() const; 168 LinkResource* linkResourceToProcess(); 169 170 void process(); 171 static void processCallback(Node*); 172 173 // From Node and subclassses 174 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 175 virtual void removedFrom(ContainerNode*) OVERRIDE; 176 virtual bool isURLAttribute(const Attribute&) const OVERRIDE; 177 virtual bool sheetLoaded() OVERRIDE; 178 virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) OVERRIDE; 179 virtual void startLoadingDynamicSheet() OVERRIDE; 180 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const OVERRIDE; 181 virtual void finishParsingChildren(); 182 183 // From LinkLoaderClient 184 virtual void linkLoaded() OVERRIDE; 185 virtual void linkLoadingErrored() OVERRIDE; 186 virtual void didStartLinkPrerender() OVERRIDE; 187 virtual void didStopLinkPrerender() OVERRIDE; 188 virtual void didSendLoadForLinkPrerender() OVERRIDE; 189 virtual void didSendDOMContentLoadedForLinkPrerender() OVERRIDE; 190 191 private: 192 HTMLLinkElement(const QualifiedName&, Document*, bool createdByParser); 193 194 RefPtr<LinkResource> m_link; 195 LinkLoader m_linkLoader; 196 197 String m_type; 198 String m_media; 199 RefPtr<DOMSettableTokenList> m_sizes; 200 LinkRelAttribute m_relAttribute; 201 202 bool m_createdByParser; 203 bool m_isInShadowTree; 204 int m_beforeLoadRecurseCount; 205 }; 206 207 inline HTMLLinkElement* toHTMLLinkElement(Node* node) 208 { 209 ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(HTMLNames::linkTag)); 210 return static_cast<HTMLLinkElement*>(node); 211 } 212 213 } //namespace 214 215 #endif 216