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 "chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h" | 5 #include "chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
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/metrics/user_metrics.h" | 11 #include "base/metrics/user_metrics.h" |
12 #include "base/task_scheduler/post_task.h" | 12 #include "base/task_scheduler/post_task.h" |
| 13 #include "chrome/browser/android/shortcut_helper.h" |
13 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" | 14 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" |
14 #include "chrome/browser/favicon/favicon_service_factory.h" | 15 #include "chrome/browser/favicon/favicon_service_factory.h" |
15 #include "chrome/browser/installable/installable_manager.h" | 16 #include "chrome/browser/installable/installable_manager.h" |
16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/common/chrome_constants.h" | 18 #include "chrome/common/chrome_constants.h" |
18 #include "chrome/common/render_messages.h" | 19 #include "chrome/common/render_messages.h" |
19 #include "chrome/common/web_application_info.h" | 20 #include "chrome/common/web_application_info.h" |
20 #include "components/dom_distiller/core/url_utils.h" | 21 #include "components/dom_distiller/core/url_utils.h" |
21 #include "components/favicon/core/favicon_service.h" | 22 #include "components/favicon/core/favicon_service.h" |
22 #include "components/favicon_base/favicon_types.h" | 23 #include "components/favicon_base/favicon_types.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 return params; | 58 return params; |
58 } | 59 } |
59 | 60 |
60 InstallableParams ParamsToPerformInstallableCheck( | 61 InstallableParams ParamsToPerformInstallableCheck( |
61 bool check_webapk_compatibility) { | 62 bool check_webapk_compatibility) { |
62 InstallableParams params; | 63 InstallableParams params; |
63 params.check_installable = check_webapk_compatibility; | 64 params.check_installable = check_webapk_compatibility; |
64 return params; | 65 return params; |
65 } | 66 } |
66 | 67 |
| 68 // Creates a launcher icon from |icon|. |start_url| is used to generate the icon |
| 69 // if |icon| is empty or is not large enough. Returns a std::pair with: |
| 70 // - the generated icon |
| 71 // - whether |icon| was used in generating the launcher icon |
| 72 std::pair<SkBitmap, bool> CreateLauncherIconInBackground(const GURL& start_url, |
| 73 const SkBitmap& icon) { |
| 74 base::ThreadRestrictions::AssertIOAllowed(); |
| 75 |
| 76 bool is_generated = false; |
| 77 SkBitmap primary_icon = ShortcutHelper::FinalizeLauncherIconInBackground( |
| 78 icon, start_url, &is_generated); |
| 79 return std::make_pair(primary_icon, is_generated); |
| 80 } |
| 81 |
| 82 // Creates a launcher icon from |bitmap_result|. |start_url| is used to |
| 83 // generate the icon if there is no bitmap in |bitmap_result| or the bitmap is |
| 84 // not large enough. Returns a std::pair with: |
| 85 // - the generated icon |
| 86 // - whether the bitmap in |bitmap_result| was used in generating the launcher |
| 87 // icon |
| 88 std::pair<SkBitmap, bool> CreateLauncherIconFromFaviconInBackground( |
| 89 const GURL& start_url, |
| 90 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| 91 base::ThreadRestrictions::AssertIOAllowed(); |
| 92 |
| 93 SkBitmap decoded; |
| 94 if (bitmap_result.is_valid()) { |
| 95 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), |
| 96 bitmap_result.bitmap_data->size(), &decoded); |
| 97 } |
| 98 return CreateLauncherIconInBackground(start_url, decoded); |
| 99 } |
| 100 |
67 } // namespace | 101 } // namespace |
68 | 102 |
69 AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( | 103 AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( |
70 content::WebContents* web_contents, | 104 content::WebContents* web_contents, |
71 int ideal_icon_size_in_px, | 105 int ideal_icon_size_in_px, |
72 int minimum_icon_size_in_px, | 106 int minimum_icon_size_in_px, |
73 int ideal_splash_image_size_in_px, | 107 int ideal_splash_image_size_in_px, |
74 int minimum_splash_image_size_in_px, | 108 int minimum_splash_image_size_in_px, |
75 int badge_size_in_px, | 109 int badge_size_in_px, |
76 int data_timeout_ms, | 110 int data_timeout_ms, |
77 bool check_webapk_compatibility, | 111 bool check_webapk_compatibility, |
78 Observer* observer) | 112 Observer* observer) |
79 : content::WebContentsObserver(web_contents), | 113 : content::WebContentsObserver(web_contents), |
80 installable_manager_(InstallableManager::FromWebContents(web_contents)), | 114 installable_manager_(InstallableManager::FromWebContents(web_contents)), |
81 weak_observer_(observer), | 115 observer_(observer), |
82 shortcut_info_(GetShortcutUrl(web_contents->GetBrowserContext(), | 116 shortcut_info_(GetShortcutUrl(web_contents->GetBrowserContext(), |
83 web_contents->GetLastCommittedURL())), | 117 web_contents->GetLastCommittedURL())), |
84 ideal_icon_size_in_px_(ideal_icon_size_in_px), | 118 ideal_icon_size_in_px_(ideal_icon_size_in_px), |
85 minimum_icon_size_in_px_(minimum_icon_size_in_px), | 119 minimum_icon_size_in_px_(minimum_icon_size_in_px), |
86 ideal_splash_image_size_in_px_(ideal_splash_image_size_in_px), | 120 ideal_splash_image_size_in_px_(ideal_splash_image_size_in_px), |
87 minimum_splash_image_size_in_px_(minimum_splash_image_size_in_px), | 121 minimum_splash_image_size_in_px_(minimum_splash_image_size_in_px), |
88 badge_size_in_px_(badge_size_in_px), | 122 badge_size_in_px_(badge_size_in_px), |
89 data_timeout_ms_(data_timeout_ms), | 123 data_timeout_ms_(data_timeout_ms), |
90 check_webapk_compatibility_(check_webapk_compatibility), | 124 check_webapk_compatibility_(check_webapk_compatibility), |
91 is_waiting_for_web_application_info_(true), | 125 is_waiting_for_web_application_info_(true), |
92 is_installable_check_complete_(false) { | 126 weak_ptr_factory_(this) { |
93 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px); | 127 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px); |
94 DCHECK(minimum_splash_image_size_in_px <= ideal_splash_image_size_in_px); | 128 DCHECK(minimum_splash_image_size_in_px <= ideal_splash_image_size_in_px); |
95 | 129 |
96 // Send a message to the renderer to retrieve information about the page. | 130 // Send a message to the renderer to retrieve information about the page. |
97 content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); | 131 content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); |
98 main_frame->Send( | 132 main_frame->Send( |
99 new ChromeFrameMsg_GetWebApplicationInfo(main_frame->GetRoutingID())); | 133 new ChromeFrameMsg_GetWebApplicationInfo(main_frame->GetRoutingID())); |
100 } | 134 } |
101 | 135 |
| 136 AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() {} |
| 137 |
102 void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo( | 138 void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo( |
103 const WebApplicationInfo& received_web_app_info) { | 139 const WebApplicationInfo& received_web_app_info) { |
104 is_waiting_for_web_application_info_ = false; | 140 is_waiting_for_web_application_info_ = false; |
105 if (!web_contents() || !weak_observer_) | 141 if (!web_contents()) |
106 return; | 142 return; |
107 | 143 |
108 // Sanitize received_web_app_info. | 144 // Sanitize received_web_app_info. |
109 WebApplicationInfo web_app_info = received_web_app_info; | 145 WebApplicationInfo web_app_info = received_web_app_info; |
110 web_app_info.title = | 146 web_app_info.title = |
111 web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength); | 147 web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength); |
112 | 148 |
113 // Simply set the user-editable title to be the page's title | 149 // Simply set the user-editable title to be the page's title |
114 shortcut_info_.user_title = web_app_info.title.empty() | 150 shortcut_info_.user_title = web_app_info.title.empty() |
115 ? web_contents()->GetTitle() | 151 ? web_contents()->GetTitle() |
(...skipping 21 matching lines...) Expand all Loading... |
137 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: | 173 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: |
138 base::RecordAction( | 174 base::RecordAction( |
139 base::UserMetricsAction("webapps.AddShortcut.Bookmark")); | 175 base::UserMetricsAction("webapps.AddShortcut.Bookmark")); |
140 break; | 176 break; |
141 } | 177 } |
142 | 178 |
143 // Kick off a timeout for downloading data. If we haven't finished within the | 179 // Kick off a timeout for downloading data. If we haven't finished within the |
144 // timeout, fall back to using a dynamically-generated launcher icon. | 180 // timeout, fall back to using a dynamically-generated launcher icon. |
145 data_timeout_timer_.Start( | 181 data_timeout_timer_.Start( |
146 FROM_HERE, base::TimeDelta::FromMilliseconds(data_timeout_ms_), | 182 FROM_HERE, base::TimeDelta::FromMilliseconds(data_timeout_ms_), |
147 base::Bind(&AddToHomescreenDataFetcher::OnDataTimedout, this)); | 183 base::Bind(&AddToHomescreenDataFetcher::OnDataTimedout, |
| 184 weak_ptr_factory_.GetWeakPtr())); |
148 | 185 |
149 installable_manager_->GetData( | 186 installable_manager_->GetData( |
150 ParamsToPerformManifestAndIconFetch( | 187 ParamsToPerformManifestAndIconFetch( |
151 ideal_icon_size_in_px_, minimum_icon_size_in_px_, badge_size_in_px_, | 188 ideal_icon_size_in_px_, minimum_icon_size_in_px_, badge_size_in_px_, |
152 check_webapk_compatibility_), | 189 check_webapk_compatibility_), |
153 base::Bind(&AddToHomescreenDataFetcher::OnDidGetManifestAndIcons, this)); | 190 base::Bind(&AddToHomescreenDataFetcher::OnDidGetManifestAndIcons, |
154 } | 191 weak_ptr_factory_.GetWeakPtr())); |
155 | |
156 AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() { | |
157 DCHECK(!weak_observer_); | |
158 } | 192 } |
159 | 193 |
160 bool AddToHomescreenDataFetcher::OnMessageReceived( | 194 bool AddToHomescreenDataFetcher::OnMessageReceived( |
161 const IPC::Message& message, | 195 const IPC::Message& message, |
162 content::RenderFrameHost* sender) { | 196 content::RenderFrameHost* sender) { |
163 if (!is_waiting_for_web_application_info_) | 197 if (!is_waiting_for_web_application_info_) |
164 return false; | 198 return false; |
165 | 199 |
166 bool handled = true; | 200 bool handled = true; |
167 | 201 |
168 IPC_BEGIN_MESSAGE_MAP(AddToHomescreenDataFetcher, message) | 202 IPC_BEGIN_MESSAGE_MAP(AddToHomescreenDataFetcher, message) |
169 IPC_MESSAGE_HANDLER(ChromeFrameHostMsg_DidGetWebApplicationInfo, | 203 IPC_MESSAGE_HANDLER(ChromeFrameHostMsg_DidGetWebApplicationInfo, |
170 OnDidGetWebApplicationInfo) | 204 OnDidGetWebApplicationInfo) |
171 IPC_MESSAGE_UNHANDLED(handled = false) | 205 IPC_MESSAGE_UNHANDLED(handled = false) |
172 IPC_END_MESSAGE_MAP() | 206 IPC_END_MESSAGE_MAP() |
173 | 207 |
174 return handled; | 208 return handled; |
175 } | 209 } |
176 | 210 |
177 void AddToHomescreenDataFetcher::OnDataTimedout() { | 211 void AddToHomescreenDataFetcher::OnDataTimedout() { |
178 if (!web_contents() || !weak_observer_) | 212 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 213 |
| 214 if (!web_contents()) |
179 return; | 215 return; |
180 | 216 |
181 if (!is_installable_check_complete_) { | 217 if (check_webapk_compatibility_) |
182 is_installable_check_complete_ = true; | 218 observer_->OnDidDetermineWebApkCompatibility(false); |
183 if (check_webapk_compatibility_) | 219 observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
184 weak_observer_->OnDidDetermineWebApkCompatibility(false); | |
185 weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); | |
186 } | |
187 | 220 |
188 CreateLauncherIcon(raw_primary_icon_); | 221 CreateLauncherIcon(raw_primary_icon_); |
189 } | 222 } |
190 | 223 |
191 void AddToHomescreenDataFetcher::OnDidGetManifestAndIcons( | 224 void AddToHomescreenDataFetcher::OnDidGetManifestAndIcons( |
192 const InstallableData& data) { | 225 const InstallableData& data) { |
193 if (!web_contents() || !weak_observer_ || is_installable_check_complete_) | 226 if (!web_contents()) |
194 return; | 227 return; |
195 | 228 |
196 if (!data.manifest.IsEmpty()) { | 229 if (!data.manifest.IsEmpty()) { |
197 base::RecordAction(base::UserMetricsAction("webapps.AddShortcut.Manifest")); | 230 base::RecordAction(base::UserMetricsAction("webapps.AddShortcut.Manifest")); |
198 shortcut_info_.UpdateFromManifest(data.manifest); | 231 shortcut_info_.UpdateFromManifest(data.manifest); |
199 shortcut_info_.manifest_url = data.manifest_url; | 232 shortcut_info_.manifest_url = data.manifest_url; |
200 } | 233 } |
201 | 234 |
202 // Do this after updating from the manifest for the case where a site has | 235 // Do this after updating from the manifest for the case where a site has |
203 // a manifest with name and standalone specified, but no icons. | 236 // a manifest with name and standalone specified, but no icons. |
204 if (data.manifest.IsEmpty() || !data.primary_icon) { | 237 if (data.manifest.IsEmpty() || !data.primary_icon) { |
205 if (check_webapk_compatibility_) | 238 if (check_webapk_compatibility_) |
206 weak_observer_->OnDidDetermineWebApkCompatibility(false); | 239 observer_->OnDidDetermineWebApkCompatibility(false); |
207 weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); | 240 observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
208 data_timeout_timer_.Stop(); | 241 data_timeout_timer_.Stop(); |
209 FetchFavicon(); | 242 FetchFavicon(); |
210 return; | 243 return; |
211 } | 244 } |
212 | 245 |
213 raw_primary_icon_ = *data.primary_icon; | 246 raw_primary_icon_ = *data.primary_icon; |
214 shortcut_info_.best_primary_icon_url = data.primary_icon_url; | 247 shortcut_info_.best_primary_icon_url = data.primary_icon_url; |
215 | 248 |
216 // Save the splash screen URL for the later download. | 249 // Save the splash screen URL for the later download. |
217 shortcut_info_.splash_image_url = | 250 shortcut_info_.splash_image_url = |
218 content::ManifestIconSelector::FindBestMatchingIcon( | 251 content::ManifestIconSelector::FindBestMatchingIcon( |
219 data.manifest.icons, ideal_splash_image_size_in_px_, | 252 data.manifest.icons, ideal_splash_image_size_in_px_, |
220 minimum_splash_image_size_in_px_, | 253 minimum_splash_image_size_in_px_, |
221 content::Manifest::Icon::IconPurpose::ANY); | 254 content::Manifest::Icon::IconPurpose::ANY); |
222 shortcut_info_.ideal_splash_image_size_in_px = ideal_splash_image_size_in_px_; | 255 shortcut_info_.ideal_splash_image_size_in_px = ideal_splash_image_size_in_px_; |
223 shortcut_info_.minimum_splash_image_size_in_px = | 256 shortcut_info_.minimum_splash_image_size_in_px = |
224 minimum_splash_image_size_in_px_; | 257 minimum_splash_image_size_in_px_; |
225 if (data.badge_icon) { | 258 if (data.badge_icon) { |
226 shortcut_info_.best_badge_icon_url = data.badge_icon_url; | 259 shortcut_info_.best_badge_icon_url = data.badge_icon_url; |
227 badge_icon_ = *data.badge_icon; | 260 badge_icon_ = *data.badge_icon; |
228 } | 261 } |
229 | 262 |
230 installable_manager_->GetData( | 263 installable_manager_->GetData( |
231 ParamsToPerformInstallableCheck(check_webapk_compatibility_), | 264 ParamsToPerformInstallableCheck(check_webapk_compatibility_), |
232 base::Bind(&AddToHomescreenDataFetcher::OnDidPerformInstallableCheck, | 265 base::Bind(&AddToHomescreenDataFetcher::OnDidPerformInstallableCheck, |
233 this)); | 266 weak_ptr_factory_.GetWeakPtr())); |
234 } | 267 } |
235 | 268 |
236 void AddToHomescreenDataFetcher::OnDidPerformInstallableCheck( | 269 void AddToHomescreenDataFetcher::OnDidPerformInstallableCheck( |
237 const InstallableData& data) { | 270 const InstallableData& data) { |
238 data_timeout_timer_.Stop(); | 271 data_timeout_timer_.Stop(); |
239 | 272 |
240 if (!web_contents() || !weak_observer_ || is_installable_check_complete_) | 273 if (!web_contents()) |
241 return; | 274 return; |
242 | 275 |
243 is_installable_check_complete_ = true; | |
244 | |
245 bool webapk_compatible = false; | 276 bool webapk_compatible = false; |
246 if (check_webapk_compatibility_) { | 277 if (check_webapk_compatibility_) { |
247 webapk_compatible = | 278 webapk_compatible = |
248 (data.error_code == NO_ERROR_DETECTED && data.is_installable && | 279 (data.error_code == NO_ERROR_DETECTED && data.is_installable && |
249 AreWebManifestUrlsWebApkCompatible(data.manifest)); | 280 AreWebManifestUrlsWebApkCompatible(data.manifest)); |
250 weak_observer_->OnDidDetermineWebApkCompatibility(webapk_compatible); | 281 observer_->OnDidDetermineWebApkCompatibility(webapk_compatible); |
251 } | 282 } |
252 | 283 |
253 weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); | 284 observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
254 if (webapk_compatible) { | 285 if (webapk_compatible) { |
255 shortcut_info_.UpdateSource(ShortcutInfo::SOURCE_ADD_TO_HOMESCREEN_PWA); | 286 shortcut_info_.UpdateSource(ShortcutInfo::SOURCE_ADD_TO_HOMESCREEN_PWA); |
256 NotifyObserver(raw_primary_icon_); | 287 NotifyObserver(std::make_pair(raw_primary_icon_, false /* is_generated */)); |
257 } else { | 288 } else { |
258 CreateLauncherIcon(raw_primary_icon_); | 289 CreateLauncherIcon(raw_primary_icon_); |
259 } | 290 } |
260 } | 291 } |
261 | 292 |
262 void AddToHomescreenDataFetcher::FetchFavicon() { | 293 void AddToHomescreenDataFetcher::FetchFavicon() { |
263 if (!web_contents() || !weak_observer_) | 294 if (!web_contents()) |
264 return; | 295 return; |
265 | 296 |
266 // Grab the best, largest icon we can find to represent this bookmark. | 297 // Grab the best, largest icon we can find to represent this bookmark. |
267 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its | 298 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its |
268 // rewrite is further along. | 299 // rewrite is further along. |
269 std::vector<int> icon_types{ | 300 std::vector<int> icon_types{ |
270 favicon_base::WEB_MANIFEST_ICON, favicon_base::FAVICON, | 301 favicon_base::WEB_MANIFEST_ICON, favicon_base::FAVICON, |
271 favicon_base::TOUCH_PRECOMPOSED_ICON | favicon_base::TOUCH_ICON}; | 302 favicon_base::TOUCH_PRECOMPOSED_ICON | favicon_base::TOUCH_ICON}; |
272 | 303 |
273 favicon::FaviconService* favicon_service = | 304 favicon::FaviconService* favicon_service = |
274 FaviconServiceFactory::GetForProfile( | 305 FaviconServiceFactory::GetForProfile( |
275 Profile::FromBrowserContext(web_contents()->GetBrowserContext()), | 306 Profile::FromBrowserContext(web_contents()->GetBrowserContext()), |
276 ServiceAccessType::EXPLICIT_ACCESS); | 307 ServiceAccessType::EXPLICIT_ACCESS); |
277 | 308 |
278 // Using favicon if its size is not smaller than platform required size, | 309 // Using favicon if its size is not smaller than platform required size, |
279 // otherwise using the largest icon among all avaliable icons. | 310 // otherwise using the largest icon among all avaliable icons. |
280 int threshold_to_get_any_largest_icon = ideal_icon_size_in_px_ - 1; | 311 int threshold_to_get_any_largest_icon = ideal_icon_size_in_px_ - 1; |
281 favicon_service->GetLargestRawFaviconForPageURL( | 312 favicon_service->GetLargestRawFaviconForPageURL( |
282 shortcut_info_.url, icon_types, threshold_to_get_any_largest_icon, | 313 shortcut_info_.url, icon_types, threshold_to_get_any_largest_icon, |
283 base::Bind(&AddToHomescreenDataFetcher::OnFaviconFetched, this), | 314 base::Bind(&AddToHomescreenDataFetcher::OnFaviconFetched, |
| 315 weak_ptr_factory_.GetWeakPtr()), |
284 &favicon_task_tracker_); | 316 &favicon_task_tracker_); |
285 } | 317 } |
286 | 318 |
287 void AddToHomescreenDataFetcher::OnFaviconFetched( | 319 void AddToHomescreenDataFetcher::OnFaviconFetched( |
288 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | 320 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
289 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 321 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
290 | 322 |
291 if (!web_contents() || !weak_observer_) | 323 if (!web_contents()) |
292 return; | 324 return; |
293 | 325 |
| 326 shortcut_info_.best_primary_icon_url = bitmap_result.icon_url; |
| 327 |
294 // The user is waiting for the icon to be processed before they can proceed | 328 // The user is waiting for the icon to be processed before they can proceed |
295 // with add to homescreen. But if we shut down, there's no point starting the | 329 // with add to homescreen. But if we shut down, there's no point starting the |
296 // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN. | 330 // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN. |
297 base::PostTaskWithTraitsAndReplyWithResult( | 331 base::PostTaskWithTraitsAndReplyWithResult( |
298 FROM_HERE, | 332 FROM_HERE, |
299 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, | 333 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, |
300 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, | 334 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, |
301 base::BindOnce(&AddToHomescreenDataFetcher:: | 335 base::BindOnce(&CreateLauncherIconFromFaviconInBackground, |
302 CreateLauncherIconFromFaviconInBackground, | 336 shortcut_info_.url, bitmap_result), |
303 base::Unretained(this), bitmap_result), | |
304 base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, | 337 base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, |
305 base::RetainedRef(this))); | 338 weak_ptr_factory_.GetWeakPtr())); |
306 } | |
307 | |
308 SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconFromFaviconInBackground( | |
309 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | |
310 base::ThreadRestrictions::AssertIOAllowed(); | |
311 | |
312 if (bitmap_result.is_valid()) { | |
313 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), | |
314 bitmap_result.bitmap_data->size(), | |
315 &raw_primary_icon_); | |
316 } | |
317 | |
318 shortcut_info_.best_primary_icon_url = bitmap_result.icon_url; | |
319 return CreateLauncherIconInBackground(raw_primary_icon_); | |
320 } | 339 } |
321 | 340 |
322 void AddToHomescreenDataFetcher::CreateLauncherIcon(const SkBitmap& icon) { | 341 void AddToHomescreenDataFetcher::CreateLauncherIcon(const SkBitmap& icon) { |
323 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 342 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
324 | 343 |
325 // The user is waiting for the icon to be processed before they can proceed | 344 // The user is waiting for the icon to be processed before they can proceed |
326 // with add to homescreen. But if we shut down, there's no point starting the | 345 // with add to homescreen. But if we shut down, there's no point starting the |
327 // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN. | 346 // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN. |
328 base::PostTaskWithTraitsAndReplyWithResult( | 347 base::PostTaskWithTraitsAndReplyWithResult( |
329 FROM_HERE, | 348 FROM_HERE, |
330 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, | 349 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, |
331 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, | 350 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, |
332 base::BindOnce( | 351 base::BindOnce(&CreateLauncherIconInBackground, shortcut_info_.url, icon), |
333 &AddToHomescreenDataFetcher::CreateLauncherIconInBackground, | |
334 base::Unretained(this), icon), | |
335 base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, | 352 base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, |
336 base::RetainedRef(this))); | 353 weak_ptr_factory_.GetWeakPtr())); |
337 } | 354 } |
338 | 355 |
339 SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconInBackground( | 356 void AddToHomescreenDataFetcher::NotifyObserver( |
340 const SkBitmap& icon) { | 357 const std::pair<SkBitmap, bool /*is_generated*/>& primary_icon) { |
341 base::ThreadRestrictions::AssertIOAllowed(); | |
342 | |
343 SkBitmap primary_icon; | |
344 bool is_generated = false; | |
345 if (weak_observer_) { | |
346 primary_icon = weak_observer_->FinalizeLauncherIconInBackground( | |
347 icon, shortcut_info_.url, &is_generated); | |
348 } | |
349 | |
350 if (is_generated) | |
351 shortcut_info_.best_primary_icon_url = GURL(); | |
352 | |
353 return primary_icon; | |
354 } | |
355 | |
356 void AddToHomescreenDataFetcher::NotifyObserver(const SkBitmap& primary_icon) { | |
357 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 358 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
358 if (!web_contents() || !weak_observer_) | 359 if (!web_contents()) |
359 return; | 360 return; |
360 | 361 |
361 primary_icon_ = primary_icon; | 362 primary_icon_ = primary_icon.first; |
362 weak_observer_->OnDataAvailable(shortcut_info_, primary_icon_, badge_icon_); | 363 if (primary_icon.second) |
| 364 shortcut_info_.best_primary_icon_url = GURL(); |
| 365 observer_->OnDataAvailable(shortcut_info_, primary_icon_, badge_icon_); |
363 } | 366 } |
OLD | NEW |