Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/message_loop/message_loop.h" | |
| 10 #include "base/task_runner.h" | |
| 11 #include "base/threading/sequenced_worker_pool.h" | |
| 7 #include "components/favicon/core/favicon_service.h" | 12 #include "components/favicon/core/favicon_service.h" |
| 8 #include "components/favicon_base/fallback_icon_style.h" | 13 #include "components/favicon_base/fallback_icon_style.h" |
| 9 #include "components/favicon_base/favicon_types.h" | 14 #include "content/public/browser/browser_thread.h" |
| 10 #include "skia/ext/image_operations.h" | 15 #include "skia/ext/image_operations.h" |
| 11 #include "ui/gfx/codec/png_codec.h" | 16 #include "ui/gfx/codec/png_codec.h" |
| 12 #include "ui/gfx/geometry/size.h" | 17 #include "ui/gfx/geometry/size.h" |
| 13 | 18 |
| 19 namespace { | |
| 20 | |
| 21 } // namespace | |
| 22 | |
| 14 namespace favicon { | 23 namespace favicon { |
| 15 | 24 |
| 16 LargeIconService::LargeIconService(FaviconService* favicon_service) | 25 LargeIconService::Session::Session( |
| 17 : favicon_service_(favicon_service) { | 26 int min_source_size_in_pixel, |
| 18 large_icon_types_.push_back(favicon_base::IconType::FAVICON); | 27 int desired_size_in_pixel, |
| 19 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); | 28 favicon_base::LargeIconCallback callback, |
| 20 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); | 29 scoped_refptr<base::TaskRunner> background_task_runner, |
| 30 base::CancelableTaskTracker* tracker) | |
| 31 : min_source_size_in_pixel_(min_source_size_in_pixel), | |
| 32 desired_size_in_pixel_(desired_size_in_pixel), | |
| 33 callback_(callback), | |
| 34 background_task_runner_(background_task_runner), | |
| 35 caller_task_runner_(base::MessageLoop::current()->task_runner()), | |
| 36 tracker_(tracker) { | |
| 21 } | 37 } |
| 22 | 38 |
| 23 LargeIconService::~LargeIconService() { | 39 LargeIconService::Session::~Session() { |
| 24 } | 40 } |
| 25 | 41 |
| 26 base::CancelableTaskTracker::TaskId | 42 void LargeIconService::Session::OnIconLookupComplete( |
| 27 LargeIconService::GetLargeIconOrFallbackStyle( | 43 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| 28 const GURL& page_url, | 44 bitmap_result_ = bitmap_result; |
| 29 int min_source_size_in_pixel, | 45 tracker_->PostTask( |
| 30 int desired_size_in_pixel, | 46 background_task_runner_.get(), FROM_HERE, |
| 31 const favicon_base::LargeIconCallback& callback, | 47 base::Bind(&LargeIconService::Session::ProcessIconOnBackgroundThread, |
| 32 base::CancelableTaskTracker* tracker) { | 48 this)); |
|
pkotwicz
2015/05/11 14:35:08
Shouldn't you use CancelableTaskTracker::PostTaskA
huangs
2015/05/11 15:20:39
Nice! Done.
| |
| 33 DCHECK_LE(1, min_source_size_in_pixel); | |
| 34 DCHECK_LE(0, desired_size_in_pixel); | |
| 35 | |
| 36 // TODO(beaudoin): For now this is just a wrapper around | |
| 37 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
| 38 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
| 39 // a large icon is known but its bitmap is not available. | |
| 40 return favicon_service_->GetLargestRawFaviconForPageURL( | |
| 41 page_url, | |
| 42 large_icon_types_, | |
| 43 std::max(min_source_size_in_pixel, desired_size_in_pixel), | |
| 44 base::Bind(&LargeIconService::RunLargeIconCallback, | |
| 45 base::Unretained(this), callback, min_source_size_in_pixel, | |
| 46 desired_size_in_pixel), | |
| 47 tracker); | |
| 48 } | 49 } |
| 49 | 50 |
| 50 bool LargeIconService::ResizeLargeIconIfValid( | 51 void LargeIconService::Session::ProcessIconOnBackgroundThread() { |
| 52 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | |
| 53 if (ResizeLargeIconOnBackgroundThreadIfValid(min_source_size_in_pixel_, | |
| 54 desired_size_in_pixel_, bitmap_result_, &resized_bitmap_result)) { | |
| 55 result_.reset( | |
| 56 new favicon_base::LargeIconResult(resized_bitmap_result)); | |
| 57 } else { | |
| 58 // Failed to resize |bitmap_result|, so compute fallback icon style. | |
| 59 scoped_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( | |
| 60 new favicon_base::FallbackIconStyle()); | |
| 61 if (bitmap_result_.is_valid()) { | |
| 62 favicon_base::SetDominantColorAsBackground( | |
| 63 bitmap_result_.bitmap_data, fallback_icon_style.get()); | |
| 64 } | |
| 65 result_.reset( | |
| 66 new favicon_base::LargeIconResult(fallback_icon_style.release())); | |
| 67 } | |
| 68 | |
| 69 // Should not use |tracker_|, which should only be used in the caller thread. | |
| 70 caller_task_runner_->PostTask( | |
| 71 FROM_HERE, | |
| 72 base::Bind(&LargeIconService::Session::OnIconProcessingComplete, this)); | |
| 73 } | |
| 74 | |
| 75 // static | |
| 76 bool LargeIconService::Session::ResizeLargeIconOnBackgroundThreadIfValid( | |
| 51 int min_source_size_in_pixel, | 77 int min_source_size_in_pixel, |
| 52 int desired_size_in_pixel, | 78 int desired_size_in_pixel, |
| 53 const favicon_base::FaviconRawBitmapResult& bitmap_result, | 79 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
| 54 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { | 80 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { |
| 55 // Require bitmap to be valid and square. | 81 // Require bitmap to be valid and square. |
| 56 if (!bitmap_result.is_valid() || | 82 if (!bitmap_result.is_valid() || |
| 57 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) | 83 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) |
| 58 return false; | 84 return false; |
| 59 | 85 |
| 60 // Require bitmap to be large enough. It's square, so just check width. | 86 // Require bitmap to be large enough. It's square, so just check width. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 82 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) | 108 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) |
| 83 return false; | 109 return false; |
| 84 | 110 |
| 85 resized_bitmap_result->pixel_size = | 111 resized_bitmap_result->pixel_size = |
| 86 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); | 112 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); |
| 87 resized_bitmap_result->bitmap_data = | 113 resized_bitmap_result->bitmap_data = |
| 88 base::RefCountedBytes::TakeVector(&bitmap_data); | 114 base::RefCountedBytes::TakeVector(&bitmap_data); |
| 89 return true; | 115 return true; |
| 90 } | 116 } |
| 91 | 117 |
| 92 void LargeIconService::RunLargeIconCallback( | 118 void LargeIconService::Session::OnIconProcessingComplete() { |
| 93 const favicon_base::LargeIconCallback& callback, | 119 callback_.Run(*result_); |
| 94 int min_source_size_in_pixel, | 120 } |
| 95 int desired_size_in_pixel, | |
| 96 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | |
| 97 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | |
| 98 if (ResizeLargeIconIfValid(min_source_size_in_pixel, desired_size_in_pixel, | |
| 99 bitmap_result, &resized_bitmap_result)) { | |
| 100 callback.Run(favicon_base::LargeIconResult(resized_bitmap_result)); | |
| 101 return; | |
| 102 } | |
| 103 | 121 |
| 104 // Failed to resize |bitmap_result|, so compute fallback icon style. | 122 LargeIconService::LargeIconService(FaviconService* favicon_service) |
| 105 favicon_base::LargeIconResult result(new favicon_base::FallbackIconStyle()); | 123 : favicon_service_(favicon_service) { |
| 106 if (bitmap_result.is_valid()) { | 124 large_icon_types_.push_back(favicon_base::IconType::FAVICON); |
| 107 favicon_base::SetDominantColorAsBackground( | 125 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); |
| 108 bitmap_result.bitmap_data, result.fallback_icon_style.get()); | 126 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); |
| 109 } | 127 } |
| 110 callback.Run(result); | 128 |
| 129 LargeIconService::~LargeIconService() { | |
| 130 } | |
| 131 | |
| 132 base::CancelableTaskTracker::TaskId | |
| 133 LargeIconService::GetLargeIconOrFallbackStyle( | |
| 134 const GURL& page_url, | |
| 135 int min_source_size_in_pixel, | |
| 136 int desired_size_in_pixel, | |
| 137 const favicon_base::LargeIconCallback& callback, | |
| 138 base::CancelableTaskTracker* tracker) { | |
| 139 DCHECK_LE(1, min_source_size_in_pixel); | |
| 140 DCHECK_LE(0, desired_size_in_pixel); | |
| 141 | |
| 142 scoped_refptr<LargeIconService::Session> session = | |
| 143 new LargeIconService::Session(min_source_size_in_pixel, | |
| 144 desired_size_in_pixel, callback, GetBackgroundTaskRunner(), tracker); | |
| 145 | |
| 146 // TODO(beaudoin): For now this is just a wrapper around | |
| 147 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
| 148 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
| 149 // a large icon is known but its bitmap is not available. | |
| 150 return favicon_service_->GetLargestRawFaviconForPageURL( | |
| 151 page_url, large_icon_types_, desired_size_in_pixel, | |
| 152 base::Bind(&LargeIconService::Session::OnIconLookupComplete, session), | |
| 153 tracker); | |
| 154 } | |
| 155 | |
| 156 // Returns TaskRunner used to execute background task. | |
| 157 scoped_refptr<base::TaskRunner> LargeIconService::GetBackgroundTaskRunner() { | |
| 158 return content::BrowserThread::GetBlockingPool() | |
| 159 ->GetTaskRunnerWithShutdownBehavior( | |
| 160 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 111 } | 161 } |
| 112 | 162 |
| 113 } // namespace favicon | 163 } // namespace favicon |
| OLD | NEW |