Index: chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc |
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc |
index 27298540429ad95d42934dd9daae03681ae7a365..626e3f3b43243995d2a03860bbe6da4744cae7c6 100644 |
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc |
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc |
@@ -10,6 +10,7 @@ |
#include "base/location.h" |
#include "base/metrics/user_metrics.h" |
#include "base/task_scheduler/post_task.h" |
+#include "chrome/browser/android/shortcut_helper.h" |
#include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" |
#include "chrome/browser/favicon/favicon_service_factory.h" |
#include "chrome/browser/installable/installable_manager.h" |
@@ -64,6 +65,39 @@ InstallableParams ParamsToPerformInstallableCheck( |
return params; |
} |
+// Creates a launcher icon from |icon|. |start_url| is used to generate the icon |
+// if |icon| is empty or is not large enough. Returns a std::pair with: |
+// - the generated icon |
+// - whether |icon| was used in generating the launcher icon |
+std::pair<SkBitmap, bool> CreateLauncherIconInBackground(const GURL& start_url, |
+ const SkBitmap& icon) { |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ bool is_generated = false; |
+ SkBitmap primary_icon = ShortcutHelper::FinalizeLauncherIconInBackground( |
+ icon, start_url, &is_generated); |
+ return std::make_pair(primary_icon, is_generated); |
+} |
+ |
+// Creates a launcher icon from |bitmap_result|. |start_url| is used to |
+// generate the icon if there is no bitmap in |bitmap_result| or the bitmap is |
+// not large enough. Returns a std::pair with: |
+// - the generated icon |
+// - whether the bitmap in |bitmap_result| was used in generating the launcher |
+// icon |
+std::pair<SkBitmap, bool> CreateLauncherIconFromFaviconInBackground( |
+ const GURL& start_url, |
+ const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ SkBitmap decoded; |
+ if (bitmap_result.is_valid()) { |
+ gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), |
+ bitmap_result.bitmap_data->size(), &decoded); |
+ } |
+ return CreateLauncherIconInBackground(start_url, decoded); |
+} |
+ |
} // namespace |
AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( |
@@ -78,7 +112,7 @@ AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( |
Observer* observer) |
: content::WebContentsObserver(web_contents), |
installable_manager_(InstallableManager::FromWebContents(web_contents)), |
- weak_observer_(observer), |
+ observer_(observer), |
shortcut_info_(GetShortcutUrl(web_contents->GetBrowserContext(), |
web_contents->GetLastCommittedURL())), |
ideal_icon_size_in_px_(ideal_icon_size_in_px), |
@@ -89,7 +123,7 @@ AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( |
data_timeout_ms_(data_timeout_ms), |
check_webapk_compatibility_(check_webapk_compatibility), |
is_waiting_for_web_application_info_(true), |
- is_installable_check_complete_(false) { |
+ weak_ptr_factory_(this) { |
DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px); |
DCHECK(minimum_splash_image_size_in_px <= ideal_splash_image_size_in_px); |
@@ -99,10 +133,12 @@ AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( |
new ChromeFrameMsg_GetWebApplicationInfo(main_frame->GetRoutingID())); |
} |
+AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() {} |
+ |
void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo( |
const WebApplicationInfo& received_web_app_info) { |
is_waiting_for_web_application_info_ = false; |
- if (!web_contents() || !weak_observer_) |
+ if (!web_contents()) |
return; |
// Sanitize received_web_app_info. |
@@ -144,17 +180,15 @@ void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo( |
// timeout, fall back to using a dynamically-generated launcher icon. |
data_timeout_timer_.Start( |
FROM_HERE, base::TimeDelta::FromMilliseconds(data_timeout_ms_), |
- base::Bind(&AddToHomescreenDataFetcher::OnDataTimedout, this)); |
+ base::Bind(&AddToHomescreenDataFetcher::OnDataTimedout, |
+ weak_ptr_factory_.GetWeakPtr())); |
installable_manager_->GetData( |
ParamsToPerformManifestAndIconFetch( |
ideal_icon_size_in_px_, minimum_icon_size_in_px_, badge_size_in_px_, |
check_webapk_compatibility_), |
- base::Bind(&AddToHomescreenDataFetcher::OnDidGetManifestAndIcons, this)); |
-} |
- |
-AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() { |
- DCHECK(!weak_observer_); |
+ base::Bind(&AddToHomescreenDataFetcher::OnDidGetManifestAndIcons, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
bool AddToHomescreenDataFetcher::OnMessageReceived( |
@@ -175,22 +209,21 @@ bool AddToHomescreenDataFetcher::OnMessageReceived( |
} |
void AddToHomescreenDataFetcher::OnDataTimedout() { |
- if (!web_contents() || !weak_observer_) |
+ weak_ptr_factory_.InvalidateWeakPtrs(); |
+ |
+ if (!web_contents()) |
return; |
- if (!is_installable_check_complete_) { |
- is_installable_check_complete_ = true; |
- if (check_webapk_compatibility_) |
- weak_observer_->OnDidDetermineWebApkCompatibility(false); |
- weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
- } |
+ if (check_webapk_compatibility_) |
+ observer_->OnDidDetermineWebApkCompatibility(false); |
+ observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
CreateLauncherIcon(raw_primary_icon_); |
} |
void AddToHomescreenDataFetcher::OnDidGetManifestAndIcons( |
const InstallableData& data) { |
- if (!web_contents() || !weak_observer_ || is_installable_check_complete_) |
+ if (!web_contents()) |
return; |
if (!data.manifest.IsEmpty()) { |
@@ -203,8 +236,8 @@ void AddToHomescreenDataFetcher::OnDidGetManifestAndIcons( |
// a manifest with name and standalone specified, but no icons. |
if (data.manifest.IsEmpty() || !data.primary_icon) { |
if (check_webapk_compatibility_) |
- weak_observer_->OnDidDetermineWebApkCompatibility(false); |
- weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
+ observer_->OnDidDetermineWebApkCompatibility(false); |
+ observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
data_timeout_timer_.Stop(); |
FetchFavicon(); |
return; |
@@ -230,37 +263,35 @@ void AddToHomescreenDataFetcher::OnDidGetManifestAndIcons( |
installable_manager_->GetData( |
ParamsToPerformInstallableCheck(check_webapk_compatibility_), |
base::Bind(&AddToHomescreenDataFetcher::OnDidPerformInstallableCheck, |
- this)); |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
void AddToHomescreenDataFetcher::OnDidPerformInstallableCheck( |
const InstallableData& data) { |
data_timeout_timer_.Stop(); |
- if (!web_contents() || !weak_observer_ || is_installable_check_complete_) |
+ if (!web_contents()) |
return; |
- is_installable_check_complete_ = true; |
- |
bool webapk_compatible = false; |
if (check_webapk_compatibility_) { |
webapk_compatible = |
(data.error_code == NO_ERROR_DETECTED && data.is_installable && |
AreWebManifestUrlsWebApkCompatible(data.manifest)); |
- weak_observer_->OnDidDetermineWebApkCompatibility(webapk_compatible); |
+ observer_->OnDidDetermineWebApkCompatibility(webapk_compatible); |
} |
- weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
+ observer_->OnUserTitleAvailable(shortcut_info_.user_title); |
if (webapk_compatible) { |
shortcut_info_.UpdateSource(ShortcutInfo::SOURCE_ADD_TO_HOMESCREEN_PWA); |
- NotifyObserver(raw_primary_icon_); |
+ NotifyObserver(std::make_pair(raw_primary_icon_, false /* is_generated */)); |
} else { |
CreateLauncherIcon(raw_primary_icon_); |
} |
} |
void AddToHomescreenDataFetcher::FetchFavicon() { |
- if (!web_contents() || !weak_observer_) |
+ if (!web_contents()) |
return; |
// Grab the best, largest icon we can find to represent this bookmark. |
@@ -280,7 +311,8 @@ void AddToHomescreenDataFetcher::FetchFavicon() { |
int threshold_to_get_any_largest_icon = ideal_icon_size_in_px_ - 1; |
favicon_service->GetLargestRawFaviconForPageURL( |
shortcut_info_.url, icon_types, threshold_to_get_any_largest_icon, |
- base::Bind(&AddToHomescreenDataFetcher::OnFaviconFetched, this), |
+ base::Bind(&AddToHomescreenDataFetcher::OnFaviconFetched, |
+ weak_ptr_factory_.GetWeakPtr()), |
&favicon_task_tracker_); |
} |
@@ -288,9 +320,11 @@ void AddToHomescreenDataFetcher::OnFaviconFetched( |
const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- if (!web_contents() || !weak_observer_) |
+ if (!web_contents()) |
return; |
+ shortcut_info_.best_primary_icon_url = bitmap_result.icon_url; |
+ |
// The user is waiting for the icon to be processed before they can proceed |
// with add to homescreen. But if we shut down, there's no point starting the |
// image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN. |
@@ -298,25 +332,10 @@ void AddToHomescreenDataFetcher::OnFaviconFetched( |
FROM_HERE, |
{base::MayBlock(), base::TaskPriority::USER_VISIBLE, |
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, |
- base::BindOnce(&AddToHomescreenDataFetcher:: |
- CreateLauncherIconFromFaviconInBackground, |
- base::Unretained(this), bitmap_result), |
+ base::BindOnce(&CreateLauncherIconFromFaviconInBackground, |
+ shortcut_info_.url, bitmap_result), |
base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, |
- base::RetainedRef(this))); |
-} |
- |
-SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconFromFaviconInBackground( |
- const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- |
- if (bitmap_result.is_valid()) { |
- gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), |
- bitmap_result.bitmap_data->size(), |
- &raw_primary_icon_); |
- } |
- |
- shortcut_info_.best_primary_icon_url = bitmap_result.icon_url; |
- return CreateLauncherIconInBackground(raw_primary_icon_); |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
void AddToHomescreenDataFetcher::CreateLauncherIcon(const SkBitmap& icon) { |
@@ -329,35 +348,19 @@ void AddToHomescreenDataFetcher::CreateLauncherIcon(const SkBitmap& icon) { |
FROM_HERE, |
{base::MayBlock(), base::TaskPriority::USER_VISIBLE, |
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, |
- base::BindOnce( |
- &AddToHomescreenDataFetcher::CreateLauncherIconInBackground, |
- base::Unretained(this), icon), |
+ base::BindOnce(&CreateLauncherIconInBackground, shortcut_info_.url, icon), |
base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, |
- base::RetainedRef(this))); |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
-SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconInBackground( |
- const SkBitmap& icon) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- |
- SkBitmap primary_icon; |
- bool is_generated = false; |
- if (weak_observer_) { |
- primary_icon = weak_observer_->FinalizeLauncherIconInBackground( |
- icon, shortcut_info_.url, &is_generated); |
- } |
- |
- if (is_generated) |
- shortcut_info_.best_primary_icon_url = GURL(); |
- |
- return primary_icon; |
-} |
- |
-void AddToHomescreenDataFetcher::NotifyObserver(const SkBitmap& primary_icon) { |
+void AddToHomescreenDataFetcher::NotifyObserver( |
+ const std::pair<SkBitmap, bool /*is_generated*/>& primary_icon) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- if (!web_contents() || !weak_observer_) |
+ if (!web_contents()) |
return; |
- primary_icon_ = primary_icon; |
- weak_observer_->OnDataAvailable(shortcut_info_, primary_icon_, badge_icon_); |
+ primary_icon_ = primary_icon.first; |
+ if (primary_icon.second) |
+ shortcut_info_.best_primary_icon_url = GURL(); |
+ observer_->OnDataAvailable(shortcut_info_, primary_icon_, badge_icon_); |
} |