Changeset 41766 in webkit
- Timestamp:
- Mar 17, 2009, 10:02:19 AM (16 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r41759 r41766 1 2009-03-17 Darin Adler <darin@apple.com> 2 3 Reviewed by Alexey Proskuryakov. 4 5 Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>, 6 seen with inspector, which uses adoptNode 7 https://bugs.webkit.org/show_bug.cgi?id=24624 8 rdar://problem/6422850 9 10 This test has one significant disadvantage. When it fails, the crash typically 11 occurs during a subsequent test, not this one. It would be great if someone figured 12 out at some point how to improve that. 13 14 * fast/dom/HTMLImageElement/image-load-cross-document-expected.txt: Added. 15 * fast/dom/HTMLImageElement/image-load-cross-document.html: Added. 16 * fast/dom/HTMLImageElement/resources/image-load-subframe.html: Added. 17 1 18 2009-03-17 Alexey Proskuryakov <ap@webkit.org> 2 19 -
trunk/WebCore/ChangeLog
r41765 r41766 1 2009-03-17 Darin Adler <darin@apple.com> 2 3 Reviewed by Alexey Proskuryakov. 4 5 Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>, 6 seen with inspector, which uses adoptNode 7 https://bugs.webkit.org/show_bug.cgi?id=24624 8 rdar://problem/6422850 9 10 Test: fast/dom/HTMLImageElement/image-load-cross-document.html 11 12 * dom/Document.cpp: 13 (WebCore::Document::Document): Removed m_imageLoadEventTimer. 14 (WebCore::Document::detach): Removed m_imageLoadEventDispatchSoonList and 15 m_imageLoadEventDispatchingList. 16 (WebCore::Document::implicitClose): Called ImageLoader::dispatchPendingLoadEvents 17 instead of dispatchImageLoadEventsNow. 18 19 * dom/Document.h: Removed ImageLoader, dispatchImageLoadEventSoon, 20 dispatchImageLoadEventsNow, removeImage, m_imageLoadEventDispatchSoonList, 21 m_imageLoadEventDispatchingList, m_imageLoadEventTimer, and imageLoadEventTimerFired. 22 23 * loader/ImageLoader.cpp: 24 (WebCore::loadEventSender): Added. Returns the single global ImageLoadEventSender 25 object used privately as the target of the load event timer. 26 (WebCore::ImageLoader::~ImageLoader): Call ImageLoadEventSender::cancelLoadEvent 27 rather than Document::removeImage. 28 (WebCore::ImageLoader::setImage): Use m_element directly, not element(). 29 (WebCore::ImageLoader::updateFromElement): Ditto. Also name the local variable 30 document instead of doc. 31 (WebCore::ImageLoader::notifyFinished): Call ImageLoadEventSender::dispatchLoadEventSoon 32 rather than Document::dispatchImageLoadEventSoon. 33 (WebCore::ImageLoader::dispatchPendingLoadEvent): Added. Handles the common logic 34 about when load events can be dispatched so that dispatchLoadEvent only has to 35 have the specific part for each derived class. This includes a check that the 36 document is attached, which used to be handled by having documents empty out the 37 image load event vectors in the detach function. 38 (WebCore::ImageLoader::dispatchPendingLoadEvents): Added. Calls the appropriate 39 function on the ImageLoadEventSender, which avoids the need to have that class be 40 public in the ImageLoader header. 41 (WebCore::ImageLoadEventSender::ImageLoadEventSender): Added. Has the code that 42 was previously in the Document constructor. 43 (WebCore::ImageLoadEventSender::dispatchLoadEventSoon): Added. Has the code that 44 was previously in Document::dispatchImageLoadEventSoon. 45 (WebCore::ImageLoadEventSender::cancelLoadEvent): Added. Has the code that was 46 previously in Document::removeImage. 47 (WebCore::ImageLoadEventSender::dispatchPendingLoadEvents): Added. Has the code 48 that was previously in Document::dispatchImageLoadEventsNow. 49 (WebCore::ImageLoadEventSender::timerFired): Added. Calls dispatchPendingLoadEvents. 50 51 * loader/ImageLoader.h: Improved comments. Made the virtual functions private 52 or protected rather than public. Added static dispatchPendingLoadEvents function 53 for use by Document and private dispatchPendingLoadEvent function for use by 54 ImageLoadEventSender. Made setLoadingImage private and eliminated 55 setHaveFiredLoadEvent since that can all be done inside the class without any 56 member functions. 57 58 * html/HTMLImageLoader.cpp: 59 (WebCore::HTMLImageLoader::dispatchLoadEvent): Removed logic to check whether a 60 load event already fired and whether image() is 0. These are now both base class 61 responsibilities. 62 * svg/SVGImageLoader.cpp: 63 (WebCore::SVGImageLoader::dispatchLoadEvent): Ditto. 64 * wml/WMLImageLoader.cpp: 65 (WebCore::WMLImageLoader::dispatchLoadEvent): Ditto. 66 1 67 2009-03-17 Dimitri Glazkov <dglazkov@chromium.org> 2 68 -
trunk/WebCore/dom/Document.cpp
r41549 r41766 285 285 , m_title("") 286 286 , m_titleSetExplicitly(false) 287 , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired)288 287 , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) 289 288 #if ENABLE(XSLT) … … 1297 1296 // indicate destruction mode, i.e. attached() but renderer == 0 1298 1297 setRenderer(0); 1299 1300 // Empty out these lists as a performance optimization, since detaching 1301 // all the individual render objects will cause all the RenderImage 1302 // objects to remove themselves from the lists. 1303 m_imageLoadEventDispatchSoonList.clear(); 1304 m_imageLoadEventDispatchingList.clear(); 1305 1298 1306 1299 m_hoverNode = 0; 1307 1300 m_focusedNode = 0; … … 1583 1576 f->animation()->resumeAnimations(this); 1584 1577 1585 dispatchImageLoadEventsNow();1586 this->dispatchWindowEvent(eventNames().loadEvent, false, false);1578 ImageLoader::dispatchPendingLoadEvents(); 1579 dispatchWindowEvent(eventNames().loadEvent, false, false); 1587 1580 if (f) 1588 1581 f->loader()->handledOnloadEvents(); … … 2875 2868 { 2876 2869 setWindowInlineEventListenerForType(eventType, createEventListener(attr->localName().string(), attr->value(), 0)); 2877 }2878 2879 void Document::dispatchImageLoadEventSoon(ImageLoader* image)2880 {2881 m_imageLoadEventDispatchSoonList.append(image);2882 if (!m_imageLoadEventTimer.isActive())2883 m_imageLoadEventTimer.startOneShot(0);2884 }2885 2886 void Document::removeImage(ImageLoader* image)2887 {2888 // Remove instances of this image from both lists.2889 // Use loops because we allow multiple instances to get into the lists.2890 size_t size = m_imageLoadEventDispatchSoonList.size();2891 for (size_t i = 0; i < size; ++i) {2892 if (m_imageLoadEventDispatchSoonList[i] == image)2893 m_imageLoadEventDispatchSoonList[i] = 0;2894 }2895 size = m_imageLoadEventDispatchingList.size();2896 for (size_t i = 0; i < size; ++i) {2897 if (m_imageLoadEventDispatchingList[i] == image)2898 m_imageLoadEventDispatchingList[i] = 0;2899 }2900 if (m_imageLoadEventDispatchSoonList.isEmpty())2901 m_imageLoadEventTimer.stop();2902 }2903 2904 void Document::dispatchImageLoadEventsNow()2905 {2906 // Need to avoid re-entering this function; if new dispatches are2907 // scheduled before the parent finishes processing the list, they2908 // will set a timer and eventually be processed.2909 if (!m_imageLoadEventDispatchingList.isEmpty())2910 return;2911 2912 m_imageLoadEventTimer.stop();2913 2914 m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList;2915 m_imageLoadEventDispatchSoonList.clear();2916 size_t size = m_imageLoadEventDispatchingList.size();2917 for (size_t i = 0; i < size; ++i) {2918 if (ImageLoader* image = m_imageLoadEventDispatchingList[i])2919 image->dispatchLoadEvent();2920 }2921 m_imageLoadEventDispatchingList.clear();2922 }2923 2924 void Document::imageLoadEventTimerFired(Timer<Document>*)2925 {2926 dispatchImageLoadEventsNow();2927 2870 } 2928 2871 -
trunk/WebCore/dom/Document.h
r41549 r41766 84 84 class HTMLInputElement; 85 85 class HTMLMapElement; 86 class ImageLoader;87 86 class IntPoint; 88 87 class JSNode; … … 640 639 void processHttpEquiv(const String& equiv, const String& content); 641 640 642 void dispatchImageLoadEventSoon(ImageLoader*);643 void dispatchImageLoadEventsNow();644 void removeImage(ImageLoader*);645 646 641 // Returns the owning element in the parent document. 647 642 // Returns 0 if this is the top level document. … … 922 917 mutable AXObjectCache* m_axObjectCache; 923 918 924 Vector<ImageLoader*> m_imageLoadEventDispatchSoonList;925 Vector<ImageLoader*> m_imageLoadEventDispatchingList;926 Timer<Document> m_imageLoadEventTimer;927 928 919 Timer<Document> m_updateFocusAppearanceTimer; 929 920 … … 1037 1028 void updateTitle(); 1038 1029 void removeAllDisconnectedNodeEventListeners(); 1039 void imageLoadEventTimerFired(Timer<Document>*);1040 1030 void updateFocusAppearanceTimerFired(Timer<Document>*); 1041 1031 void updateBaseURL(); -
trunk/WebCore/html/HTMLImageLoader.cpp
r38094 r41766 43 43 void HTMLImageLoader::dispatchLoadEvent() 44 44 { 45 if (!haveFiredLoadEvent() && image()) { 46 setHaveFiredLoadEvent(true); 47 element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false); 48 } 45 element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false); 49 46 } 50 47 -
trunk/WebCore/loader/ImageLoader.cpp
r40638 r41766 2 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.4 * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 32 32 namespace WebCore { 33 33 34 ImageLoader::ImageLoader(Element* elt) 35 : m_element(elt) 34 class ImageLoadEventSender { 35 public: 36 ImageLoadEventSender(); 37 38 void dispatchLoadEventSoon(ImageLoader*); 39 void cancelLoadEvent(ImageLoader*); 40 41 void dispatchPendingLoadEvents(); 42 43 private: 44 ~ImageLoadEventSender(); 45 46 void timerFired(Timer<ImageLoadEventSender>*); 47 48 Timer<ImageLoadEventSender> m_timer; 49 Vector<ImageLoader*> m_dispatchSoonList; 50 Vector<ImageLoader*> m_dispatchingList; 51 }; 52 53 static ImageLoadEventSender& loadEventSender() 54 { 55 DEFINE_STATIC_LOCAL(ImageLoadEventSender, sender, ()); 56 return sender; 57 } 58 59 ImageLoader::ImageLoader(Element* element) 60 : m_element(element) 36 61 , m_image(0) 37 62 , m_firedLoad(true) … … 45 70 if (m_image) 46 71 m_image->removeClient(this); 47 m_element->document()->removeImage(this);72 loadEventSender().cancelLoadEvent(this); 48 73 } 49 74 … … 62 87 } 63 88 64 if (RenderObject* renderer = element()->renderer()) {89 if (RenderObject* renderer = m_element->renderer()) { 65 90 if (!renderer->isImage()) 66 91 return; … … 81 106 // If we're not making renderers for the page, then don't load images. We don't want to slow 82 107 // down the raw HTML parsing case by loading images we don't intend to display. 83 Element* elem = element(); 84 Document* doc = elem->document(); 85 if (!doc->renderer()) 86 return; 87 88 AtomicString attr = elem->getAttribute(elem->imageSourceAttributeName()); 108 Document* document = m_element->document(); 109 if (!document->renderer()) 110 return; 111 112 AtomicString attr = m_element->getAttribute(m_element->imageSourceAttributeName()); 89 113 90 114 if (attr == m_failedLoadURL) … … 96 120 // need (<rdar://problem/5994621>). 97 121 CachedImage* newImage = 0; 98 if (!(attr.isNull() || attr.isEmpty() && doc ->baseURI().isLocalFile())) {122 if (!(attr.isNull() || attr.isEmpty() && document->baseURI().isLocalFile())) { 99 123 if (m_loadManually) { 100 doc ->docLoader()->setAutoLoadImages(false);124 document->docLoader()->setAutoLoadImages(false); 101 125 newImage = new CachedImage(sourceURI(attr)); 102 126 newImage->setLoading(true); 103 newImage->setDocLoader(doc ->docLoader());104 doc ->docLoader()->m_documentResources.set(newImage->url(), newImage);127 newImage->setDocLoader(document->docLoader()); 128 document->docLoader()->m_documentResources.set(newImage->url(), newImage); 105 129 } else 106 newImage = doc ->docLoader()->requestImage(sourceURI(attr));130 newImage = document->docLoader()->requestImage(sourceURI(attr)); 107 131 108 132 // If we do not have an image here, it means that a cross-site … … 120 144 } 121 145 122 if (RenderObject* renderer = elem->renderer()) {146 if (RenderObject* renderer = m_element->renderer()) { 123 147 if (!renderer->isImage()) 124 148 return; … … 140 164 m_imageComplete = true; 141 165 142 Element* elem = element(); 143 elem->document()->dispatchImageLoadEventSoon(this); 144 145 if (RenderObject* renderer = elem->renderer()) { 166 loadEventSender().dispatchLoadEventSoon(this); 167 168 if (RenderObject* renderer = m_element->renderer()) { 146 169 if (!renderer->isImage()) 147 170 return; … … 151 174 } 152 175 153 } 176 void ImageLoader::dispatchPendingLoadEvent() 177 { 178 if (m_firedLoad) 179 return; 180 if (!m_image) 181 return; 182 if (!m_element->document()->attached()) 183 return; 184 m_firedLoad = true; 185 dispatchLoadEvent(); 186 } 187 188 void ImageLoader::dispatchPendingLoadEvents() 189 { 190 loadEventSender().dispatchPendingLoadEvents(); 191 } 192 193 ImageLoadEventSender::ImageLoadEventSender() 194 : m_timer(this, &ImageLoadEventSender::timerFired) 195 { 196 } 197 198 void ImageLoadEventSender::dispatchLoadEventSoon(ImageLoader* loader) 199 { 200 m_dispatchSoonList.append(loader); 201 if (!m_timer.isActive()) 202 m_timer.startOneShot(0); 203 } 204 205 void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader) 206 { 207 // Remove instances of this loader from both lists. 208 // Use loops because we allow multiple instances to get into the lists. 209 size_t size = m_dispatchSoonList.size(); 210 for (size_t i = 0; i < size; ++i) { 211 if (m_dispatchSoonList[i] == loader) 212 m_dispatchSoonList[i] = 0; 213 } 214 size = m_dispatchingList.size(); 215 for (size_t i = 0; i < size; ++i) { 216 if (m_dispatchingList[i] == loader) 217 m_dispatchingList[i] = 0; 218 } 219 if (m_dispatchSoonList.isEmpty()) 220 m_timer.stop(); 221 } 222 223 void ImageLoadEventSender::dispatchPendingLoadEvents() 224 { 225 // Need to avoid re-entering this function; if new dispatches are 226 // scheduled before the parent finishes processing the list, they 227 // will set a timer and eventually be processed. 228 if (!m_dispatchingList.isEmpty()) 229 return; 230 231 m_timer.stop(); 232 233 m_dispatchingList.swap(m_dispatchSoonList); 234 size_t size = m_dispatchingList.size(); 235 for (size_t i = 0; i < size; ++i) { 236 if (ImageLoader* loader = m_dispatchingList[i]) 237 loader->dispatchPendingLoadEvent(); 238 } 239 m_dispatchingList.clear(); 240 } 241 242 void ImageLoadEventSender::timerFired(Timer<ImageLoadEventSender>*) 243 { 244 dispatchPendingLoadEvents(); 245 } 246 247 } -
trunk/WebCore/loader/ImageLoader.h
r39104 r41766 2 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * Copyright (C) 2004 Apple Computer, Inc.4 * Copyright (C) 2004, 2009 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 31 31 32 32 class Element; 33 class ImageLoadEventSender; 33 34 34 35 class ImageLoader : public CachedResourceClient { … … 37 38 virtual ~ImageLoader(); 38 39 40 // This function should be called when the element is attached to a document; starts 41 // loading if a load hasn't already been started. 39 42 void updateFromElement(); 40 43 41 // This method should be called after the 'src' attribute 42 // is set (even when it is not modified) to force the update 43 // and match Firefox and Opera. 44 // This function should be called whenever the 'src' attribute is set, even if its value 45 // doesn't change; starts new load unconditionally (matches Firefox and Opera behavior). 44 46 void updateFromElementIgnoringPreviousError(); 45 46 virtual void dispatchLoadEvent() = 0;47 virtual String sourceURI(const AtomicString&) const = 0;48 47 49 48 Element* element() const { return m_element; } … … 55 54 void setLoadManually(bool loadManually) { m_loadManually = loadManually; } 56 55 57 // CachedResourceClient API 56 bool haveFiredLoadEvent() const { return m_firedLoad; } 57 58 static void dispatchPendingLoadEvents(); 59 60 protected: 58 61 virtual void notifyFinished(CachedResource*); 59 62 60 bool haveFiredLoadEvent() const { return m_firedLoad; } 61 protected: 63 private: 64 virtual void dispatchLoadEvent() = 0; 65 virtual String sourceURI(const AtomicString&) const = 0; 66 67 friend class ImageLoadEventSender; 68 void dispatchPendingLoadEvent(); 69 62 70 void setLoadingImage(CachedImage*); 63 64 void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; }65 71 66 private:67 72 Element* m_element; 68 73 CachedResourceHandle<CachedImage> m_image; -
trunk/WebCore/svg/SVGImageLoader.cpp
r38094 r41766 43 43 void SVGImageLoader::dispatchLoadEvent() 44 44 { 45 if (!haveFiredLoadEvent() && image()) { 46 setHaveFiredLoadEvent(true); 47 48 if (image()->errorOccurred()) 49 element()->dispatchEventForType(eventNames().errorEvent, false, false); 50 else { 51 SVGImageElement* imageElement = static_cast<SVGImageElement*>(element()); 52 if (imageElement->externalResourcesRequiredBaseValue()) 53 imageElement->sendSVGLoadEventIfPossible(true); 54 } 45 if (image()->errorOccurred()) 46 element()->dispatchEventForType(eventNames().errorEvent, false, false); 47 else { 48 SVGImageElement* imageElement = static_cast<SVGImageElement*>(element()); 49 if (imageElement->externalResourcesRequiredBaseValue()) 50 imageElement->sendSVGLoadEventIfPossible(true); 55 51 } 56 52 } -
trunk/WebCore/wml/WMLImageLoader.cpp
r39432 r41766 46 46 { 47 47 // WML doesn't fire any events. 48 if (haveFiredLoadEvent())49 return;50 51 setHaveFiredLoadEvent(true);52 48 } 53 49
Note:
See TracChangeset
for help on using the changeset viewer.