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

Side by Side Diff: content/renderer/image_downloader/image_downloader_core.cc

Issue 2538853002: Media Remoting: Draw remoting interstitial on poster image. (Closed)
Patch Set: Addressed comments. Created 4 years 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 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/image_downloader/image_downloader_impl.h" 5 #include "content/renderer/image_downloader/image_downloader_core.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "content/child/image_decoder.h" 12 #include "content/child/image_decoder.h"
15 #include "content/public/renderer/render_frame.h" 13 #include "content/public/renderer/render_frame.h"
16 #include "content/public/renderer/render_thread.h" 14 #include "content/public/renderer/render_thread.h"
17 #include "content/renderer/fetchers/multi_resolution_image_resource_fetcher.h" 15 #include "content/renderer/fetchers/multi_resolution_image_resource_fetcher.h"
18 #include "net/base/data_url.h" 16 #include "net/base/data_url.h"
19 #include "skia/ext/image_operations.h"
20 #include "third_party/WebKit/public/platform/WebCachePolicy.h" 17 #include "third_party/WebKit/public/platform/WebCachePolicy.h"
21 #include "third_party/WebKit/public/platform/WebURLRequest.h" 18 #include "third_party/WebKit/public/platform/WebURLRequest.h"
22 #include "third_party/WebKit/public/platform/WebVector.h"
23 #include "third_party/WebKit/public/web/WebLocalFrame.h" 19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
24 #include "third_party/WebKit/public/web/WebView.h"
25 #include "ui/gfx/favicon_size.h" 20 #include "ui/gfx/favicon_size.h"
26 #include "ui/gfx/geometry/size.h" 21 #include "ui/gfx/geometry/size.h"
27 #include "ui/gfx/skbitmap_operations.h"
28 #include "url/url_constants.h" 22 #include "url/url_constants.h"
29 23
30 using blink::WebCachePolicy; 24 using blink::WebCachePolicy;
31 using blink::WebFrame; 25 using blink::WebFrame;
32 using blink::WebVector;
33 using blink::WebURL;
34 using blink::WebURLRequest; 26 using blink::WebURLRequest;
35 27
36 namespace { 28 namespace {
37 29
38 // Decodes a data: URL image or returns an empty image in case of failure. 30 // Decodes a data: URL image or returns an empty image in case of failure.
39 SkBitmap ImageFromDataUrl(const GURL& url) { 31 SkBitmap ImageFromDataUrl(const GURL& url) {
40 std::string mime_type, char_set, data; 32 std::string mime_type, char_set, data;
41 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) { 33 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
42 // Decode the image using Blink's image decoder. 34 // Decode the image using Blink's image decoder.
43 content::ImageDecoder decoder( 35 content::ImageDecoder decoder(
44 gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); 36 gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize));
45 const unsigned char* src_data = 37 const unsigned char* src_data =
46 reinterpret_cast<const unsigned char*>(data.data()); 38 reinterpret_cast<const unsigned char*>(data.data());
47 39
48 return decoder.Decode(src_data, data.size()); 40 return decoder.Decode(src_data, data.size());
49 } 41 }
50 return SkBitmap(); 42 return SkBitmap();
51 } 43 }
52 44
53 // Proportionally resizes the |image| to fit in a box of size
54 // |max_image_size|.
55 SkBitmap ResizeImage(const SkBitmap& image, uint32_t max_image_size) {
56 if (max_image_size == 0)
57 return image;
58 uint32_t max_dimension = std::max(image.width(), image.height());
59 if (max_dimension <= max_image_size)
60 return image;
61 // Proportionally resize the minimal image to fit in a box of size
62 // max_image_size.
63 return skia::ImageOperations::Resize(
64 image, skia::ImageOperations::RESIZE_BEST,
65 static_cast<uint64_t>(image.width()) * max_image_size / max_dimension,
66 static_cast<uint64_t>(image.height()) * max_image_size / max_dimension);
67 }
68
69 // Filters the array of bitmaps, removing all images that do not fit in a box of
70 // size |max_image_size|. Returns the result if it is not empty. Otherwise,
71 // find the smallest image in the array and resize it proportionally to fit
72 // in a box of size |max_image_size|.
73 // Sets |original_image_sizes| to the sizes of |images| before resizing.
74 void FilterAndResizeImagesForMaximalSize(
75 const std::vector<SkBitmap>& unfiltered,
76 uint32_t max_image_size,
77 std::vector<SkBitmap>* images,
78 std::vector<gfx::Size>* original_image_sizes) {
79 images->clear();
80 original_image_sizes->clear();
81
82 if (unfiltered.empty())
83 return;
84
85 if (max_image_size == 0)
86 max_image_size = std::numeric_limits<uint32_t>::max();
87
88 const SkBitmap* min_image = NULL;
89 uint32_t min_image_size = std::numeric_limits<uint32_t>::max();
90 // Filter the images by |max_image_size|, and also identify the smallest image
91 // in case all the images are bigger than |max_image_size|.
92 for (std::vector<SkBitmap>::const_iterator it = unfiltered.begin();
93 it != unfiltered.end(); ++it) {
94 const SkBitmap& image = *it;
95 uint32_t current_size = std::max(it->width(), it->height());
96 if (current_size < min_image_size) {
97 min_image = &image;
98 min_image_size = current_size;
99 }
100 if (static_cast<uint32_t>(image.width()) <= max_image_size &&
101 static_cast<uint32_t>(image.height()) <= max_image_size) {
102 images->push_back(image);
103 original_image_sizes->push_back(gfx::Size(image.width(), image.height()));
104 }
105 }
106 DCHECK(min_image);
107 if (images->size())
108 return;
109 // Proportionally resize the minimal image to fit in a box of size
110 // |max_image_size|.
111 SkBitmap resized = ResizeImage(*min_image, max_image_size);
112 // Drop null or empty SkBitmap.
113 if (resized.drawsNothing())
114 return;
115 images->push_back(resized);
116 original_image_sizes->push_back(
117 gfx::Size(min_image->width(), min_image->height()));
118 }
119
120 } // namespace 45 } // namespace
121 46
122 namespace content { 47 namespace content {
123 48
124 ImageDownloaderImpl::ImageDownloaderImpl( 49 ImageDownloaderCore::ImageDownloaderCore(RenderFrame* render_frame)
125 RenderFrame* render_frame, 50 : render_frame_(render_frame) {
miu 2016/12/03 01:05:30 It makes sense to use the RenderFrameObserver in t
xjz 2016/12/06 19:50:55 Done. I do "delete this" when OnDestruct() is call
xjz 2016/12/06 23:58:17 Now removed "delete this" from OnDestruct(), and c
126 mojom::ImageDownloaderRequest request)
127 : RenderFrameObserver(render_frame),
128 binding_(this, std::move(request)) {
129 DCHECK(render_frame);
130 RenderThread::Get()->AddObserver(this); 51 RenderThread::Get()->AddObserver(this);
131 binding_.set_connection_error_handler(
132 base::Bind(&ImageDownloaderImpl::OnDestruct, base::Unretained(this)));
133 } 52 }
134 53
135 ImageDownloaderImpl::~ImageDownloaderImpl() { 54 ImageDownloaderCore::~ImageDownloaderCore() {
136 RenderThread* thread = RenderThread::Get(); 55 RenderThread* thread = RenderThread::Get();
137 // As ImageDownloaderImpl is a strong binding with message pipe, the 56 // The destructor may run after message loop shutdown, so we need to check
138 // destructor may run after message loop shutdown, so we need to check whether 57 // whether RenderThread is null.
139 // RenderThread is null.
140 if (thread) 58 if (thread)
141 thread->RemoveObserver(this); 59 thread->RemoveObserver(this);
142 } 60 }
143 61
144 // static
145 void ImageDownloaderImpl::CreateMojoService(
146 RenderFrame* render_frame,
147 mojom::ImageDownloaderRequest request) {
148 DVLOG(1) << "ImageDownloaderImpl::CreateMojoService";
149 DCHECK(render_frame);
150
151 // Owns itself.
152 new ImageDownloaderImpl(render_frame, std::move(request));
153 }
154
155 // Ensure all loaders cleared before calling blink::shutdown. 62 // Ensure all loaders cleared before calling blink::shutdown.
156 void ImageDownloaderImpl::OnRenderProcessShutdown() { 63 void ImageDownloaderCore::OnRenderProcessShutdown() {
157 image_fetchers_.clear(); 64 image_fetchers_.clear();
158 } 65 }
159 66
160 // ImageDownloader methods: 67 void ImageDownloaderCore::DownloadImage(const GURL& image_url,
161 void ImageDownloaderImpl::DownloadImage(const GURL& image_url,
162 bool is_favicon, 68 bool is_favicon,
163 uint32_t max_bitmap_size,
164 bool bypass_cache, 69 bool bypass_cache,
165 const DownloadImageCallback& callback) { 70 const DownloadCallback& callback) {
166 std::vector<SkBitmap> result_images; 71 std::vector<SkBitmap> result_images;
167 std::vector<gfx::Size> result_original_image_sizes;
168 72
169 if (image_url.SchemeIs(url::kDataScheme)) { 73 if (image_url.SchemeIs(url::kDataScheme)) {
170 SkBitmap data_image = ImageFromDataUrl(image_url); 74 SkBitmap data_image = ImageFromDataUrl(image_url);
171 SkBitmap resized = ResizeImage(data_image, max_bitmap_size);
172 // Drop null or empty SkBitmap. 75 // Drop null or empty SkBitmap.
173 if (!resized.drawsNothing()) { 76 if (!data_image.drawsNothing())
174 result_images.push_back(resized); 77 result_images.push_back(data_image);
175 result_original_image_sizes.push_back(
176 gfx::Size(data_image.width(), data_image.height()));
177 }
178 } else { 78 } else {
179 if (FetchImage(image_url, is_favicon, max_bitmap_size, bypass_cache, 79 if (FetchImage(image_url, is_favicon, bypass_cache, callback)) {
180 callback)) { 80 // Will complete asynchronously via ImageDownloaderCore::DidFetchImage
181 // Will complete asynchronously via ImageDownloaderImpl::DidFetchImage
182 return; 81 return;
183 } 82 }
184 } 83 }
185 84
186 ReplyDownloadResult(0, result_images, result_original_image_sizes, callback); 85 callback.Run(0, result_images);
187 } 86 }
188 87
189 bool ImageDownloaderImpl::FetchImage(const GURL& image_url, 88 bool ImageDownloaderCore::FetchImage(const GURL& image_url,
190 bool is_favicon, 89 bool is_favicon,
191 uint32_t max_image_size,
192 bool bypass_cache, 90 bool bypass_cache,
193 const DownloadImageCallback& callback) { 91 const DownloadCallback& callback) {
194 blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); 92 blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
195 DCHECK(frame); 93 DCHECK(frame);
196 94
197 // Create an image resource fetcher and assign it with a call back object. 95 // Create an image resource fetcher and assign it with a call back object.
198 image_fetchers_.push_back(new MultiResolutionImageResourceFetcher( 96 image_fetchers_.push_back(new MultiResolutionImageResourceFetcher(
199 image_url, frame, 0, is_favicon ? WebURLRequest::RequestContextFavicon 97 image_url, frame, 0, is_favicon ? WebURLRequest::RequestContextFavicon
200 : WebURLRequest::RequestContextImage, 98 : WebURLRequest::RequestContextImage,
201 bypass_cache ? WebCachePolicy::BypassingCache 99 bypass_cache ? WebCachePolicy::BypassingCache
202 : WebCachePolicy::UseProtocolCachePolicy, 100 : WebCachePolicy::UseProtocolCachePolicy,
203 base::Bind(&ImageDownloaderImpl::DidFetchImage, base::Unretained(this), 101 base::Bind(&ImageDownloaderCore::DidFetchImage, base::Unretained(this),
204 max_image_size, callback))); 102 callback)));
205 return true; 103 return true;
206 } 104 }
207 105
208 void ImageDownloaderImpl::DidFetchImage( 106 void ImageDownloaderCore::DidFetchImage(
209 uint32_t max_image_size, 107 const DownloadCallback& callback,
210 const DownloadImageCallback& callback,
211 MultiResolutionImageResourceFetcher* fetcher, 108 MultiResolutionImageResourceFetcher* fetcher,
212 const std::vector<SkBitmap>& images) { 109 const std::vector<SkBitmap>& images) {
213 std::vector<SkBitmap> result_images; 110 int32_t http_status_code = fetcher->http_status_code();
214 std::vector<gfx::Size> result_original_image_sizes;
215 FilterAndResizeImagesForMaximalSize(images, max_image_size, &result_images,
216 &result_original_image_sizes);
217
218 ReplyDownloadResult(fetcher->http_status_code(), result_images,
219 result_original_image_sizes, callback);
220 111
221 // Remove the image fetcher from our pending list. We're in the callback from 112 // Remove the image fetcher from our pending list. We're in the callback from
222 // MultiResolutionImageResourceFetcher, best to delay deletion. 113 // MultiResolutionImageResourceFetcher, best to delay deletion.
223 ImageResourceFetcherList::iterator iter = 114 ImageResourceFetcherList::iterator iter =
224 std::find(image_fetchers_.begin(), image_fetchers_.end(), fetcher); 115 std::find(image_fetchers_.begin(), image_fetchers_.end(), fetcher);
225 if (iter != image_fetchers_.end()) { 116 if (iter != image_fetchers_.end()) {
226 image_fetchers_.weak_erase(iter); 117 image_fetchers_.weak_erase(iter);
227 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, fetcher); 118 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, fetcher);
228 } 119 }
229 }
230 120
231 void ImageDownloaderImpl::ReplyDownloadResult( 121 // |this| may be destructed after callback is run.
232 int32_t http_status_code, 122 callback.Run(http_status_code, images);
233 const std::vector<SkBitmap>& result_images,
234 const std::vector<gfx::Size>& result_original_image_sizes,
235 const DownloadImageCallback& callback) {
236 callback.Run(http_status_code, result_images, result_original_image_sizes);
237 }
238
239 void ImageDownloaderImpl::OnDestruct() {
240 delete this;
241 } 123 }
242 124
243 } // namespace content 125 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698