| 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_);
|
| }
|
|
|