1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * Copyright (C) 2004, 2009 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef ImageLoader_h 24 #define ImageLoader_h 25 26 #include "core/fetch/ImageResource.h" 27 #include "core/fetch/ImageResourceClient.h" 28 #include "core/fetch/ResourcePtr.h" 29 #include "platform/heap/Handle.h" 30 #include "wtf/HashSet.h" 31 #include "wtf/WeakPtr.h" 32 #include "wtf/text/AtomicString.h" 33 34 namespace WebCore { 35 36 class IncrementLoadEventDelayCount; 37 38 class ImageLoaderClient : public WillBeGarbageCollectedMixin { 39 public: 40 virtual void notifyImageSourceChanged() = 0; 41 42 // Determines whether the observed ImageResource should have higher priority in the decoded resources cache. 43 virtual bool requestsHighLiveResourceCachePriority() { return false; } 44 45 virtual void trace(Visitor*) { } 46 47 protected: 48 ImageLoaderClient() { } 49 }; 50 51 class Element; 52 class ImageLoader; 53 class RenderImageResource; 54 55 template<typename T> class EventSender; 56 typedef EventSender<ImageLoader> ImageEventSender; 57 58 class ImageLoader : public NoBaseWillBeGarbageCollectedFinalized<ImageLoader>, public ImageResourceClient { 59 public: 60 explicit ImageLoader(Element*); 61 virtual ~ImageLoader(); 62 void trace(Visitor*); 63 64 enum LoadType { 65 LoadNormally, 66 ForceLoadImmediately 67 }; 68 69 // This function should be called when the element is attached to a document; starts 70 // loading if a load hasn't already been started. 71 void updateFromElement(LoadType = LoadNormally); 72 73 // This function should be called whenever the 'src' attribute is set, even if its value 74 // doesn't change; starts new load unconditionally (matches Firefox and Opera behavior). 75 void updateFromElementIgnoringPreviousError(); 76 77 void elementDidMoveToNewDocument(); 78 79 Element* element() const { return m_element; } 80 bool imageComplete() const 81 { 82 return m_imageComplete && !m_pendingTask; 83 } 84 85 ImageResource* image() const { return m_image.get(); } 86 void setImage(ImageResource*); // Cancels pending load events, and doesn't dispatch new ones. 87 88 void setLoadManually(bool loadManually) { m_loadManually = loadManually; } 89 90 bool hasPendingActivity() const 91 { 92 return m_hasPendingLoadEvent || m_hasPendingErrorEvent || m_pendingTask; 93 } 94 95 void dispatchPendingEvent(ImageEventSender*); 96 97 static void dispatchPendingLoadEvents(); 98 static void dispatchPendingErrorEvents(); 99 100 void addClient(ImageLoaderClient*); 101 void removeClient(ImageLoaderClient*); 102 103 protected: 104 virtual void notifyFinished(Resource*) OVERRIDE; 105 106 private: 107 class Task; 108 109 // Called from the task or from updateFromElement to initiate the load. 110 void doUpdateFromElement(bool bypassMainWorldCSP = false); 111 112 virtual void dispatchLoadEvent() = 0; 113 virtual String sourceURI(const AtomicString&) const = 0; 114 115 void updatedHasPendingEvent(); 116 117 void dispatchPendingLoadEvent(); 118 void dispatchPendingErrorEvent(); 119 120 RenderImageResource* renderImageResource(); 121 void updateRenderer(); 122 123 void setImageWithoutConsideringPendingLoadEvent(ImageResource*); 124 void sourceImageChanged(); 125 void clearFailedLoadURL(); 126 127 void timerFired(Timer<ImageLoader>*); 128 129 KURL imageURL() const; 130 131 // Used to determine whether to immediately initiate the load 132 // or to schedule a microtask. 133 bool shouldLoadImmediately(const KURL&) const; 134 135 void willRemoveClient(ImageLoaderClient&); 136 137 RawPtrWillBeMember<Element> m_element; 138 ResourcePtr<ImageResource> m_image; 139 // FIXME: Oilpan: We might be able to remove this Persistent hack when 140 // ImageResourceClient is traceable. 141 GC_PLUGIN_IGNORE("http://crbug.com/383741") 142 RefPtrWillBePersistent<Element> m_keepAlive; 143 #if ENABLE(OILPAN) 144 class ImageLoaderClientRemover { 145 public: 146 ImageLoaderClientRemover(ImageLoader& loader, ImageLoaderClient& client) : m_loader(loader), m_client(client) { } 147 ~ImageLoaderClientRemover(); 148 149 private: 150 ImageLoader& m_loader; 151 ImageLoaderClient& m_client; 152 }; 153 friend class ImageLoaderClientRemover; 154 // Oilpan: This ImageLoader object must outlive its clients because they 155 // need to call ImageLoader::willRemoveClient before they 156 // die. Non-Persistent HeapHashMap doesn't work well because weak processing 157 // for HeapHashMap is not triggered when both of ImageLoader and 158 // ImageLoaderClient are unreachable. 159 GC_PLUGIN_IGNORE("http://crbug.com/383742") 160 PersistentHeapHashMap<WeakMember<ImageLoaderClient>, OwnPtr<ImageLoaderClientRemover> > m_clients; 161 #else 162 HashSet<ImageLoaderClient*> m_clients; 163 #endif 164 Timer<ImageLoader> m_derefElementTimer; 165 AtomicString m_failedLoadURL; 166 WeakPtr<Task> m_pendingTask; // owned by Microtask 167 OwnPtr<IncrementLoadEventDelayCount> m_delayLoad; 168 bool m_hasPendingLoadEvent : 1; 169 bool m_hasPendingErrorEvent : 1; 170 bool m_imageComplete : 1; 171 bool m_loadManually : 1; 172 bool m_elementIsProtected : 1; 173 unsigned m_highPriorityClientCount; 174 }; 175 176 } 177 178 #endif 179