Commit 1dbf5a77 authored by Eric Willigers's avatar Eric Willigers Committed by Commit Bot

Desktop PWAs: Cache favicons for use in context menus

Existing menu code such as RenderViewContextMenu assumes the icons are
available synchronously.

We cache the favicon for each web app. If no icon is cached, the menu
item is shown with no visible icon.

References to Bookmark Apps in RenderViewContextMenu are replaced
with references to web apps.

Bug: 1052707
Change-Id: Ib6dd23c448e01dfb36575008532fcce76b339ddd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2216834
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Commit-Queue: Maggie Cai <mxcai@chromium.org>
Auto-Submit: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: default avatarMaggie Cai <mxcai@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
Reviewed-by: default avatarAlexey Baskakov <loyso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772556}
parent 24aefbf7
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/app_service/browser_app_launcher.h"
#include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h" #include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h"
#include "chrome/browser/apps/intent_helper/page_transition_util.h" #include "chrome/browser/apps/intent_helper/page_transition_util.h"
#include "chrome/browser/extensions/menu_manager.h"
#include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
...@@ -23,6 +22,7 @@ ...@@ -23,6 +22,7 @@
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/intent_picker_tab_helper.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/web_applications/components/app_icon_manager.h"
#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h"
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "third_party/blink/public/mojom/referrer.mojom.h" #include "third_party/blink/public/mojom/referrer.mojom.h"
#include "ui/gfx/image/image.h"
#include "url/origin.h" #include "url/origin.h"
namespace { namespace {
...@@ -356,17 +357,14 @@ std::vector<IntentPickerAppInfo> AppsNavigationThrottle::FindPwaForUrl( ...@@ -356,17 +357,14 @@ std::vector<IntentPickerAppInfo> AppsNavigationThrottle::FindPwaForUrl(
if (!app_id) if (!app_id)
return apps; return apps;
// TODO(crbug.com/1052707): Use AppIconManager to read PWA icons. auto* const provider = web_app::WebAppProviderBase::GetProviderBase(profile);
auto* menu_manager = gfx::Image icon = gfx::Image::CreateFrom1xBitmap(
extensions::MenuManager::Get(web_contents->GetBrowserContext()); provider->icon_manager().GetFavicon(*app_id));
// Prefer the web and place apps of type PWA before apps of type ARC. // Prefer the web and place apps of type PWA before apps of type ARC.
// TODO(crbug.com/824598): deterministically sort this list. // TODO(crbug.com/824598): deterministically sort this list.
apps.emplace(apps.begin(), PickerEntryType::kWeb, apps.emplace(apps.begin(), PickerEntryType::kWeb, icon, *app_id,
menu_manager->GetIconForExtension(*app_id), *app_id, provider->registrar().GetAppShortName(*app_id));
web_app::WebAppProviderBase::GetProviderBase(profile)
->registrar()
.GetAppShortName(*app_id));
return apps; return apps;
} }
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
#include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/history/foreign_session_handler.h" #include "chrome/browser/ui/webui/history/foreign_session_handler.h"
#include "chrome/browser/web_applications/components/app_icon_manager.h"
#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h"
...@@ -159,6 +160,7 @@ ...@@ -159,6 +160,7 @@
#include "ui/base/models/image_model.h" #include "ui/base/models/image_model.h"
#include "ui/gfx/favicon_size.h" #include "ui/gfx/favicon_size.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/text_elider.h" #include "ui/gfx/text_elider.h"
#include "ui/strings/grit/ui_strings.h" #include "ui/strings/grit/ui_strings.h"
...@@ -1174,7 +1176,7 @@ void RenderViewContextMenu::AppendLinkItems() { ...@@ -1174,7 +1176,7 @@ void RenderViewContextMenu::AppendLinkItems() {
in_app ? IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD_INAPP in_app ? IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD_INAPP
: IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD); : IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
AppendOpenInBookmarkAppLinkItems(); AppendOpenInWebAppLinkItems();
AppendOpenWithLinkItems(); AppendOpenWithLinkItems();
// While ChromeOS supports multiple profiles, only one can be open at a // While ChromeOS supports multiple profiles, only one can be open at a
...@@ -1356,7 +1358,7 @@ void RenderViewContextMenu::AppendSmartSelectionActionItems() { ...@@ -1356,7 +1358,7 @@ void RenderViewContextMenu::AppendSmartSelectionActionItems() {
#endif #endif
} }
void RenderViewContextMenu::AppendOpenInBookmarkAppLinkItems() { void RenderViewContextMenu::AppendOpenInWebAppLinkItems() {
Profile* const profile = Profile::FromBrowserContext(browser_context_); Profile* const profile = Profile::FromBrowserContext(browser_context_);
base::Optional<web_app::AppId> app_id = base::Optional<web_app::AppId> app_id =
...@@ -1373,16 +1375,15 @@ void RenderViewContextMenu::AppendOpenInBookmarkAppLinkItems() { ...@@ -1373,16 +1375,15 @@ void RenderViewContextMenu::AppendOpenInBookmarkAppLinkItems() {
open_in_app_string_id = IDS_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP; open_in_app_string_id = IDS_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP;
} }
auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile); auto* const provider = web_app::WebAppProviderBase::GetProviderBase(profile);
menu_model_.AddItem( menu_model_.AddItem(
IDC_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP, IDC_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP,
l10n_util::GetStringFUTF16( l10n_util::GetStringFUTF16(
open_in_app_string_id, open_in_app_string_id,
base::UTF8ToUTF16(provider->registrar().GetAppShortName(*app_id)))); base::UTF8ToUTF16(provider->registrar().GetAppShortName(*app_id))));
MenuManager* menu_manager = MenuManager::Get(browser_context_); gfx::Image icon = gfx::Image::CreateFrom1xBitmap(
// TODO(crbug.com/1052707): Use AppIconManager to read PWA icons. provider->icon_manager().GetFavicon(*app_id));
gfx::Image icon = menu_manager->GetIconForExtension(*app_id);
menu_model_.SetIcon(menu_model_.GetItemCount() - 1, menu_model_.SetIcon(menu_model_.GetItemCount() - 1,
ui::ImageModel::FromImage(icon)); ui::ImageModel::FromImage(icon));
} }
...@@ -2207,7 +2208,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { ...@@ -2207,7 +2208,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
break; break;
case IDC_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP: case IDC_CONTENT_CONTEXT_OPENLINKBOOKMARKAPP:
ExecOpenBookmarkApp(); ExecOpenWebApp();
break; break;
case IDC_CONTENT_CONTEXT_SAVELINKAS: case IDC_CONTENT_CONTEXT_SAVELINKAS:
...@@ -2725,7 +2726,7 @@ bool RenderViewContextMenu::IsOpenLinkOTREnabled() const { ...@@ -2725,7 +2726,7 @@ bool RenderViewContextMenu::IsOpenLinkOTREnabled() const {
return incognito_avail != IncognitoModePrefs::DISABLED; return incognito_avail != IncognitoModePrefs::DISABLED;
} }
void RenderViewContextMenu::ExecOpenBookmarkApp() { void RenderViewContextMenu::ExecOpenWebApp() {
base::Optional<web_app::AppId> app_id = base::Optional<web_app::AppId> app_id =
web_app::FindInstalledAppWithUrlInScope( web_app::FindInstalledAppWithUrlInScope(
Profile::FromBrowserContext(browser_context_), params_.link_url); Profile::FromBrowserContext(browser_context_), params_.link_url);
......
...@@ -160,7 +160,7 @@ class RenderViewContextMenu : public RenderViewContextMenuBase { ...@@ -160,7 +160,7 @@ class RenderViewContextMenu : public RenderViewContextMenuBase {
void AppendLinkItems(); void AppendLinkItems();
void AppendOpenWithLinkItems(); void AppendOpenWithLinkItems();
void AppendSmartSelectionActionItems(); void AppendSmartSelectionActionItems();
void AppendOpenInBookmarkAppLinkItems(); void AppendOpenInWebAppLinkItems();
void AppendQuickAnswersItems(); void AppendQuickAnswersItems();
void AppendImageItems(); void AppendImageItems();
void AppendAudioItems(); void AppendAudioItems();
...@@ -211,7 +211,7 @@ class RenderViewContextMenu : public RenderViewContextMenuBase { ...@@ -211,7 +211,7 @@ class RenderViewContextMenu : public RenderViewContextMenuBase {
bool IsOpenLinkOTREnabled() const; bool IsOpenLinkOTREnabled() const;
// Command execution functions. // Command execution functions.
void ExecOpenBookmarkApp(); void ExecOpenWebApp();
void ExecProtocolHandler(int event_flags, int handler_index); void ExecProtocolHandler(int event_flags, int handler_index);
void ExecOpenLinkInProfile(int profile_index); void ExecOpenLinkInProfile(int profile_index);
void ExecInspectElement(); void ExecInspectElement();
......
...@@ -23,6 +23,9 @@ class AppIconManager { ...@@ -23,6 +23,9 @@ class AppIconManager {
AppIconManager() = default; AppIconManager() = default;
virtual ~AppIconManager() = default; virtual ~AppIconManager() = default;
virtual void Start() = 0;
virtual void Shutdown() = 0;
// Returns false if any icon in |icon_sizes_in_px| is missing from downloaded // Returns false if any icon in |icon_sizes_in_px| is missing from downloaded
// icons for a given app. |icon_sizes_in_px| must be sorted in ascending // icons for a given app. |icon_sizes_in_px| must be sorted in ascending
// order. // order.
...@@ -75,6 +78,8 @@ class AppIconManager { ...@@ -75,6 +78,8 @@ class AppIconManager {
SquareSizePx icon_size_in_px, SquareSizePx icon_size_in_px,
ReadCompressedIconCallback callback) const = 0; ReadCompressedIconCallback callback) const = 0;
virtual SkBitmap GetFavicon(const AppId& app_id) const = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(AppIconManager); DISALLOW_COPY_AND_ASSIGN(AppIconManager);
}; };
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/check_op.h" #include "base/check_op.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "chrome/browser/extensions/menu_manager.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h" #include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
...@@ -96,6 +97,10 @@ BookmarkAppIconManager::BookmarkAppIconManager(Profile* profile) ...@@ -96,6 +97,10 @@ BookmarkAppIconManager::BookmarkAppIconManager(Profile* profile)
BookmarkAppIconManager::~BookmarkAppIconManager() = default; BookmarkAppIconManager::~BookmarkAppIconManager() = default;
void BookmarkAppIconManager::Start() {}
void BookmarkAppIconManager::Shutdown() {}
bool BookmarkAppIconManager::HasIcons( bool BookmarkAppIconManager::HasIcons(
const web_app::AppId& app_id, const web_app::AppId& app_id,
const std::vector<SquareSizePx>& icon_sizes_in_px) const { const std::vector<SquareSizePx>& icon_sizes_in_px) const {
...@@ -172,4 +177,10 @@ void BookmarkAppIconManager::ReadSmallestCompressedIcon( ...@@ -172,4 +177,10 @@ void BookmarkAppIconManager::ReadSmallestCompressedIcon(
std::move(callback).Run(std::vector<uint8_t>()); std::move(callback).Run(std::vector<uint8_t>());
} }
SkBitmap BookmarkAppIconManager::GetFavicon(
const web_app::AppId& app_id) const {
auto* menu_manager = extensions::MenuManager::Get(profile_);
return menu_manager->GetIconForExtension(app_id).AsBitmap();
}
} // namespace extensions } // namespace extensions
...@@ -22,6 +22,8 @@ class BookmarkAppIconManager : public web_app::AppIconManager { ...@@ -22,6 +22,8 @@ class BookmarkAppIconManager : public web_app::AppIconManager {
~BookmarkAppIconManager() override; ~BookmarkAppIconManager() override;
// AppIconManager: // AppIconManager:
void Start() override;
void Shutdown() override;
bool HasIcons( bool HasIcons(
const web_app::AppId& app_id, const web_app::AppId& app_id,
const std::vector<SquareSizePx>& icon_sizes_in_px) const override; const std::vector<SquareSizePx>& icon_sizes_in_px) const override;
...@@ -42,6 +44,7 @@ class BookmarkAppIconManager : public web_app::AppIconManager { ...@@ -42,6 +44,7 @@ class BookmarkAppIconManager : public web_app::AppIconManager {
const web_app::AppId& app_id, const web_app::AppId& app_id,
SquareSizePx icon_size_in_px, SquareSizePx icon_size_in_px,
ReadCompressedIconCallback callback) const override; ReadCompressedIconCallback callback) const override;
SkBitmap GetFavicon(const web_app::AppId& app_id) const override;
private: private:
Profile* const profile_; Profile* const profile_;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "skia/ext/image_operations.h" #include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
namespace web_app { namespace web_app {
...@@ -494,6 +495,15 @@ void WebAppIconManager::DeleteData(AppId app_id, WriteDataCallback callback) { ...@@ -494,6 +495,15 @@ void WebAppIconManager::DeleteData(AppId app_id, WriteDataCallback callback) {
std::move(callback)); std::move(callback));
} }
void WebAppIconManager::Start() {
for (const AppId& app_id : registrar_.GetAppIds()) {
ReadFavicon(app_id);
}
registrar_observer_.Add(&registrar_);
}
void WebAppIconManager::Shutdown() {}
bool WebAppIconManager::HasIcons( bool WebAppIconManager::HasIcons(
const AppId& app_id, const AppId& app_id,
const std::vector<SquareSizePx>& icon_sizes_in_px) const { const std::vector<SquareSizePx>& icon_sizes_in_px) const {
...@@ -590,6 +600,21 @@ void WebAppIconManager::ReadSmallestCompressedIcon( ...@@ -590,6 +600,21 @@ void WebAppIconManager::ReadSmallestCompressedIcon(
std::move(callback)); std::move(callback));
} }
SkBitmap WebAppIconManager::GetFavicon(const web_app::AppId& app_id) const {
auto iter = favicon_cache_.find(app_id);
if (iter == favicon_cache_.end())
return SkBitmap();
return iter->second;
}
void WebAppIconManager::OnWebAppInstalled(const AppId& app_id) {
ReadFavicon(app_id);
}
void WebAppIconManager::OnAppRegistrarDestroyed() {
registrar_observer_.RemoveAll();
}
bool WebAppIconManager::HasIconToResize(const AppId& app_id, bool WebAppIconManager::HasIconToResize(const AppId& app_id,
SquareSizePx desired_icon_size) const { SquareSizePx desired_icon_size) const {
return FindDownloadedSizeInPxMatchBigger(app_id, desired_icon_size) return FindDownloadedSizeInPxMatchBigger(app_id, desired_icon_size)
...@@ -620,6 +645,11 @@ void WebAppIconManager::ReadIconAndResize(const AppId& app_id, ...@@ -620,6 +645,11 @@ void WebAppIconManager::ReadIconAndResize(const AppId& app_id,
std::move(callback)); std::move(callback));
} }
void WebAppIconManager::SetFaviconReadCallbackForTesting(
FaviconReadCallback callback) {
favicon_read_callback_ = callback;
}
base::Optional<SquareSizePx> base::Optional<SquareSizePx>
WebAppIconManager::FindDownloadedSizeInPxMatchBigger( WebAppIconManager::FindDownloadedSizeInPxMatchBigger(
const AppId& app_id, const AppId& app_id,
...@@ -656,4 +686,20 @@ WebAppIconManager::FindDownloadedSizeInPxMatchSmaller( ...@@ -656,4 +686,20 @@ WebAppIconManager::FindDownloadedSizeInPxMatchSmaller(
return base::nullopt; return base::nullopt;
} }
void WebAppIconManager::ReadFavicon(const AppId& app_id) {
if (!HasSmallestIcon(app_id, gfx::kFaviconSize))
return;
ReadSmallestIcon(app_id, gfx::kFaviconSize,
base::BindOnce(&WebAppIconManager::OnReadFavicon,
weak_ptr_factory_.GetWeakPtr(), app_id));
}
void WebAppIconManager::OnReadFavicon(const AppId& app_id,
const SkBitmap& bitmap) {
favicon_cache_[app_id] = bitmap;
if (favicon_read_callback_)
favicon_read_callback_.Run(app_id);
}
} // namespace web_app } // namespace web_app
...@@ -9,10 +9,15 @@ ...@@ -9,10 +9,15 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/scoped_observer.h"
#include "chrome/browser/web_applications/components/app_icon_manager.h" #include "chrome/browser/web_applications/components/app_icon_manager.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/app_registrar_observer.h"
#include "chrome/common/web_application_info.h" #include "chrome/common/web_application_info.h"
class Profile; class Profile;
...@@ -23,8 +28,11 @@ class FileUtilsWrapper; ...@@ -23,8 +28,11 @@ class FileUtilsWrapper;
class WebAppRegistrar; class WebAppRegistrar;
// Exclusively used from the UI thread. // Exclusively used from the UI thread.
class WebAppIconManager : public AppIconManager { class WebAppIconManager : public AppIconManager, public AppRegistrarObserver {
public: public:
using FaviconReadCallback =
base::RepeatingCallback<void(const AppId& app_id)>;
WebAppIconManager(Profile* profile, WebAppIconManager(Profile* profile,
WebAppRegistrar& registrar, WebAppRegistrar& registrar,
std::unique_ptr<FileUtilsWrapper> utils); std::unique_ptr<FileUtilsWrapper> utils);
...@@ -43,6 +51,8 @@ class WebAppIconManager : public AppIconManager { ...@@ -43,6 +51,8 @@ class WebAppIconManager : public AppIconManager {
void DeleteData(AppId app_id, WriteDataCallback callback); void DeleteData(AppId app_id, WriteDataCallback callback);
// AppIconManager: // AppIconManager:
void Start() override;
void Shutdown() override;
bool HasIcons( bool HasIcons(
const AppId& app_id, const AppId& app_id,
const std::vector<SquareSizePx>& icon_sizes_in_px) const override; const std::vector<SquareSizePx>& icon_sizes_in_px) const override;
...@@ -63,6 +73,11 @@ class WebAppIconManager : public AppIconManager { ...@@ -63,6 +73,11 @@ class WebAppIconManager : public AppIconManager {
const AppId& app_id, const AppId& app_id,
SquareSizePx icon_size_in_px, SquareSizePx icon_size_in_px,
ReadCompressedIconCallback callback) const override; ReadCompressedIconCallback callback) const override;
SkBitmap GetFavicon(const web_app::AppId& app_id) const override;
// AppRegistrarObserver:
void OnWebAppInstalled(const AppId& app_id) override;
void OnAppRegistrarDestroyed() override;
// If there is no icon at the downloaded sizes, we may resize what we can get. // If there is no icon at the downloaded sizes, we may resize what we can get.
bool HasIconToResize(const AppId& app_id, bool HasIconToResize(const AppId& app_id,
...@@ -73,6 +88,8 @@ class WebAppIconManager : public AppIconManager { ...@@ -73,6 +88,8 @@ class WebAppIconManager : public AppIconManager {
SquareSizePx desired_icon_size, SquareSizePx desired_icon_size,
ReadIconsCallback callback) const; ReadIconsCallback callback) const;
void SetFaviconReadCallbackForTesting(FaviconReadCallback callback);
private: private:
base::Optional<SquareSizePx> FindDownloadedSizeInPxMatchBigger( base::Optional<SquareSizePx> FindDownloadedSizeInPxMatchBigger(
const AppId& app_id, const AppId& app_id,
...@@ -81,10 +98,22 @@ class WebAppIconManager : public AppIconManager { ...@@ -81,10 +98,22 @@ class WebAppIconManager : public AppIconManager {
const AppId& app_id, const AppId& app_id,
SquareSizePx desired_size) const; SquareSizePx desired_size) const;
const WebAppRegistrar& registrar_; void ReadFavicon(const AppId& app_id);
void OnReadFavicon(const AppId& app_id, const SkBitmap&);
WebAppRegistrar& registrar_;
base::FilePath web_apps_directory_; base::FilePath web_apps_directory_;
std::unique_ptr<FileUtilsWrapper> utils_; std::unique_ptr<FileUtilsWrapper> utils_;
ScopedObserver<AppRegistrar, AppRegistrarObserver> registrar_observer_{this};
// We cache a single low-resolution icon for each app.
std::map<AppId, SkBitmap> favicon_cache_;
FaviconReadCallback favicon_read_callback_;
base::WeakPtrFactory<WebAppIconManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebAppIconManager); DISALLOW_COPY_AND_ASSIGN(WebAppIconManager);
}; };
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/favicon_size.h"
namespace web_app { namespace web_app {
...@@ -653,4 +654,64 @@ TEST_F(WebAppIconManagerTest, MatchSizes) { ...@@ -653,4 +654,64 @@ TEST_F(WebAppIconManagerTest, MatchSizes) {
EXPECT_EQ(kWebAppIconSmall, extension_misc::EXTENSION_ICON_SMALL); EXPECT_EQ(kWebAppIconSmall, extension_misc::EXTENSION_ICON_SMALL);
} }
TEST_F(WebAppIconManagerTest, CacheExistingAppFavicon) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const std::vector<int> sizes_px{gfx::kFaviconSize, icon_size::k48};
const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorRED};
WriteIcons(app_id, sizes_px, colors);
web_app->SetDownloadedIconSizes(sizes_px);
controller().RegisterApp(std::move(web_app));
base::RunLoop run_loop;
icon_manager().SetFaviconReadCallbackForTesting(
base::BindLambdaForTesting([&](const AppId& cached_app_id) {
EXPECT_EQ(cached_app_id, app_id);
run_loop.Quit();
}));
icon_manager().Start();
run_loop.Run();
SkBitmap bitmap = icon_manager().GetFavicon(app_id);
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(gfx::kFaviconSize, bitmap.width());
EXPECT_EQ(gfx::kFaviconSize, bitmap.height());
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0));
}
TEST_F(WebAppIconManagerTest, CacheNewAppFavicon) {
icon_manager().Start();
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const std::vector<int> sizes_px{gfx::kFaviconSize, icon_size::k48};
const std::vector<SkColor> colors{SK_ColorBLUE, SK_ColorRED};
WriteIcons(app_id, sizes_px, colors);
web_app->SetDownloadedIconSizes(sizes_px);
base::RunLoop run_loop;
icon_manager().SetFaviconReadCallbackForTesting(
base::BindLambdaForTesting([&](const AppId& cached_app_id) {
EXPECT_EQ(cached_app_id, app_id);
run_loop.Quit();
}));
controller().RegisterApp(std::move(web_app));
registrar().NotifyWebAppInstalled(app_id);
run_loop.Run();
SkBitmap bitmap = icon_manager().GetFavicon(app_id);
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(gfx::kFaviconSize, bitmap.width());
EXPECT_EQ(gfx::kFaviconSize, bitmap.height());
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 0));
}
} // namespace web_app } // namespace web_app
...@@ -155,6 +155,7 @@ void WebAppProvider::Shutdown() { ...@@ -155,6 +155,7 @@ void WebAppProvider::Shutdown() {
install_manager_->Shutdown(); install_manager_->Shutdown();
manifest_update_manager_->Shutdown(); manifest_update_manager_->Shutdown();
system_web_app_manager_->Shutdown(); system_web_app_manager_->Shutdown();
icon_manager_->Shutdown();
install_finalizer_->Shutdown(); install_finalizer_->Shutdown();
registrar_->Shutdown(); registrar_->Shutdown();
} }
...@@ -274,6 +275,7 @@ void WebAppProvider::OnRegistryControllerReady() { ...@@ -274,6 +275,7 @@ void WebAppProvider::OnRegistryControllerReady() {
registrar_->Start(); registrar_->Start();
install_finalizer_->Start(); install_finalizer_->Start();
icon_manager_->Start();
external_web_app_manager_->Start(); external_web_app_manager_->Start();
web_app_policy_manager_->Start(); web_app_policy_manager_->Start();
system_web_app_manager_->Start(); system_web_app_manager_->Start();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment