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

Side by Side Diff: third_party/WebKit/Source/core/fetch/ImageResource.cpp

Issue 2054643003: Remove duplication of encoded image data (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring Created 4 years, 5 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
OLDNEW
1 /* 1 /*
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 , m_image(image) 74 , m_image(image)
75 , m_hasDevicePixelRatioHeaderValue(false) 75 , m_hasDevicePixelRatioHeaderValue(false)
76 { 76 {
77 WTF_LOG(Timers, "new ImageResource(Image) %p", this); 77 WTF_LOG(Timers, "new ImageResource(Image) %p", this);
78 setStatus(Cached); 78 setStatus(Cached);
79 } 79 }
80 80
81 ImageResource::~ImageResource() 81 ImageResource::~ImageResource()
82 { 82 {
83 WTF_LOG(Timers, "~ImageResource %p", this); 83 WTF_LOG(Timers, "~ImageResource %p", this);
84 clearImage();
85 } 84 }
86 85
87 DEFINE_TRACE(ImageResource) 86 DEFINE_TRACE(ImageResource)
88 { 87 {
89 visitor->trace(m_multipartParser); 88 visitor->trace(m_multipartParser);
90 Resource::trace(visitor); 89 Resource::trace(visitor);
91 ImageObserver::trace(visitor); 90 ImageObserver::trace(visitor);
92 MultipartImageResourceParser::Client::trace(visitor); 91 MultipartImageResourceParser::Client::trace(visitor);
93 } 92 }
94 93
(...skipping 22 matching lines...) Expand all
117 116
118 void ImageResource::addObserver(ImageResourceObserver* observer) 117 void ImageResource::addObserver(ImageResourceObserver* observer)
119 { 118 {
120 willAddClientOrObserver(); 119 willAddClientOrObserver();
121 120
122 m_observers.add(observer); 121 m_observers.add(observer);
123 122
124 if (isCacheValidator()) 123 if (isCacheValidator())
125 return; 124 return;
126 125
127 if (m_data && !m_image && !errorOccurred()) { 126 DCHECK(!m_data || m_image);
128 createImage();
129 m_image->setData(m_data, true);
130 }
131 127
132 if (m_image && !m_image->isNull()) { 128 if (m_image && !m_image->isNull()) {
133 observer->imageChanged(this); 129 observer->imageChanged(this);
134 } 130 }
135 131
136 if (isLoaded()) { 132 if (isLoaded()) {
137 observer->imageNotifyFinished(this); 133 observer->imageNotifyFinished(this);
138 if (m_observers.contains(observer)) { 134 if (m_observers.contains(observer)) {
139 m_finishedObservers.add(observer); 135 m_finishedObservers.add(observer);
140 m_observers.remove(observer); 136 m_observers.remove(observer);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 } 179 }
184 180
185 bool ImageResource::isSafeToUnlock() const 181 bool ImageResource::isSafeToUnlock() const
186 { 182 {
187 // Note that |m_image| holds a reference to |m_data| in addition to the one held by the Resource parent class. 183 // Note that |m_image| holds a reference to |m_data| in addition to the one held by the Resource parent class.
188 return !m_image || (m_image->hasOneRef() && m_data->refCount() == 2); 184 return !m_image || (m_image->hasOneRef() && m_data->refCount() == 2);
189 } 185 }
190 186
191 void ImageResource::destroyDecodedDataForFailedRevalidation() 187 void ImageResource::destroyDecodedDataForFailedRevalidation()
192 { 188 {
193 m_image = nullptr; 189 m_image->destroyDecodedData();
hiroshige 2016/06/29 07:04:06 I think we have to clear |m_image| here, because w
hiroshige 2016/06/29 08:20:52 Created the tests. https://codereview.chromium.org
hajimehoshi 2016/07/04 10:46:24 Done.
194 setDecodedSize(0);
195 } 190 }
196 191
197 void ImageResource::destroyDecodedDataIfPossible() 192 void ImageResource::destroyDecodedDataIfPossible()
198 { 193 {
199 if (!hasClientsOrObservers() && !isLoading() && (!m_image || (m_image->hasOn eRef() && m_image->isBitmapImage()))) { 194 if (!m_image)
200 m_image = nullptr; 195 return;
201 setDecodedSize(0); 196 if ((!hasClientsOrObservers() && !isLoading() && m_image->hasOneRef() && m_i mage->isBitmapImage()) || !errorOccurred())
hiroshige 2016/06/29 07:04:06 I'm not sure, but can we simplify this condition t
hajimehoshi 2016/07/04 10:46:24 As we talked offline, let's keep this condition as
202 } else if (m_image && !errorOccurred()) {
203 m_image->destroyDecodedData(); 197 m_image->destroyDecodedData();
204 }
205 } 198 }
206 199
207 void ImageResource::doResetAnimation() 200 void ImageResource::doResetAnimation()
208 { 201 {
209 if (m_image) 202 if (m_image)
210 m_image->resetAnimation(); 203 m_image->resetAnimation();
211 } 204 }
212 205
213 void ImageResource::allClientsAndObserversRemoved() 206 void ImageResource::allClientsAndObserversRemoved()
214 { 207 {
215 if (m_image && !errorOccurred()) { 208 if (m_image && !errorOccurred()) {
216 // If possible, delay the resetting until back at the event loop. 209 // If possible, delay the resetting until back at the event loop.
217 // Doing so after a conservative GC prevents resetAnimation() from 210 // Doing so after a conservative GC prevents resetAnimation() from
218 // upsetting ongoing animation updates (crbug.com/613709) 211 // upsetting ongoing animation updates (crbug.com/613709)
219 if (!ThreadHeap::willObjectBeLazilySwept(this)) 212 if (!ThreadHeap::willObjectBeLazilySwept(this))
220 Platform::current()->currentThread()->getWebTaskRunner()->postTask(B LINK_FROM_HERE, bind(&ImageResource::doResetAnimation, wrapWeakPersistent(this)) ); 213 Platform::current()->currentThread()->getWebTaskRunner()->postTask(B LINK_FROM_HERE, bind(&ImageResource::doResetAnimation, wrapWeakPersistent(this)) );
221 else 214 else
222 m_image->resetAnimation(); 215 m_image->resetAnimation();
223 } 216 }
224 if (m_multipartParser) 217 if (m_multipartParser)
225 m_multipartParser->cancel(); 218 m_multipartParser->cancel();
226 Resource::allClientsAndObserversRemoved(); 219 Resource::allClientsAndObserversRemoved();
227 } 220 }
228 221
222 PassRefPtr<SharedBuffer> ImageResource::resourceBuffer() const
223 {
224 RefPtr<SharedBuffer> data = Resource::resourceBuffer();
225 if (data)
226 return data;
f(malita) 2016/06/30 18:21:46 Nit: return data.release();
hajimehoshi 2016/07/04 10:46:24 Done.
227 if (m_image)
228 return m_image->data();
229 return nullptr;
230 }
231
229 void ImageResource::appendData(const char* data, size_t length) 232 void ImageResource::appendData(const char* data, size_t length)
230 { 233 {
231 if (m_multipartParser) { 234 if (m_multipartParser) {
232 m_multipartParser->appendData(data, length); 235 m_multipartParser->appendData(data, length);
233 } else { 236 } else {
234 Resource::appendData(data, length); 237 Resource::appendData(data, length);
235 updateImage(false); 238 updateImage(false);
236 } 239 }
237 } 240 }
238 241
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 325
323 ImageResourceObserverWalker walker(m_observers); 326 ImageResourceObserverWalker walker(m_observers);
324 while (auto* observer = walker.next()) { 327 while (auto* observer = walker.next()) {
325 observer->imageChanged(this, changeRect); 328 observer->imageChanged(this, changeRect);
326 } 329 }
327 } 330 }
328 331
329 void ImageResource::clear() 332 void ImageResource::clear()
330 { 333 {
331 prune(); 334 prune();
332 clearImage();
hiroshige 2016/06/29 07:04:06 Perhaps, we need to call clearImage() here, becaus
hajimehoshi 2016/07/04 10:46:24 Done.
333 m_data.clear(); 335 m_data.clear();
334 setEncodedSize(0); 336 setEncodedSize(0);
335 } 337 }
336 338
337 inline void ImageResource::createImage() 339 inline void ImageResource::createImage()
338 { 340 {
339 // Create the image if it doesn't yet exist. 341 // When |m_image| exists here, this is a previous part of a multipart
342 // response. Recreate it.
340 if (m_image) 343 if (m_image)
341 return; 344 m_image = nullptr;
scroggo_chromium 2016/06/28 15:33:44 It's not obvious to me how this relates to the res
hiroshige 2016/06/29 07:04:06 I think it's better to call clearImage() explicitl
hajimehoshi 2016/07/04 10:46:24 Done.
342 345
343 if (m_response.mimeType() == "image/svg+xml") { 346 if (m_response.mimeType() == "image/svg+xml") {
344 m_image = SVGImage::create(this); 347 m_image = SVGImage::create(this);
345 } else { 348 } else {
346 m_image = BitmapImage::create(this); 349 m_image = BitmapImage::create(this);
347 } 350 }
348 } 351 }
349 352
350 inline void ImageResource::clearImage()
351 {
352 if (!m_image)
353 return;
354
355 // If our Image has an observer, it's always us so we need to clear the back pointer
356 // before dropping our reference.
357 m_image->clearImageObserver();
scroggo_chromium 2016/06/28 15:33:44 Why is it okay to drop this line? My first thought
hajimehoshi 2016/07/04 10:46:24 Ah, you're right. I'll revert this function and ca
358 m_image.clear();
359 }
360
361 void ImageResource::updateImage(bool allDataReceived) 353 void ImageResource::updateImage(bool allDataReceived)
362 { 354 {
363 TRACE_EVENT0("blink", "ImageResource::updateImage"); 355 TRACE_EVENT0("blink", "ImageResource::updateImage");
364 356
365 if (m_data) 357 if (m_data)
366 createImage(); 358 createImage();
367 359
368 bool sizeAvailable = false; 360 bool sizeAvailable = false;
369 361
370 // Have the image update its data from its internal buffer. 362 // Have the image update its data from its internal buffer.
371 // It will not do anything now, but will delay decoding until 363 // It will not do anything now, but will delay decoding until
372 // queried for info (like size or specific image frames). 364 // queried for info (like size or specific image frames).
373 if (m_image) 365 if (m_image && m_data)
scroggo_chromium 2016/06/28 15:33:44 If we have m_data, aren't we guaranteed to also ha
hajimehoshi 2016/07/04 10:46:24 Right, now m_image's lifetime should include m_dat
374 sizeAvailable = m_image->setData(m_data, allDataReceived); 366 sizeAvailable = m_image->setData(m_data, allDataReceived);
375 367
376 // Go ahead and tell our observers to try to draw if we have either 368 // Go ahead and tell our observers to try to draw if we have either
377 // received all the data or the size is known. Each chunk from the 369 // received all the data or the size is known. Each chunk from the
378 // network causes observers to repaint, which will force that chunk 370 // network causes observers to repaint, which will force that chunk
379 // to decode. 371 // to decode.
380 if (sizeAvailable || allDataReceived) { 372 if (sizeAvailable || allDataReceived) {
381 if (!m_image || m_image->isNull()) { 373 if (!m_image || m_image->isNull()) {
382 if (!errorOccurred()) 374 if (!errorOccurred())
383 setStatus(DecodeError); 375 setStatus(DecodeError);
384 clear(); 376 clear();
385 if (memoryCache()->contains(this)) 377 if (memoryCache()->contains(this))
386 memoryCache()->remove(this); 378 memoryCache()->remove(this);
387 } 379 }
388 380
389 // It would be nice to only redraw the decoded band of the image, but wi th the current design 381 // It would be nice to only redraw the decoded band of the image, but wi th the current design
390 // (decoding delayed until painting) that seems hard. 382 // (decoding delayed until painting) that seems hard.
391 notifyObservers(); 383 notifyObservers();
392 } 384 }
393 }
394 385
395 void ImageResource::updateImageAndClearBuffer() 386 if (allDataReceived)
396 { 387 m_data.clear();
397 clearImage();
398 updateImage(true);
399 m_data.clear();
400 } 388 }
401 389
402 void ImageResource::finish(double loadFinishTime) 390 void ImageResource::finish(double loadFinishTime)
403 { 391 {
404 if (m_multipartParser) { 392 if (m_multipartParser) {
405 m_multipartParser->finish(); 393 m_multipartParser->finish();
406 if (m_data) 394 if (m_data)
407 updateImageAndClearBuffer(); 395 updateImage(true);
408 } else { 396 } else {
409 updateImage(true); 397 updateImage(true);
410 } 398 }
411 Resource::finish(loadFinishTime); 399 Resource::finish(loadFinishTime);
412 } 400 }
413 401
414 void ImageResource::error(const ResourceError& error) 402 void ImageResource::error(const ResourceError& error)
415 { 403 {
416 if (m_multipartParser) 404 if (m_multipartParser)
417 m_multipartParser->cancel(); 405 m_multipartParser->cancel();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 499
512 void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher) 500 void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher)
513 { 501 {
514 if (!m_response.httpHeaderField("chrome-proxy").contains("q=low")) 502 if (!m_response.httpHeaderField("chrome-proxy").contains("q=low"))
515 return; 503 return;
516 m_resourceRequest.setCachePolicy(WebCachePolicy::BypassingCache); 504 m_resourceRequest.setCachePolicy(WebCachePolicy::BypassingCache);
517 m_resourceRequest.setLoFiState(WebURLRequest::LoFiOff); 505 m_resourceRequest.setLoFiState(WebURLRequest::LoFiOff);
518 if (isLoading()) 506 if (isLoading())
519 m_loader->cancel(); 507 m_loader->cancel();
520 else 508 else
521 updateImageAndClearBuffer(); 509 updateImage(true);
522 setStatus(NotStarted); 510 setStatus(NotStarted);
523 fetcher->startLoad(this); 511 fetcher->startLoad(this);
524 } 512 }
525 513
526 void ImageResource::changedInRect(const blink::Image* image, const IntRect& rect ) 514 void ImageResource::changedInRect(const blink::Image* image, const IntRect& rect )
527 { 515 {
528 if (!image || image != m_image) 516 if (!image || image != m_image)
529 return; 517 return;
530 notifyObservers(&rect); 518 notifyObservers(&rect);
531 } 519 }
532 520
533 void ImageResource::onePartInMultipartReceived(const ResourceResponse& response) 521 void ImageResource::onePartInMultipartReceived(const ResourceResponse& response)
534 { 522 {
535 ASSERT(m_multipartParser); 523 ASSERT(m_multipartParser);
536 524
537 m_response = response; 525 m_response = response;
538 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { 526 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) {
539 // We have nothing to do because we don't have any data. 527 // We have nothing to do because we don't have any data.
540 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; 528 m_multipartParsingState = MultipartParsingState::ParsingFirstPart;
541 return; 529 return;
542 } 530 }
543 updateImageAndClearBuffer(); 531 updateImage(true);
544 532
545 if (m_multipartParsingState == MultipartParsingState::ParsingFirstPart) { 533 if (m_multipartParsingState == MultipartParsingState::ParsingFirstPart) {
546 m_multipartParsingState = MultipartParsingState::FinishedParsingFirstPar t; 534 m_multipartParsingState = MultipartParsingState::FinishedParsingFirstPar t;
547 // Notify finished when the first part ends. 535 // Notify finished when the first part ends.
548 if (!errorOccurred()) 536 if (!errorOccurred())
549 setStatus(Cached); 537 setStatus(Cached);
550 checkNotify(); 538 checkNotify();
551 if (m_loader) 539 if (m_loader)
552 m_loader->didFinishLoadingFirstPartInMultipart(); 540 m_loader->didFinishLoadingFirstPartInMultipart();
553 } 541 }
(...skipping 10 matching lines...) Expand all
564 if (response().wasFetchedViaServiceWorker()) 552 if (response().wasFetchedViaServiceWorker())
565 return response().serviceWorkerResponseType() != WebServiceWorkerRespons eTypeOpaque; 553 return response().serviceWorkerResponseType() != WebServiceWorkerRespons eTypeOpaque;
566 if (!getImage()->currentFrameHasSingleSecurityOrigin()) 554 if (!getImage()->currentFrameHasSingleSecurityOrigin())
567 return false; 555 return false;
568 if (passesAccessControlCheck(securityOrigin)) 556 if (passesAccessControlCheck(securityOrigin))
569 return true; 557 return true;
570 return !securityOrigin->taintsCanvas(response().url()); 558 return !securityOrigin->taintsCanvas(response().url());
571 } 559 }
572 560
573 } // namespace blink 561 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698