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

Side by Side Diff: components/favicon/core/large_icon_service.cc

Issue 1122103003: [Large Icon Service] Move icon resizing into worker thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment and DCHECK() fixes. Created 5 years, 7 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 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/favicon/core/large_icon_service.h" 5 #include "components/favicon/core/large_icon_service.h"
6 6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/task_runner.h"
10 #include "base/threading/sequenced_worker_pool.h"
7 #include "components/favicon/core/favicon_service.h" 11 #include "components/favicon/core/favicon_service.h"
8 #include "components/favicon_base/fallback_icon_style.h" 12 #include "components/favicon_base/fallback_icon_style.h"
9 #include "components/favicon_base/favicon_types.h" 13 #include "content/public/browser/browser_thread.h"
10 #include "skia/ext/image_operations.h" 14 #include "skia/ext/image_operations.h"
11 #include "ui/gfx/codec/png_codec.h" 15 #include "ui/gfx/codec/png_codec.h"
12 #include "ui/gfx/geometry/size.h" 16 #include "ui/gfx/geometry/size.h"
13 17
18 namespace {
19
20 // Return a TaskRunner used to execute background task.
21 scoped_refptr<base::TaskRunner> GetBackgroundTaskRunner() {
22 return content::BrowserThread::GetBlockingPool()
23 ->GetTaskRunnerWithShutdownBehavior(
24 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
25 }
26
27 } // namespace
28
14 namespace favicon { 29 namespace favicon {
15 30
16 LargeIconService::LargeIconService(FaviconService* favicon_service) 31 LargeIconService::LargeIconService(FaviconService* favicon_service)
17 : favicon_service_(favicon_service) { 32 : favicon_service_(favicon_service) {
18 large_icon_types_.push_back(favicon_base::IconType::FAVICON); 33 large_icon_types_.push_back(favicon_base::IconType::FAVICON);
19 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); 34 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON);
20 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); 35 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON);
21 } 36 }
22 37
23 LargeIconService::~LargeIconService() { 38 LargeIconService::~LargeIconService() {
24 } 39 }
25 40
41 // Main entry point. Must run on the UI thread.
beaudoin 2015/05/06 14:06:53 Move comment to .h?
huangs 2015/05/06 22:45:14 Done.
26 base::CancelableTaskTracker::TaskId 42 base::CancelableTaskTracker::TaskId
27 LargeIconService::GetLargeIconOrFallbackStyle( 43 LargeIconService::GetLargeIconOrFallbackStyle(
28 const GURL& page_url, 44 const GURL& page_url,
29 int desired_size_in_pixel, 45 int desired_size_in_pixel,
30 const favicon_base::LargeIconCallback& callback, 46 const favicon_base::LargeIconCallback& callback,
31 base::CancelableTaskTracker* tracker) { 47 base::CancelableTaskTracker* tracker) {
48 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
49 scoped_refptr<LargeIconService::Session> session =
50 new LargeIconService::Session();
51 session->desired_size_in_pixel = desired_size_in_pixel;
52 session->callback = callback;
53 session->tracker = tracker;
54
32 // TODO(beaudoin): For now this is just a wrapper around 55 // TODO(beaudoin): For now this is just a wrapper around
33 // GetLargestRawFaviconForPageURL. Add the logic required to select the best 56 // GetLargestRawFaviconForPageURL. Add the logic required to select the best
34 // possible large icon. Also add logic to fetch-on-demand when the URL of 57 // possible large icon. Also add logic to fetch-on-demand when the URL of
35 // a large icon is known but its bitmap is not available. 58 // a large icon is known but its bitmap is not available.
36 return favicon_service_->GetLargestRawFaviconForPageURL( 59 return favicon_service_->GetLargestRawFaviconForPageURL(
37 page_url, 60 page_url, large_icon_types_, desired_size_in_pixel,
38 large_icon_types_, 61 base::Bind(&LargeIconService::OnIconLookupComplete,
39 desired_size_in_pixel, 62 base::Unretained(this), session),
40 base::Bind(&LargeIconService::RunLargeIconCallback,
41 base::Unretained(this), callback, desired_size_in_pixel),
42 tracker); 63 tracker);
43 } 64 }
44 65
66 // static
45 bool LargeIconService::ResizeLargeIconIfValid( 67 bool LargeIconService::ResizeLargeIconIfValid(
46 int desired_size_in_pixel, 68 int desired_size_in_pixel,
47 const favicon_base::FaviconRawBitmapResult& bitmap_result, 69 const favicon_base::FaviconRawBitmapResult& bitmap_result,
48 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { 70 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) {
49 // Require bitmap to be valid and square. 71 // Require bitmap to be valid and square.
50 if (!bitmap_result.is_valid() || 72 if (!bitmap_result.is_valid() ||
51 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) 73 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height())
52 return false; 74 return false;
53 75
54 // Require bitmap to be large enough. It's square, so just check width. 76 // Require bitmap to be large enough. It's square, so just check width.
55 if (bitmap_result.pixel_size.width() < desired_size_in_pixel) { 77 if (bitmap_result.pixel_size.width() < desired_size_in_pixel) {
56 // TODO(beaudoin): Potentially relax this, and allow icon to be scaled up. 78 // TODO(beaudoin): Potentially relax this, and allow icon to be scaled up.
57 return false; 79 return false;
58 } 80 }
59 81
60 *resized_bitmap_result = bitmap_result; 82 *resized_bitmap_result = bitmap_result;
61
62 // Special case: Can use |resized_bitmap_result| as is. 83 // Special case: Can use |resized_bitmap_result| as is.
63 if (bitmap_result.pixel_size.width() == desired_size_in_pixel) 84 if (bitmap_result.pixel_size.width() == desired_size_in_pixel)
64 return true; 85 return true;
65 86
66 // Resize bitmap: decode PNG, resize, and re-encode PNG. 87 // Resize bitmap: decode PNG, resize, and re-encode PNG.
67 SkBitmap decoded_bitmap; 88 SkBitmap decoded_bitmap;
68 if (!gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), 89 if (!gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(),
69 bitmap_result.bitmap_data->size(), &decoded_bitmap)) 90 bitmap_result.bitmap_data->size(), &decoded_bitmap))
70 return false; 91 return false;
71 92
72 SkBitmap resized_bitmap = skia::ImageOperations::Resize( 93 SkBitmap resized_bitmap = skia::ImageOperations::Resize(
73 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, 94 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
74 desired_size_in_pixel, desired_size_in_pixel); 95 desired_size_in_pixel, desired_size_in_pixel);
75 96
76 std::vector<unsigned char> bitmap_data; 97 std::vector<unsigned char> bitmap_data;
77 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) 98 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data))
78 return false; 99 return false;
79 100
80 resized_bitmap_result->pixel_size = 101 resized_bitmap_result->pixel_size =
81 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); 102 gfx::Size(desired_size_in_pixel, desired_size_in_pixel);
82 resized_bitmap_result->bitmap_data = 103 resized_bitmap_result->bitmap_data =
83 base::RefCountedBytes::TakeVector(&bitmap_data); 104 base::RefCountedBytes::TakeVector(&bitmap_data);
84 return true; 105 return true;
85 } 106 }
86 107
87 void LargeIconService::RunLargeIconCallback( 108 // Must run on the UI thread.
beaudoin 2015/05/06 14:06:53 I get the impression these comments are typically
huangs 2015/05/06 22:45:14 Done.
88 const favicon_base::LargeIconCallback& callback, 109 void LargeIconService::OnIconLookupComplete(
89 int desired_size_in_pixel, 110 scoped_refptr<LargeIconService::Session> session,
90 const favicon_base::FaviconRawBitmapResult& bitmap_result) { 111 const favicon_base::FaviconRawBitmapResult& bitmap_result) {
112 session->bitmap_result = bitmap_result;
113 session->tracker->PostTask(
114 GetBackgroundTaskRunner().get(), FROM_HERE,
115 base::Bind(&LargeIconService::ProcessIconOnBackgroundThread,
116 base::Unretained(this), session));
117 }
118
119 // Must run on a background thread.
120 void LargeIconService::ProcessIconOnBackgroundThread(
jochen (gone - plz use gerrit) 2015/05/06 12:58:48 how can you ensure that "this" is still a valid po
huangs 2015/05/06 13:28:07 So making OnIconLookupComplete() ProcessIconOn
huangs 2015/05/06 22:45:14 Going with static to keep things simple.
121 scoped_refptr<LargeIconService::Session> session) {
122 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
91 favicon_base::FaviconRawBitmapResult resized_bitmap_result; 123 favicon_base::FaviconRawBitmapResult resized_bitmap_result;
92 if (ResizeLargeIconIfValid(desired_size_in_pixel, bitmap_result, 124 if (ResizeLargeIconIfValid(session->desired_size_in_pixel,
93 &resized_bitmap_result)) { 125 session->bitmap_result, &resized_bitmap_result)) {
94 callback.Run(favicon_base::LargeIconResult(resized_bitmap_result)); 126 session->result.reset(
95 return; 127 new favicon_base::LargeIconResult(resized_bitmap_result));
128 } else {
129 // Failed to resize |bitmap_result|, so compute fallback icon style.
130 scoped_ptr<favicon_base::FallbackIconStyle> fallback_icon_style(
131 new favicon_base::FallbackIconStyle());
132 if (session->bitmap_result.is_valid()) {
133 favicon_base::SetDominantColorAsBackground(
134 session->bitmap_result.bitmap_data, fallback_icon_style.get());
135 }
136 session->result.reset(
137 new favicon_base::LargeIconResult(fallback_icon_style.release()));
96 } 138 }
97 139
98 // Failed to resize |bitmap_result|, so compute fallback icon style. 140 content::BrowserThread::PostTask(
99 favicon_base::LargeIconResult result(new favicon_base::FallbackIconStyle()); 141 content::BrowserThread::UI, FROM_HERE,
100 if (bitmap_result.is_valid()) { 142 base::Bind(&LargeIconService::OnIconProcessingComplete,
101 favicon_base::SetDominantColorAsBackground( 143 base::Unretained(this), session));
102 bitmap_result.bitmap_data, result.fallback_icon_style.get()); 144 }
103 } 145
104 callback.Run(result); 146 // Must run on the UI thread.
147 void LargeIconService::OnIconProcessingComplete(
148 scoped_refptr<LargeIconService::Session> session) {
149 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
jochen (gone - plz use gerrit) 2015/05/06 12:58:48 same here
huangs 2015/05/06 22:45:14 Done.
150 session->callback.Run(*session->result);
105 } 151 }
106 152
107 } // namespace favicon 153 } // namespace favicon
OLDNEW
« components/favicon/core/large_icon_service.h ('K') | « components/favicon/core/large_icon_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698