Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: Source/core/loader/ImageLoader.cpp

Issue 200923002: Post a microtask to load <img> elements. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: with a test for isolated world csp Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/loader/ImageLoader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserv ed. 4 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserv ed.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
11 * This library is distributed in the hope that it will be useful, 11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details. 14 * Library General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU Library General Public License 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 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, 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA. 19 * Boston, MA 02110-1301, USA.
20 */ 20 */
21 21
22 #include "config.h" 22 #include "config.h"
23 #include "core/loader/ImageLoader.h" 23 #include "core/loader/ImageLoader.h"
24 24
25 #include "bindings/v8/ScriptController.h"
25 #include "core/dom/Document.h" 26 #include "core/dom/Document.h"
26 #include "core/dom/Element.h" 27 #include "core/dom/Element.h"
28 #include "core/dom/Microtask.h"
27 #include "core/events/Event.h" 29 #include "core/events/Event.h"
28 #include "core/events/EventSender.h" 30 #include "core/events/EventSender.h"
29 #include "core/fetch/CrossOriginAccessControl.h" 31 #include "core/fetch/CrossOriginAccessControl.h"
30 #include "core/fetch/FetchRequest.h" 32 #include "core/fetch/FetchRequest.h"
31 #include "core/fetch/MemoryCache.h" 33 #include "core/fetch/MemoryCache.h"
32 #include "core/fetch/ResourceFetcher.h" 34 #include "core/fetch/ResourceFetcher.h"
33 #include "core/html/HTMLObjectElement.h" 35 #include "core/frame/LocalFrame.h"
36 #include "core/html/HTMLImageElement.h"
34 #include "core/html/parser/HTMLParserIdioms.h" 37 #include "core/html/parser/HTMLParserIdioms.h"
35 #include "core/rendering/RenderImage.h" 38 #include "core/rendering/RenderImage.h"
36 #include "core/rendering/RenderVideo.h" 39 #include "core/rendering/RenderVideo.h"
37 #include "core/rendering/svg/RenderSVGImage.h" 40 #include "core/rendering/svg/RenderSVGImage.h"
38 #include "platform/weborigin/SecurityOrigin.h" 41 #include "platform/weborigin/SecurityOrigin.h"
39 42
40 namespace WebCore { 43 namespace WebCore {
41 44
42 static ImageEventSender& loadEventSender() 45 static ImageEventSender& loadEventSender()
43 { 46 {
44 DEFINE_STATIC_LOCAL(ImageEventSender, sender, (EventTypeNames::load)); 47 DEFINE_STATIC_LOCAL(ImageEventSender, sender, (EventTypeNames::load));
45 return sender; 48 return sender;
46 } 49 }
47 50
48 static ImageEventSender& errorEventSender() 51 static ImageEventSender& errorEventSender()
49 { 52 {
50 DEFINE_STATIC_LOCAL(ImageEventSender, sender, (EventTypeNames::error)); 53 DEFINE_STATIC_LOCAL(ImageEventSender, sender, (EventTypeNames::error));
51 return sender; 54 return sender;
52 } 55 }
53 56
54 static inline bool pageIsBeingDismissed(Document* document) 57 static inline bool pageIsBeingDismissed(Document* document)
55 { 58 {
56 return document->pageDismissalEventBeingDispatched() != Document::NoDismissa l; 59 return document->pageDismissalEventBeingDispatched() != Document::NoDismissa l;
57 } 60 }
58 61
62 class ImageLoader::Task : public blink::WebThread::Task {
63 public:
64 Task(ImageLoader* loader)
65 : m_loader(loader)
66 , m_document(&m_loader->m_element->document())
67 , m_shouldBypassMainWorldContentSecurityPolicy(false)
68 {
69 m_document->incrementLoadEventDelayCount();
abarth-chromium 2014/04/25 23:59:44 Why is it the task's job to increment and decremen
cbiesinger 2014/05/01 00:09:08 Well the entire reason was your request to have a
70
71 LocalFrame* frame = m_document->frame();
72 m_shouldBypassMainWorldContentSecurityPolicy =
73 frame && frame->script().shouldBypassMainWorldContentSecurityPolicy( );
abarth-chromium 2014/04/25 23:59:44 Can |frame| actually be zero here?
cbiesinger 2014/05/01 00:09:08 This was copied from https://code.google.com/p/chr
74 }
75
76 virtual ~Task()
77 {
78 clearLoader();
79 }
80
81 virtual void run() OVERRIDE
82 {
83 if (m_loader) {
84 m_loader->m_pendingTask = 0;
abarth-chromium 2014/04/25 23:59:44 This works seems like it should be done by the loa
cbiesinger 2014/05/01 00:09:08 Done. (Note that the task is only friends implicit
85 m_loader->updateFromElement(true, m_shouldBypassMainWorldContentSecu rityPolicy);
abarth-chromium 2014/04/25 23:59:44 Rather than passing a bool from the two different
cbiesinger 2014/05/01 00:09:08 Done.
86 }
87 }
88
89 void clearLoader()
90 {
91 if (m_loader) {
92 m_document->decrementLoadEventDelayCount();
93 m_document.clear();
abarth-chromium 2014/04/25 23:59:44 Once it's the loaders job to increment/decrement t
cbiesinger 2014/05/01 00:09:08 Hm... WeakPtr requires refcounted objects?
94 m_loader = 0;
95 }
96 }
97
98 void documentChanged()
99 {
100 m_document->decrementLoadEventDelayCount();
101 m_document = &m_loader->m_element->document();
102 m_document->incrementLoadEventDelayCount();
103 }
104
105 private:
106 ImageLoader* m_loader;
107 RefPtr<Document> m_document;
108 bool m_shouldBypassMainWorldContentSecurityPolicy;
109 };
110
59 ImageLoader::ImageLoader(Element* element) 111 ImageLoader::ImageLoader(Element* element)
60 : m_element(element) 112 : m_element(element)
61 , m_image(0) 113 , m_image(0)
62 , m_derefElementTimer(this, &ImageLoader::timerFired) 114 , m_derefElementTimer(this, &ImageLoader::timerFired)
115 , m_pendingTask(0)
63 , m_hasPendingLoadEvent(false) 116 , m_hasPendingLoadEvent(false)
64 , m_hasPendingErrorEvent(false) 117 , m_hasPendingErrorEvent(false)
65 , m_imageComplete(true) 118 , m_imageComplete(true)
66 , m_loadManually(false) 119 , m_loadManually(false)
67 , m_elementIsProtected(false) 120 , m_elementIsProtected(false)
68 , m_highPriorityClientCount(0) 121 , m_highPriorityClientCount(0)
69 { 122 {
70 } 123 }
71 124
72 ImageLoader::~ImageLoader() 125 ImageLoader::~ImageLoader()
73 { 126 {
127 if (m_pendingTask)
128 m_pendingTask->clearLoader();
129
74 if (m_image) 130 if (m_image)
75 m_image->removeClient(this); 131 m_image->removeClient(this);
76 132
77 ASSERT(m_hasPendingLoadEvent || !loadEventSender().hasPendingEvents(this)); 133 ASSERT(m_hasPendingLoadEvent || !loadEventSender().hasPendingEvents(this));
78 if (m_hasPendingLoadEvent) 134 if (m_hasPendingLoadEvent)
79 loadEventSender().cancelEvent(this); 135 loadEventSender().cancelEvent(this);
80 136
81 ASSERT(m_hasPendingErrorEvent || !errorEventSender().hasPendingEvents(this)) ; 137 ASSERT(m_hasPendingErrorEvent || !errorEventSender().hasPendingEvents(this)) ;
82 if (m_hasPendingErrorEvent) 138 if (m_hasPendingErrorEvent)
83 errorEventSender().cancelEvent(this); 139 errorEventSender().cancelEvent(this);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 if (newImage) 172 if (newImage)
117 newImage->addClient(this); 173 newImage->addClient(this);
118 if (oldImage) 174 if (oldImage)
119 oldImage->removeClient(this); 175 oldImage->removeClient(this);
120 } 176 }
121 177
122 if (RenderImageResource* imageResource = renderImageResource()) 178 if (RenderImageResource* imageResource = renderImageResource())
123 imageResource->resetAnimation(); 179 imageResource->resetAnimation();
124 } 180 }
125 181
126 void ImageLoader::updateFromElement() 182 void ImageLoader::updateFromElement(bool calledFromTask, bool bypassMainWorldCSP )
127 { 183 {
128 // Don't load images for inactive documents. We don't want to slow down the 184 // Don't load images for inactive documents. We don't want to slow down the
129 // raw HTML parsing case by loading images we don't intend to display. 185 // raw HTML parsing case by loading images we don't intend to display.
130 Document& document = m_element->document(); 186 Document& document = m_element->document();
131 if (!document.isActive()) 187 if (!document.isActive())
132 return; 188 return;
133 189
134 AtomicString attr = m_element->imageSourceURL(); 190 AtomicString attr = m_element->imageSourceURL();
135 191
136 if (!m_failedLoadURL.isEmpty() && attr == m_failedLoadURL) 192 if (!m_failedLoadURL.isEmpty() && attr == m_failedLoadURL)
137 return; 193 return;
138 194
139 // Do not load any image if the 'src' attribute is missing or if it is 195 // Do not load any image if the 'src' attribute is missing or if it is
140 // an empty string. 196 // an empty string.
141 ResourcePtr<ImageResource> newImage = 0; 197 ResourcePtr<ImageResource> newImage = 0;
142 if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { 198 if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) {
143 FetchRequest request(ResourceRequest(document.completeURL(sourceURI(attr ))), element()->localName()); 199 KURL url = document.completeURL(sourceURI(attr));
200 if (!calledFromTask) {
201 // If we have a pending task, we have to clear it -- either we're
202 // now loading immediately, or we need to reset the task's state.
203 if (m_pendingTask) {
204 m_pendingTask->clearLoader();
205 m_pendingTask = 0;
206 }
207 bool loadImmediately = shouldLoadImmediately(url);
208 if (!loadImmediately) {
209 m_pendingTask = new Task(this);
210 Microtask::enqueueMicrotask(adoptPtr(m_pendingTask));
211 return;
212 }
213 }
214
215 FetchRequest request(ResourceRequest(url), element()->localName());
216 if (bypassMainWorldCSP)
217 request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy);
144 218
145 AtomicString crossOriginMode = m_element->fastGetAttribute(HTMLNames::cr ossoriginAttr); 219 AtomicString crossOriginMode = m_element->fastGetAttribute(HTMLNames::cr ossoriginAttr);
146 if (!crossOriginMode.isNull()) 220 if (!crossOriginMode.isNull())
147 request.setCrossOriginAccessControl(document.securityOrigin(), cross OriginMode); 221 request.setCrossOriginAccessControl(document.securityOrigin(), cross OriginMode);
148 222
149 if (m_loadManually) { 223 if (m_loadManually) {
150 bool autoLoadOtherImages = document.fetcher()->autoLoadImages(); 224 bool autoLoadOtherImages = document.fetcher()->autoLoadImages();
151 document.fetcher()->setAutoLoadImages(false); 225 document.fetcher()->setAutoLoadImages(false);
152 newImage = new ImageResource(request.resourceRequest()); 226 newImage = new ImageResource(request.resourceRequest());
153 newImage->setLoading(true); 227 newImage->setLoading(true);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 // from this function as doing so might result in the destruction of this Im ageLoader. 291 // from this function as doing so might result in the destruction of this Im ageLoader.
218 updatedHasPendingEvent(); 292 updatedHasPendingEvent();
219 } 293 }
220 294
221 void ImageLoader::updateFromElementIgnoringPreviousError() 295 void ImageLoader::updateFromElementIgnoringPreviousError()
222 { 296 {
223 clearFailedLoadURL(); 297 clearFailedLoadURL();
224 updateFromElement(); 298 updateFromElement();
225 } 299 }
226 300
301 bool ImageLoader::shouldLoadImmediately(const KURL& url) const
302 {
303 if (m_loadManually)
304 return true;
305
306 if (url.protocolIsData())
307 return true;
308 if (memoryCache()->resourceForURL(url))
309 return true;
310 return false;
311 }
312
227 void ImageLoader::notifyFinished(Resource* resource) 313 void ImageLoader::notifyFinished(Resource* resource)
228 { 314 {
229 ASSERT(m_failedLoadURL.isEmpty()); 315 ASSERT(m_failedLoadURL.isEmpty());
230 ASSERT(resource == m_image.get()); 316 ASSERT(resource == m_image.get());
231 317
232 m_imageComplete = true; 318 m_imageComplete = true;
233 updateRenderer(); 319 updateRenderer();
234 320
235 if (!m_hasPendingLoadEvent) 321 if (!m_hasPendingLoadEvent)
236 return; 322 return;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 loadEventSender().dispatchPendingEvents(); 468 loadEventSender().dispatchPendingEvents();
383 } 469 }
384 470
385 void ImageLoader::dispatchPendingErrorEvents() 471 void ImageLoader::dispatchPendingErrorEvents()
386 { 472 {
387 errorEventSender().dispatchPendingEvents(); 473 errorEventSender().dispatchPendingEvents();
388 } 474 }
389 475
390 void ImageLoader::elementDidMoveToNewDocument() 476 void ImageLoader::elementDidMoveToNewDocument()
391 { 477 {
478 if (m_pendingTask) {
479 m_pendingTask->documentChanged();
480 }
392 clearFailedLoadURL(); 481 clearFailedLoadURL();
393 setImage(0); 482 setImage(0);
394 } 483 }
395 484
396 void ImageLoader::sourceImageChanged() 485 void ImageLoader::sourceImageChanged()
397 { 486 {
398 ImageLoaderClientSet::iterator end = m_clients.end(); 487 ImageLoaderClientSet::iterator end = m_clients.end();
399 for (ImageLoaderClientSet::iterator it = m_clients.begin(); it != end; ++it) { 488 for (ImageLoaderClientSet::iterator it = m_clients.begin(); it != end; ++it) {
400 ImageLoaderClient* handle = *it; 489 ImageLoaderClient* handle = *it;
401 handle->notifyImageSourceChanged(); 490 handle->notifyImageSourceChanged();
402 } 491 }
403 } 492 }
404 493
405 inline void ImageLoader::clearFailedLoadURL() 494 inline void ImageLoader::clearFailedLoadURL()
406 { 495 {
407 m_failedLoadURL = AtomicString(); 496 m_failedLoadURL = AtomicString();
408 } 497 }
409 498
410 } 499 }
OLDNEW
« no previous file with comments | « Source/core/loader/ImageLoader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698