| 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 |