Skip to content

Commit

Permalink
WebApp: Implement ReadAllIcons method in AppIconManager.
Browse files Browse the repository at this point in the history
This method will be used by views dialogs to support proper device scale
factors.

Bug: 953540
Change-Id: I854e2f9b6afd95dba1a78735a4b788c0a3714857
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1952544
Reviewed-by: Alan Cutter <alancutter@chromium.org>
Commit-Queue: Alexey Baskakov <loyso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#722274}
  • Loading branch information
Alexey Baskakov authored and Commit Bot committed Dec 5, 2019
1 parent ce35fc7 commit c4e8da9
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 10 deletions.
12 changes: 10 additions & 2 deletions chrome/browser/web_applications/components/app_icon_manager.h
Expand Up @@ -6,13 +6,14 @@
#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_APP_ICON_MANAGER_H_

#include <cstdint>
#include <map>
#include <vector>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"

class SkBitmap;
#include "chrome/common/web_application_info.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace web_app {

Expand All @@ -35,6 +36,13 @@ class AppIconManager {
int icon_size_in_px,
ReadIconCallback callback) const = 0;

// Reads all icon bitmaps for an app. Returns empty |icon_bitmaps| in
// |callback| if IO error.
using ReadAllIconsCallback =
base::OnceCallback<void(std::map<SquareSizePx, SkBitmap> icon_bitmaps)>;
virtual void ReadAllIcons(const AppId& app_id,
ReadAllIconsCallback callback) const = 0;

// Reads smallest icon with size at least |icon_size_in_px|. Returns empty
// SkBitmap in |callback| if IO error.
virtual void ReadSmallestIcon(const AppId& app_id,
Expand Down
Expand Up @@ -13,6 +13,7 @@
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

namespace extensions {

Expand Down Expand Up @@ -47,6 +48,45 @@ void ReadExtensionIcon(Profile* profile,
base::BindOnce(&OnExtensionIconLoaded, std::move(callback)));
}

void OnExtensionIconsLoaded(
BookmarkAppIconManager::ReadAllIconsCallback callback,
const gfx::Image& image) {
std::map<SquareSizePx, SkBitmap> icons_map;

gfx::ImageSkia image_skia = image.AsImageSkia();
for (const gfx::ImageSkiaRep& image_skia_rep : image_skia.image_reps())
icons_map[image_skia_rep.pixel_width()] = image_skia_rep.GetBitmap();

std::move(callback).Run(std::move(icons_map));
}

void ReadExtensionIcons(Profile* profile,
const web_app::AppId& app_id,
BookmarkAppIconManager::ReadAllIconsCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const Extension* extension = GetBookmarkApp(profile, app_id);
DCHECK(extension);

const ExtensionIconSet& icons = IconsInfo::GetIcons(extension);

std::vector<ImageLoader::ImageRepresentation> info_list;
for (const ExtensionIconSet::IconMap::value_type& icon_info : icons.map()) {
const int size_in_px = icon_info.first;

ExtensionResource resource = IconsInfo::GetIconResource(
extension, size_in_px, ExtensionIconSet::MATCH_EXACTLY);
ImageLoader::ImageRepresentation image_rep{
resource, ImageLoader::ImageRepresentation::NEVER_RESIZE,
gfx::Size{size_in_px, size_in_px}, /*scale_factor=*/0.0f};
info_list.push_back(image_rep);
}

ImageLoader* loader = ImageLoader::Get(profile);
loader->LoadImagesAsync(
extension, info_list,
base::BindOnce(&OnExtensionIconsLoaded, std::move(callback)));
}

} // anonymous namespace

BookmarkAppIconManager::BookmarkAppIconManager(Profile* profile)
Expand All @@ -72,6 +112,11 @@ void BookmarkAppIconManager::ReadIcon(const web_app::AppId& app_id,
ExtensionIconSet::MATCH_EXACTLY, std::move(callback));
}

void BookmarkAppIconManager::ReadAllIcons(const web_app::AppId& app_id,
ReadAllIconsCallback callback) const {
ReadExtensionIcons(profile_, app_id, std::move(callback));
}

void BookmarkAppIconManager::ReadSmallestIcon(const web_app::AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const {
Expand Down
Expand Up @@ -27,6 +27,8 @@ class BookmarkAppIconManager : public web_app::AppIconManager {
void ReadIcon(const web_app::AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const override;
void ReadAllIcons(const web_app::AppId& app_id,
ReadAllIconsCallback callback) const override;
void ReadSmallestIcon(const web_app::AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const override;
Expand Down
Expand Up @@ -18,10 +18,10 @@ SkBitmap CreateSquareIcon(int size_px, SkColor solid_color) {
return bitmap;
}

void AddGeneratedIcon(WebApplicationInfo* web_app_info,
void AddGeneratedIcon(std::map<SquareSizePx, SkBitmap>* icon_bitmaps,
int size_px,
SkColor solid_color) {
web_app_info->icon_bitmaps[size_px] = CreateSquareIcon(size_px, solid_color);
(*icon_bitmaps)[size_px] = CreateSquareIcon(size_px, solid_color);
}

void AddIconToIconsMap(const GURL& icon_url,
Expand Down
Expand Up @@ -5,18 +5,20 @@
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_ICON_TEST_UTILS_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_ICON_TEST_UTILS_H_

#include <map>

#include "chrome/browser/web_applications/components/web_app_install_utils.h"
#include "chrome/common/web_application_info.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"

class GURL;
class SkBitmap;

namespace web_app {

SkBitmap CreateSquareIcon(int size_px, SkColor solid_color);

void AddGeneratedIcon(WebApplicationInfo* web_app_info,
void AddGeneratedIcon(std::map<SquareSizePx, SkBitmap>* icon_bitmaps,
int size_px,
SkColor solid_color);

Expand Down
51 changes: 51 additions & 0 deletions chrome/browser/web_applications/web_app_icon_manager.cc
Expand Up @@ -193,6 +193,41 @@ SkBitmap ReadIconBlocking(std::unique_ptr<FileUtilsWrapper> utils,
return bitmap;
}

// Performs blocking I/O. May be called on another thread.
std::map<SquareSizePx, SkBitmap> ReadAllIconsBlocking(
std::unique_ptr<FileUtilsWrapper> utils,
base::FilePath web_apps_directory,
AppId app_id,
const std::vector<SquareSizePx>& downloaded_icon_sizes) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);

std::map<SquareSizePx, SkBitmap> result;

for (SquareSizePx icon_size_px : downloaded_icon_sizes) {
base::FilePath icon_file =
GetIconFileName(web_apps_directory, app_id, icon_size_px);

auto icon_data = base::MakeRefCounted<base::RefCountedString>();

if (!utils->ReadFileToString(icon_file, &icon_data->data())) {
LOG(ERROR) << "Could not read icon file: " << icon_file;
continue;
}

SkBitmap bitmap;
if (!gfx::PNGCodec::Decode(icon_data->front(), icon_data->size(),
&bitmap)) {
LOG(ERROR) << "Could not decode icon data for file " << icon_file;
continue;
}

result[icon_size_px] = bitmap;
}

return result;
}

// Performs blocking I/O. May be called on another thread.
// Returns empty vector if any errors occurred.
std::vector<uint8_t> ReadCompressedIconBlocking(
Expand Down Expand Up @@ -283,6 +318,22 @@ void WebAppIconManager::ReadIcon(const AppId& app_id,
ReadIconInternal(app_id, icon_size_in_px, std::move(callback));
}

void WebAppIconManager::ReadAllIcons(const AppId& app_id,
ReadAllIconsCallback callback) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const WebApp* web_app = registrar_.GetAppById(app_id);
if (!web_app) {
std::move(callback).Run(std::map<SquareSizePx, SkBitmap>());
return;
}

base::PostTaskAndReplyWithResult(
FROM_HERE, kTaskTraits,
base::BindOnce(ReadAllIconsBlocking, utils_->Clone(), web_apps_directory_,
app_id, web_app->downloaded_icon_sizes()),
std::move(callback));
}

void WebAppIconManager::ReadSmallestIcon(const AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const {
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/web_applications/web_app_icon_manager.h
Expand Up @@ -41,6 +41,8 @@ class WebAppIconManager : public AppIconManager {
void ReadIcon(const AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const override;
void ReadAllIcons(const AppId& app_id,
ReadAllIconsCallback callback) const override;
void ReadSmallestIcon(const AppId& app_id,
int icon_size_in_px,
ReadIconCallback callback) const override;
Expand Down
30 changes: 29 additions & 1 deletion chrome/browser/web_applications/web_app_icon_manager_unittest.cc
Expand Up @@ -55,7 +55,7 @@ class WebAppIconManagerTest : public WebAppTest {

for (size_t i = 0; i < sizes_px.size(); ++i) {
std::string icon_name = base::StringPrintf("app-%d.ico", sizes_px[i]);
AddGeneratedIcon(web_app_info.get(), sizes_px[i], colors[i]);
AddGeneratedIcon(&web_app_info->icon_bitmaps, sizes_px[i], colors[i]);
}

base::RunLoop run_loop;
Expand Down Expand Up @@ -147,6 +147,34 @@ TEST_F(WebAppIconManagerTest, WriteAndReadIcon) {
}
}

TEST_F(WebAppIconManagerTest, ReadAllIcons) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();

const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
WriteIcons(app_id, sizes_px, colors);

web_app->SetDownloadedIconSizes(sizes_px);

controller().RegisterApp(std::move(web_app));
{
base::RunLoop run_loop;

icon_manager().ReadAllIcons(
app_id,
base::BindLambdaForTesting(
[&](std::map<SquareSizePx, SkBitmap> icons_map) {
EXPECT_EQ(2u, icons_map.size());
EXPECT_EQ(colors[0], icons_map[sizes_px[0]].getColor(0, 0));
EXPECT_EQ(colors[1], icons_map[sizes_px[1]].getColor(0, 0));
run_loop.Quit();
}));

run_loop.Run();
}
}

TEST_F(WebAppIconManagerTest, ReadIconFailed) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
Expand Down
Expand Up @@ -658,8 +658,8 @@ TEST_F(WebAppInstallTaskTest, WriteDataToDisk) {
const int original_icon_size_px = icon_size::k512;

// Generate one icon as if it was fetched from renderer.
AddGeneratedIcon(&data_retriever_->web_app_info(), original_icon_size_px,
color);
AddGeneratedIcon(&data_retriever_->web_app_info().icon_bitmaps,
original_icon_size_px, color);

const AppId app_id = InstallWebAppFromManifestWithFallback();

Expand Down Expand Up @@ -880,7 +880,8 @@ TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfo_GenerateIcons) {
web_app_info->open_as_window = false;

// Add square yellow icon.
AddGeneratedIcon(web_app_info.get(), icon_size::k256, SK_ColorYELLOW);
AddGeneratedIcon(&web_app_info->icon_bitmaps, icon_size::k256,
SK_ColorYELLOW);

base::RunLoop run_loop;

Expand Down

0 comments on commit c4e8da9

Please sign in to comment.