summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcalamity@chromium.org <calamity@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-25 06:28:15 +0000
committercalamity@chromium.org <calamity@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-25 06:28:15 +0000
commit33c878970a834a4f64bd2205c1183216019bb156 (patch)
tree2cd1182db3352fb9fdaf8c11583a1487aa31f25e
parent008e3b3ce883855afaaeb0ea150594c09c8877f1 (diff)
downloadchromium_src-33c878970a834a4f64bd2205c1183216019bb156.zip
chromium_src-33c878970a834a4f64bd2205c1183216019bb156.tar.gz
chromium_src-33c878970a834a4f64bd2205c1183216019bb156.tar.bz2
Pull bookmark app creation from TabHelper into its own class.
This CL adds a BookmarkAppHelper which encapsulates the creation of a bookmark app from a WebContents, allowing tests to be written. The implementation is pulled from TabHelper where this functionality was previously implemented. BUG=318607 Review URL: https://codereview.chromium.org/197683004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259165 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/bookmark_app_helper.cc285
-rw-r--r--chrome/browser/extensions/bookmark_app_helper.h93
-rw-r--r--chrome/browser/extensions/bookmark_app_helper_unittest.cc195
-rw-r--r--chrome/browser/extensions/tab_helper.cc302
-rw-r--r--chrome/browser/extensions/tab_helper.h26
-rw-r--r--chrome/browser/extensions/tab_helper_unittest.cc103
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi2
8 files changed, 616 insertions, 392 deletions
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
new file mode 100644
index 0000000..24ce2f8
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -0,0 +1,285 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/bookmark_app_helper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/favicon_downloader.h"
+#include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/common/extension.h"
+#include "skia/ext/image_operations.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/image/image.h"
+
+namespace extensions {
+
+// static
+std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes(
+ const std::vector<SkBitmap>& bitmaps,
+ const std::set<int>& sizes) {
+ std::map<int, SkBitmap> output_bitmaps;
+ std::map<int, SkBitmap> ordered_bitmaps;
+ for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
+ it != bitmaps.end();
+ ++it) {
+ DCHECK(it->width() == it->height());
+ ordered_bitmaps[it->width()] = *it;
+ }
+
+ std::set<int>::const_iterator sizes_it = sizes.begin();
+ std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
+ while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
+ int size = *sizes_it;
+ // Find the closest not-smaller bitmap.
+ bitmaps_it = ordered_bitmaps.lower_bound(size);
+ ++sizes_it;
+ // Ensure the bitmap is valid and smaller than the next allowed size.
+ if (bitmaps_it != ordered_bitmaps.end() &&
+ (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
+ // Resize the bitmap if it does not exactly match the desired size.
+ output_bitmaps[size] = bitmaps_it->second.width() == size
+ ? bitmaps_it->second
+ : skia::ImageOperations::Resize(
+ bitmaps_it->second,
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ size,
+ size);
+ }
+ }
+ return output_bitmaps;
+}
+
+// static
+void BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
+ int output_size) {
+ std::map<int, SkBitmap>::const_iterator it =
+ bitmaps->lower_bound(output_size);
+ // Do nothing if there is no icon smaller than the desired size or there is
+ // already an icon of |output_size|.
+ if (it == bitmaps->begin() || bitmaps->count(output_size))
+ return;
+
+ --it;
+ // This is the biggest icon smaller than |output_size|.
+ const SkBitmap& base_icon = it->second;
+
+ const size_t kBorderRadius = 5;
+ const size_t kColorStripHeight = 3;
+ const SkColor kBorderColor = 0xFFD5D5D5;
+ const SkColor kBackgroundColor = 0xFFFFFFFF;
+
+ // Create a separate canvas for the color strip.
+ scoped_ptr<SkCanvas> color_strip_canvas(
+ skia::CreateBitmapCanvas(output_size, output_size, false));
+ DCHECK(color_strip_canvas);
+
+ // Draw a rounded rect of the |base_icon|'s dominant color.
+ SkPaint color_strip_paint;
+ color_utils::GridSampler sampler;
+ color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
+ color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG(
+ gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
+ 100,
+ 665,
+ &sampler));
+ color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+ kBorderRadius,
+ kBorderRadius,
+ color_strip_paint);
+
+ // Erase the top of the rounded rect to leave a color strip.
+ SkPaint clear_paint;
+ clear_paint.setColor(SK_ColorTRANSPARENT);
+ clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ color_strip_canvas->drawRect(
+ SkRect::MakeWH(output_size, output_size - kColorStripHeight),
+ clear_paint);
+
+ // Draw each element to an output canvas.
+ scoped_ptr<SkCanvas> canvas(
+ skia::CreateBitmapCanvas(output_size, output_size, false));
+ DCHECK(canvas);
+
+ // Draw the background.
+ SkPaint background_paint;
+ background_paint.setColor(kBackgroundColor);
+ background_paint.setFlags(SkPaint::kAntiAlias_Flag);
+ canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+ kBorderRadius,
+ kBorderRadius,
+ background_paint);
+
+ // Draw the color strip.
+ canvas->drawBitmap(
+ color_strip_canvas->getDevice()->accessBitmap(false), 0, 0);
+
+ // Draw the border.
+ SkPaint border_paint;
+ border_paint.setColor(kBorderColor);
+ border_paint.setStyle(SkPaint::kStroke_Style);
+ border_paint.setFlags(SkPaint::kAntiAlias_Flag);
+ canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+ kBorderRadius,
+ kBorderRadius,
+ border_paint);
+
+ // Draw the centered base icon to the output canvas.
+ canvas->drawBitmap(base_icon,
+ (output_size - base_icon.width()) / 2,
+ (output_size - base_icon.height()) / 2);
+
+ const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false);
+ generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
+}
+
+BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
+ WebApplicationInfo web_app_info,
+ content::WebContents* contents)
+ : web_app_info_(web_app_info),
+ crx_installer_(extensions::CrxInstaller::CreateSilent(service)) {
+ registrar_.Add(this,
+ chrome::NOTIFICATION_CRX_INSTALLER_DONE,
+ content::Source<CrxInstaller>(crx_installer_.get()));
+
+ registrar_.Add(this,
+ chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+ content::Source<CrxInstaller>(crx_installer_.get()));
+
+ crx_installer_->set_error_on_unsupported_requirements(true);
+
+ // Add urls from the WebApplicationInfo.
+ std::vector<GURL> web_app_info_icon_urls;
+ for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
+ web_app_info_.icons.begin();
+ it != web_app_info_.icons.end();
+ ++it) {
+ if (it->url.is_valid())
+ web_app_info_icon_urls.push_back(it->url);
+ }
+
+ favicon_downloader_.reset(
+ new FaviconDownloader(contents,
+ web_app_info_icon_urls,
+ base::Bind(&BookmarkAppHelper::OnIconsDownloaded,
+ base::Unretained(this))));
+}
+
+BookmarkAppHelper::~BookmarkAppHelper() {}
+
+void BookmarkAppHelper::Create(const CreateBookmarkAppCallback& callback) {
+ callback_ = callback;
+ favicon_downloader_->Start();
+}
+
+void BookmarkAppHelper::OnIconsDownloaded(
+ bool success,
+ const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
+ // The tab has navigated away during the icon download. Cancel the bookmark
+ // app creation.
+ if (!success) {
+ favicon_downloader_.reset();
+ callback_.Run(NULL, web_app_info_);
+ return;
+ }
+
+ // Add the downloaded icons. Extensions only allow certain icon sizes. First
+ // populate icons that match the allowed sizes exactly and then downscale
+ // remaining icons to the closest allowed size that doesn't yet have an icon.
+ std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
+ extension_misc::kExtensionIconSizes +
+ extension_misc::kNumExtensionIconSizes);
+ std::vector<SkBitmap> downloaded_icons;
+ for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
+ map_it != bitmaps.end();
+ ++map_it) {
+ for (std::vector<SkBitmap>::const_iterator bitmap_it =
+ map_it->second.begin();
+ bitmap_it != map_it->second.end();
+ ++bitmap_it) {
+ if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
+ continue;
+
+ downloaded_icons.push_back(*bitmap_it);
+ }
+ }
+
+ // If there are icons that don't match the accepted icon sizes, find the
+ // closest bigger icon to the accepted sizes and resize the icon to it. An
+ // icon will be resized and used for at most one size.
+ std::map<int, SkBitmap> resized_bitmaps(
+ ConstrainBitmapsToSizes(downloaded_icons, allowed_sizes));
+
+ // Generate container icons from smaller icons.
+ const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL,
+ extension_misc::EXTENSION_ICON_MEDIUM, };
+ const std::set<int> generate_sizes(
+ kIconSizesToGenerate,
+ kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
+
+ // Only generate icons if larger icons don't exist. This means the app
+ // launcher and the taskbar will do their best downsizing large icons and
+ // these container icons are only generated as a last resort against upscaling
+ // a smaller icon.
+ if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
+ resized_bitmaps.end()) {
+ // Generate these from biggest to smallest so we don't end up with
+ // concentric container icons.
+ for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
+ it != generate_sizes.rend();
+ ++it) {
+ GenerateContainerIcon(&resized_bitmaps, *it);
+ }
+ }
+
+ // Populate the icon data into the WebApplicationInfo we are using to
+ // install the bookmark app.
+ for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
+ resized_bitmaps.begin();
+ resized_bitmaps_it != resized_bitmaps.end();
+ ++resized_bitmaps_it) {
+ WebApplicationInfo::IconInfo icon_info;
+ icon_info.data = resized_bitmaps_it->second;
+ icon_info.width = icon_info.data.width();
+ icon_info.height = icon_info.data.height();
+ web_app_info_.icons.push_back(icon_info);
+ }
+
+ // Install the app.
+ crx_installer_->InstallWebApp(web_app_info_);
+ favicon_downloader_.reset();
+}
+
+void BookmarkAppHelper::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
+ const Extension* extension =
+ content::Details<const Extension>(details).ptr();
+ DCHECK(extension);
+ DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(extension),
+ web_app_info_.app_url);
+ callback_.Run(extension, web_app_info_);
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR:
+ callback_.Run(NULL, web_app_info_);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h
new file mode 100644
index 0000000..6218dc3
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
+#define CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/web_application_info.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class ExtensionService;
+class FaviconDownloader;
+class SkBitmap;
+
+namespace content {
+class WebContents;
+}
+
+namespace extensions {
+class CrxInstaller;
+class Extension;
+
+// A helper class for creating bookmark apps from a WebContents.
+class BookmarkAppHelper : public content::NotificationObserver {
+ public:
+ typedef base::Callback<void(const Extension*, const WebApplicationInfo&)>
+ CreateBookmarkAppCallback;
+
+ // This helper class will create a bookmark app out of |web_app_info| and
+ // install it to |service|. Icons will be downloaded from the URLs in
+ // |web_app_info.icons| using |contents|.
+ BookmarkAppHelper(ExtensionService* service,
+ WebApplicationInfo web_app_info,
+ content::WebContents* contents);
+ virtual ~BookmarkAppHelper();
+
+ // This finds the closest not-smaller bitmap in |bitmaps| for each size in
+ // |sizes| and resizes it to that size. This returns a map of sizes to bitmaps
+ // which contains only bitmaps of a size in |sizes| and at most one bitmap of
+ // each size.
+ static std::map<int, SkBitmap> ConstrainBitmapsToSizes(
+ const std::vector<SkBitmap>& bitmaps,
+ const std::set<int>& sizes);
+
+ // Adds a square container icon of |output_size| pixels to |bitmaps| by
+ // centering the biggest smaller icon in |bitmaps| and drawing a rounded
+ // rectangle with strip of the that icon's dominant color at the bottom.
+ // Does nothing if an icon of |output_size| already exists in |bitmaps|.
+ static void GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
+ int output_size);
+
+ // Begins the asynchronous bookmark app creation.
+ void Create(const CreateBookmarkAppCallback& callback);
+
+ private:
+ friend class TestBookmarkAppHelper;
+
+ // Performs post icon download tasks including installing the bookmark app.
+ void OnIconsDownloaded(bool success,
+ const std::map<GURL, std::vector<SkBitmap> >& bitmaps);
+
+ // Overridden from content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // The WebApplicationInfo that the bookmark app is being created for.
+ WebApplicationInfo web_app_info_;
+
+ // Called on app creation or failure.
+ CreateBookmarkAppCallback callback_;
+
+ // Downloads icons from the given WebApplicationInfo using the given
+ // WebContents.
+ scoped_ptr<FaviconDownloader> favicon_downloader_;
+
+ // Used to install the created bookmark app.
+ scoped_refptr<extensions::CrxInstaller> crx_installer_;
+
+ content::NotificationRegistrar registrar_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
new file mode 100644
index 0000000..bac705e
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/bookmark_app_helper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
+#include "chrome/test/base/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace {
+
+#if !defined(OS_ANDROID)
+const char kAppUrl[] = "http://www.chromium.org";
+const char kAppTitle[] = "Test title";
+const char kAppDescription[] = "Test description";
+
+const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL;
+#endif
+
+class BookmarkAppHelperTest : public testing::Test {
+ public:
+ BookmarkAppHelperTest() {}
+ virtual ~BookmarkAppHelperTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperTest);
+};
+
+class BookmarkAppHelperExtensionServiceTest : public ExtensionServiceTestBase {
+ public:
+ BookmarkAppHelperExtensionServiceTest() {}
+ virtual ~BookmarkAppHelperExtensionServiceTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ExtensionServiceTestBase::SetUp();
+ InitializeEmptyExtensionService();
+ service_->Init();
+ EXPECT_EQ(0u, service_->extensions()->size());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest);
+};
+
+SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, size, size);
+ bitmap.allocPixels();
+ bitmap.eraseColor(color);
+ return bitmap;
+}
+
+void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) {
+ // Obtain pixel lock to access pixels.
+ SkAutoLockPixels lock(bitmap);
+ EXPECT_EQ(color, bitmap.getColor(0, 0));
+ EXPECT_EQ(size, bitmap.width());
+ EXPECT_EQ(size, bitmap.height());
+}
+
+} // namespace
+
+namespace extensions {
+
+class TestBookmarkAppHelper : public BookmarkAppHelper {
+ public:
+ TestBookmarkAppHelper(ExtensionService* service,
+ WebApplicationInfo web_app_info,
+ content::WebContents* contents)
+ : BookmarkAppHelper(service, web_app_info, contents) {}
+
+ virtual ~TestBookmarkAppHelper() {}
+
+ void CreationComplete(const extensions::Extension* extension,
+ const WebApplicationInfo& web_app_info) {
+ extension_ = extension;
+ }
+
+ void CompleteIconDownload(
+ bool success,
+ const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
+ BookmarkAppHelper::OnIconsDownloaded(success, bitmaps);
+ }
+
+ const Extension* extension() { return extension_; }
+
+ private:
+ const Extension* extension_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppHelper);
+};
+
+// Android doesn't support extensions.
+#if !defined(OS_ANDROID)
+TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) {
+ WebApplicationInfo web_app_info;
+ web_app_info.app_url = GURL(kAppUrl);
+ web_app_info.title = base::UTF8ToUTF16(kAppTitle);
+ web_app_info.description = base::UTF8ToUTF16(kAppDescription);
+
+ TestBookmarkAppHelper helper(service_, web_app_info, NULL);
+ helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
+ base::Unretained(&helper)));
+
+ std::map<GURL, std::vector<SkBitmap> > icon_map;
+ icon_map[GURL(kAppUrl)].push_back(
+ CreateSquareBitmapWithColor(kIconSizeSmall, SK_ColorRED));
+ helper.CompleteIconDownload(true, icon_map);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(helper.extension());
+ const Extension* extension =
+ service_->GetInstalledExtension(helper.extension()->id());
+ EXPECT_TRUE(extension);
+ EXPECT_EQ(1u, service_->extensions()->size());
+ EXPECT_TRUE(extension->from_bookmark());
+ EXPECT_EQ(kAppTitle, extension->name());
+ EXPECT_EQ(kAppDescription, extension->description());
+ EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
+ EXPECT_FALSE(
+ IconsInfo::GetIconResource(
+ extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
+}
+#endif
+
+TEST_F(BookmarkAppHelperTest, ConstrainBitmapsToSizes) {
+ std::set<int> desired_sizes;
+ desired_sizes.insert(16);
+ desired_sizes.insert(32);
+ desired_sizes.insert(128);
+ desired_sizes.insert(256);
+
+ {
+ std::vector<SkBitmap> bitmaps;
+ bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED));
+ bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN));
+ bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE));
+ bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW));
+
+ std::map<int, SkBitmap> results(
+ BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
+
+ EXPECT_EQ(3u, results.size());
+ ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED);
+ ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN);
+ ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW);
+ }
+ {
+ std::vector<SkBitmap> bitmaps;
+ bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED));
+ bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN));
+ bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE));
+ bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW));
+
+ std::map<int, SkBitmap> results(
+ BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
+
+ EXPECT_EQ(3u, results.size());
+ ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW);
+ ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE);
+ ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED);
+ }
+}
+
+TEST_F(BookmarkAppHelperTest, GenerateIcons) {
+ {
+ // The 32x32 icon should be generated from the 16x16 icon.
+ std::map<int, SkBitmap> bitmaps;
+ bitmaps[16] = CreateSquareBitmapWithColor(16, SK_ColorRED);
+ BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+ EXPECT_EQ(1u, bitmaps.count(32));
+ EXPECT_EQ(32, bitmaps[32].width());
+ }
+ {
+ // The 32x32 icon should not be generated because no smaller icon exists.
+ std::map<int, SkBitmap> bitmaps;
+ bitmaps[48] = CreateSquareBitmapWithColor(48, SK_ColorRED);
+ BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+ EXPECT_EQ(0u, bitmaps.count(32));
+ }
+ {
+ // The 32x32 icon should not be generated with no base icons.
+ std::map<int, SkBitmap> bitmaps;
+ BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+ EXPECT_EQ(0u, bitmaps.count(32));
+ }
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index 5bc94af..9eacd19 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -12,13 +12,12 @@
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
#include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
-#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/bookmark_app_helper.h"
#include "chrome/browser/extensions/error_console/error_console.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/favicon_downloader.h"
#include "chrome/browser/extensions/image_loader.h"
#include "chrome/browser/extensions/page_action_controller.h"
#include "chrome/browser/extensions/script_executor.h"
@@ -64,10 +63,6 @@
#include "extensions/common/extension_resource.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/feature_switch.h"
-#include "skia/ext/image_operations.h"
-#include "skia/ext/platform_canvas.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/image/image.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
@@ -97,118 +92,6 @@ TabHelper::ScriptExecutionObserver::~ScriptExecutionObserver() {
tab_helper_->RemoveScriptExecutionObserver(this);
}
-// static
-std::map<int, SkBitmap> TabHelper::ConstrainBitmapsToSizes(
- const std::vector<SkBitmap>& bitmaps,
- const std::set<int>& sizes) {
- std::map<int, SkBitmap> output_bitmaps;
- std::map<int, SkBitmap> ordered_bitmaps;
- for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
- it != bitmaps.end(); ++it) {
- DCHECK(it->width() == it->height());
- ordered_bitmaps[it->width()] = *it;
- }
-
- std::set<int>::const_iterator sizes_it = sizes.begin();
- std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
- while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
- int size = *sizes_it;
- // Find the closest not-smaller bitmap.
- bitmaps_it = ordered_bitmaps.lower_bound(size);
- ++sizes_it;
- // Ensure the bitmap is valid and smaller than the next allowed size.
- if (bitmaps_it != ordered_bitmaps.end() &&
- (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
- // Resize the bitmap if it does not exactly match the desired size.
- output_bitmaps[size] = bitmaps_it->second.width() == size
- ? bitmaps_it->second
- : skia::ImageOperations::Resize(
- bitmaps_it->second, skia::ImageOperations::RESIZE_LANCZOS3,
- size, size);
- }
- }
- return output_bitmaps;
-}
-
-// static
-void TabHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
- int output_size) {
- std::map<int, SkBitmap>::const_iterator it =
- bitmaps->lower_bound(output_size);
- // Do nothing if there is no icon smaller than the desired size or there is
- // already an icon of |output_size|.
- if (it == bitmaps->begin() || bitmaps->count(output_size))
- return;
-
- --it;
- // This is the biggest icon smaller than |output_size|.
- const SkBitmap& base_icon = it->second;
-
- const size_t kBorderRadius = 5;
- const size_t kColorStripHeight = 3;
- const SkColor kBorderColor = 0xFFD5D5D5;
- const SkColor kBackgroundColor = 0xFFFFFFFF;
-
- // Create a separate canvas for the color strip.
- SkBitmap color_strip_bitmap;
- color_strip_bitmap.allocN32Pixels(output_size, output_size);
- SkCanvas color_strip_canvas(color_strip_bitmap);
- color_strip_canvas.clear(SK_ColorTRANSPARENT);
-
- // Draw a rounded rect of the |base_icon|'s dominant color.
- SkPaint color_strip_paint;
- color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
- color_strip_paint.setColor(
- color_utils::CalculateKMeanColorOfBitmap(base_icon));
- color_strip_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
- kBorderRadius,
- kBorderRadius,
- color_strip_paint);
-
- // Erase the top of the rounded rect to leave a color strip.
- SkPaint clear_paint;
- clear_paint.setColor(SK_ColorTRANSPARENT);
- clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- color_strip_canvas.drawRect(
- SkRect::MakeWH(output_size, output_size - kColorStripHeight),
- clear_paint);
-
- // Draw each element to an output canvas.
- SkBitmap generated_icon;
- generated_icon.allocN32Pixels(output_size, output_size);
- SkCanvas generated_icon_canvas(generated_icon);
- generated_icon_canvas.clear(SK_ColorTRANSPARENT);
-
- // Draw the background.
- SkPaint background_paint;
- background_paint.setColor(kBackgroundColor);
- background_paint.setFlags(SkPaint::kAntiAlias_Flag);
- generated_icon_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
- kBorderRadius,
- kBorderRadius,
- background_paint);
-
- // Draw the color strip.
- generated_icon_canvas.drawBitmap(color_strip_bitmap, 0, 0);
-
- // Draw the border.
- SkPaint border_paint;
- border_paint.setColor(kBorderColor);
- border_paint.setStyle(SkPaint::kStroke_Style);
- border_paint.setFlags(SkPaint::kAntiAlias_Flag);
- generated_icon_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
- kBorderRadius,
- kBorderRadius,
- border_paint);
-
- // Draw the centered base icon to the output canvas.
- generated_icon_canvas.drawBitmap(base_icon,
- (output_size - base_icon.width()) / 2,
- (output_size - base_icon.height()) / 2);
-
- generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
-}
-
TabHelper::TabHelper(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
extension_app_(NULL),
@@ -242,14 +125,6 @@ TabHelper::TabHelper(content::WebContents* web_contents)
content::NOTIFICATION_LOAD_STOP,
content::Source<NavigationController>(
&web_contents->GetController()));
-
- registrar_.Add(this,
- chrome::NOTIFICATION_CRX_INSTALLER_DONE,
- content::Source<CrxInstaller>(NULL));
-
- registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
- content::NotificationService::AllSources());
}
TabHelper::~TabHelper() {
@@ -329,6 +204,28 @@ SkBitmap* TabHelper::GetExtensionAppIcon() {
return &extension_app_icon_;
}
+void TabHelper::FinishCreateBookmarkApp(
+ const extensions::Extension* extension,
+ const WebApplicationInfo& web_app_info) {
+ pending_web_app_action_ = NONE;
+
+ // There was an error with downloading the icons or installing the app.
+ if (!extension)
+ return;
+
+#if defined(OS_CHROMEOS)
+ ChromeLauncherController::instance()->PinAppWithID(extension->id());
+#endif
+
+// Android does not implement browser_finder.cc.
+#if !defined(OS_ANDROID)
+ Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+ if (browser) {
+ browser->window()->ShowBookmarkAppBubble(web_app_info, extension->id());
+ }
+#endif
+}
+
void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) {
SetTabId(render_view_host);
}
@@ -405,115 +302,6 @@ bool TabHelper::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void TabHelper::CreateHostedApp() {
- // Add urls from the WebApplicationInfo.
- std::vector<GURL> web_app_info_icon_urls;
- for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
- web_app_info_.icons.begin();
- it != web_app_info_.icons.end(); ++it) {
- if (it->url.is_valid())
- web_app_info_icon_urls.push_back(it->url);
- }
-
- favicon_downloader_.reset(
- new FaviconDownloader(web_contents(),
- web_app_info_icon_urls,
- base::Bind(&TabHelper::FinishCreateHostedApp,
- base::Unretained(this))));
- favicon_downloader_->Start();
-}
-
-// TODO(calamity): Move hosted app generation into its own file.
-void TabHelper::FinishCreateHostedApp(
- bool success,
- const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
- // The tab has navigated away during the icon download. Cancel the hosted app
- // creation.
- if (!success) {
- favicon_downloader_.reset();
- return;
- }
-
- if (web_app_info_.app_url.is_empty())
- web_app_info_.app_url = web_contents()->GetURL();
-
- if (web_app_info_.title.empty())
- web_app_info_.title = web_contents()->GetTitle();
- if (web_app_info_.title.empty())
- web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
-
- // Add the downloaded icons. Extensions only allow certain icon sizes. First
- // populate icons that match the allowed sizes exactly and then downscale
- // remaining icons to the closest allowed size that doesn't yet have an icon.
- std::set<int> allowed_sizes(
- extension_misc::kExtensionIconSizes,
- extension_misc::kExtensionIconSizes +
- extension_misc::kNumExtensionIconSizes);
- std::vector<SkBitmap> downloaded_icons;
- for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
- map_it != bitmaps.end(); ++map_it) {
- for (std::vector<SkBitmap>::const_iterator bitmap_it =
- map_it->second.begin();
- bitmap_it != map_it->second.end(); ++bitmap_it) {
- if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
- continue;
-
- downloaded_icons.push_back(*bitmap_it);
- }
- }
-
- // If there are icons that don't match the accepted icon sizes, find the
- // closest bigger icon to the accepted sizes and resize the icon to it. An
- // icon will be resized and used for at most one size.
- std::map<int, SkBitmap> resized_bitmaps(
- TabHelper::ConstrainBitmapsToSizes(downloaded_icons,
- allowed_sizes));
-
- // Generate container icons from smaller icons.
- const int kIconSizesToGenerate[] = {
- extension_misc::EXTENSION_ICON_SMALL,
- extension_misc::EXTENSION_ICON_MEDIUM,
- };
- const std::set<int> generate_sizes(
- kIconSizesToGenerate,
- kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
-
- // Only generate icons if larger icons don't exist. This means the app
- // launcher and the taskbar will do their best downsizing large icons and
- // these container icons are only generated as a last resort against upscaling
- // a smaller icon.
- if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
- resized_bitmaps.end()) {
- // Generate these from biggest to smallest so we don't end up with
- // concentric container icons.
- for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
- it != generate_sizes.rend(); ++it) {
- TabHelper::GenerateContainerIcon(&resized_bitmaps, *it);
- }
- }
-
- // Populate a the icon data into the WebApplicationInfo we are using to
- // install the bookmark app.
- for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
- resized_bitmaps.begin();
- resized_bitmaps_it != resized_bitmaps.end(); ++resized_bitmaps_it) {
- WebApplicationInfo::IconInfo icon_info;
- icon_info.data = resized_bitmaps_it->second;
- icon_info.width = icon_info.data.width();
- icon_info.height = icon_info.data.height();
- web_app_info_.icons.push_back(icon_info);
- }
-
- // Install the app.
- Profile* profile =
- Profile::FromBrowserContext(web_contents()->GetBrowserContext());
- scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::CreateSilent(profile->GetExtensionService()));
- installer->set_error_on_unsupported_requirements(true);
- installer->InstallWebApp(web_app_info_);
- favicon_downloader_.reset();
-}
-
void TabHelper::DidCloneToNewWebContents(WebContents* old_web_contents,
WebContents* new_web_contents) {
// When the WebContents that this is attached to is cloned, give the new clone
@@ -544,7 +332,18 @@ void TabHelper::OnDidGetApplicationInfo(int32 page_id,
break;
}
case CREATE_HOSTED_APP: {
- CreateHostedApp();
+ if (web_app_info_.app_url.is_empty())
+ web_app_info_.app_url = web_contents()->GetURL();
+
+ if (web_app_info_.title.empty())
+ web_app_info_.title = web_contents()->GetTitle();
+ if (web_app_info_.title.empty())
+ web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
+
+ bookmark_app_helper_.reset(new BookmarkAppHelper(
+ profile_->GetExtensionService(), web_app_info_, web_contents()));
+ bookmark_app_helper_->Create(base::Bind(
+ &TabHelper::FinishCreateBookmarkApp, base::Unretained(this)));
break;
}
case UPDATE_SHORTCUT: {
@@ -745,37 +544,6 @@ void TabHelper::Observe(int type,
}
break;
}
- case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
- if (pending_web_app_action_ != CREATE_HOSTED_APP)
- return;
-
- pending_web_app_action_ = NONE;
-
- const Extension* extension =
- content::Details<const Extension>(details).ptr();
- if (!extension ||
- AppLaunchInfo::GetLaunchWebURL(extension) != web_app_info_.app_url)
- return;
-
-#if defined(OS_CHROMEOS)
- ChromeLauncherController::instance()->PinAppWithID(extension->id());
-#endif
-
- // Android does not implement browser_finder.cc.
-#if !defined(OS_ANDROID)
- Browser* browser =
- chrome::FindBrowserWithWebContents(web_contents());
- if (browser) {
- browser->window()->ShowBookmarkAppBubble(web_app_info_,
- extension->id());
- }
-#endif
- }
- case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
- if (pending_web_app_action_ == CREATE_HOSTED_APP)
- pending_web_app_action_ = NONE;
- break;
- }
}
}
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h
index bb30c76..42603de 100644
--- a/chrome/browser/extensions/tab_helper.h
+++ b/chrome/browser/extensions/tab_helper.h
@@ -35,6 +35,7 @@ class Image;
}
namespace extensions {
+class BookmarkAppHelper;
class Extension;
class LocationBarController;
class ScriptExecutor;
@@ -86,21 +87,6 @@ class TabHelper : public content::WebContentsObserver,
TabHelper* tab_helper_;
};
- // This finds the closest not-smaller bitmap in |bitmaps| for each size in
- // |sizes| and resizes it to that size. This returns a map of sizes to bitmaps
- // which contains only bitmaps of a size in |sizes| and at most one bitmap of
- // each size.
- static std::map<int, SkBitmap> ConstrainBitmapsToSizes(
- const std::vector<SkBitmap>& bitmaps,
- const std::set<int>& sizes);
-
- // Adds a square container icon of |output_size| pixels to |bitmaps| by
- // centering the biggest smaller icon in |bitmaps| and drawing a rounded
- // rectangle with strip of the that icon's dominant color at the bottom.
- // Does nothing if an icon of |output_size| already exists in |bitmaps|.
- static void GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
- int output_size);
-
virtual ~TabHelper();
void AddScriptExecutionObserver(ScriptExecutionObserver* observer) {
@@ -180,11 +166,9 @@ class TabHelper : public content::WebContentsObserver,
explicit TabHelper(content::WebContents* web_contents);
friend class content::WebContentsUserData<TabHelper>;
- // Creates a hosted app for the current tab. Requires the |web_app_info_| to
- // be populated.
- void CreateHostedApp();
- void FinishCreateHostedApp(
- bool success, const std::map<GURL, std::vector<SkBitmap> >& bitmaps);
+ // Displays UI for completion of creating a bookmark hosted app.
+ void FinishCreateBookmarkApp(const extensions::Extension* extension,
+ const WebApplicationInfo& web_app_info);
// content::WebContentsObserver overrides.
virtual void RenderViewCreated(
@@ -283,7 +267,7 @@ class TabHelper : public content::WebContentsObserver,
scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_;
- scoped_ptr<FaviconDownloader> favicon_downloader_;
+ scoped_ptr<BookmarkAppHelper> bookmark_app_helper_;
Profile* profile_;
diff --git a/chrome/browser/extensions/tab_helper_unittest.cc b/chrome/browser/extensions/tab_helper_unittest.cc
deleted file mode 100644
index 7169063..0000000
--- a/chrome/browser/extensions/tab_helper_unittest.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/tab_helper.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) {
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size, size);
- bitmap.allocPixels();
- bitmap.eraseColor(color);
- return bitmap;
-}
-
-void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) {
- // Obtain pixel lock to access pixels.
- SkAutoLockPixels lock(bitmap);
- EXPECT_EQ(color, bitmap.getColor(0, 0));
- EXPECT_EQ(size, bitmap.width());
- EXPECT_EQ(size, bitmap.height());
-}
-
-class TabHelperTest : public testing::Test {
- protected:
- TabHelperTest() {
- }
-
- virtual ~TabHelperTest() {
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TabHelperTest);
-};
-
-} // namespace
-
-TEST_F(TabHelperTest, ConstrainBitmapsToSizes) {
- std::set<int> desired_sizes;
- desired_sizes.insert(16);
- desired_sizes.insert(32);
- desired_sizes.insert(128);
- desired_sizes.insert(256);
-
- {
- std::vector<SkBitmap> bitmaps;
- bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED));
- bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN));
- bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE));
- bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW));
-
- std::map<int, SkBitmap> results(
- extensions::TabHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
-
- EXPECT_EQ(3u, results.size());
- ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED);
- ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN);
- ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW);
- }
- {
- std::vector<SkBitmap> bitmaps;
- bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED));
- bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN));
- bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE));
- bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW));
-
- std::map<int, SkBitmap> results(
- extensions::TabHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
-
- EXPECT_EQ(3u, results.size());
- ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW);
- ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE);
- ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED);
- }
-}
-
-TEST_F(TabHelperTest, GenerateIcons) {
- {
- // The 32x32 icon should be generated from the 16x16 icon.
- std::map<int, SkBitmap> bitmaps;
- bitmaps[16] = CreateSquareBitmapWithColor(16, SK_ColorRED);
- extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
- EXPECT_EQ(1u, bitmaps.count(32));
- EXPECT_EQ(32, bitmaps[32].width());
- }
- {
- // The 32x32 icon should not be generated because no smaller icon exists.
- std::map<int, SkBitmap> bitmaps;
- bitmaps[48] = CreateSquareBitmapWithColor(48, SK_ColorRED);
- extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
- EXPECT_EQ(0u, bitmaps.count(32));
- }
- {
- // The 32x32 icon should not be generated with no base icons.
- std::map<int, SkBitmap> bitmaps;
- extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
- EXPECT_EQ(0u, bitmaps.count(32));
- }
-}
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index a0b5081..c0119b0 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -609,6 +609,8 @@
'browser/extensions/blacklist_state_fetcher.h',
'browser/extensions/blob_reader.cc',
'browser/extensions/blob_reader.h',
+ 'browser/extensions/bookmark_app_helper.cc',
+ 'browser/extensions/bookmark_app_helper.h',
'browser/extensions/browser_action_test_util.h',
'browser/extensions/browser_context_keyed_service_factories.cc',
'browser/extensions/browser_context_keyed_service_factories.h',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index f5da7d0..a9d737b 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -917,6 +917,7 @@
'browser/extensions/app_sync_data_unittest.cc',
'browser/extensions/blacklist_unittest.cc',
'browser/extensions/blacklist_state_fetcher_unittest.cc',
+ 'browser/extensions/bookmark_app_helper_unittest.cc',
'browser/extensions/browser_permissions_policy_delegate_unittest.cc',
'browser/extensions/chrome_app_sorting_unittest.cc',
'browser/extensions/component_loader_unittest.cc',
@@ -960,7 +961,6 @@
'browser/extensions/policy_handlers_unittest.cc',
'browser/extensions/sandboxed_unpacker_unittest.cc',
'browser/extensions/standard_management_policy_provider_unittest.cc',
- 'browser/extensions/tab_helper_unittest.cc',
'browser/extensions/token_cache/token_cache_service_unittest.cc',
'browser/extensions/updater/extension_cache_fake.h',
'browser/extensions/updater/extension_cache_fake.cc',