Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(313)

Side by Side Diff: chrome/browser/extensions/bookmark_app_helper.cc

Issue 899443002: Create bookmark apps at the end of the process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Feedback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/bookmark_app_helper.h" 5 #include "chrome/browser/extensions/bookmark_app_helper.h"
6 6
7 #include <cctype> 7 #include <cctype>
8 8
9 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/crx_installer.h" 12 #include "chrome/browser/extensions/crx_installer.h"
11 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/favicon_downloader.h" 14 #include "chrome/browser/extensions/favicon_downloader.h"
15 #include "chrome/browser/extensions/launch_util.h"
13 #include "chrome/browser/extensions/tab_helper.h" 16 #include "chrome/browser/extensions/tab_helper.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/app_list/app_list_service.h"
19 #include "chrome/browser/ui/app_list/app_list_util.h"
20 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/host_desktop.h"
14 #include "chrome/common/extensions/extension_constants.h" 23 #include "chrome/common/extensions/extension_constants.h"
15 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 24 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
25 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h" 27 #include "content/public/browser/notification_source.h"
18 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
29 #include "extensions/browser/extension_system.h"
19 #include "extensions/browser/image_loader.h" 30 #include "extensions/browser/image_loader.h"
20 #include "extensions/browser/notification_types.h" 31 #include "extensions/browser/notification_types.h"
32 #include "extensions/browser/pref_names.h"
21 #include "extensions/common/constants.h" 33 #include "extensions/common/constants.h"
22 #include "extensions/common/extension.h" 34 #include "extensions/common/extension.h"
23 #include "extensions/common/manifest_handlers/icons_handler.h" 35 #include "extensions/common/manifest_handlers/icons_handler.h"
24 #include "extensions/common/url_pattern.h" 36 #include "extensions/common/url_pattern.h"
25 #include "grit/platform_locale_settings.h" 37 #include "grit/platform_locale_settings.h"
26 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 38 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
27 #include "skia/ext/image_operations.h" 39 #include "skia/ext/image_operations.h"
28 #include "skia/ext/platform_canvas.h" 40 #include "skia/ext/platform_canvas.h"
29 #include "third_party/skia/include/core/SkBitmap.h" 41 #include "third_party/skia/include/core/SkBitmap.h"
30 #include "ui/base/l10n/l10n_util.h" 42 #include "ui/base/l10n/l10n_util.h"
31 #include "ui/gfx/canvas.h" 43 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/color_analysis.h" 44 #include "ui/gfx/color_analysis.h"
33 #include "ui/gfx/color_utils.h" 45 #include "ui/gfx/color_utils.h"
34 #include "ui/gfx/font.h" 46 #include "ui/gfx/font.h"
35 #include "ui/gfx/font_list.h" 47 #include "ui/gfx/font_list.h"
36 #include "ui/gfx/geometry/rect.h" 48 #include "ui/gfx/geometry/rect.h"
37 #include "ui/gfx/image/canvas_image_source.h" 49 #include "ui/gfx/image/canvas_image_source.h"
38 #include "ui/gfx/image/image.h" 50 #include "ui/gfx/image/image.h"
39 #include "ui/gfx/image/image_family.h" 51 #include "ui/gfx/image/image_family.h"
40 52
53 #if defined(OS_MACOSX)
54 #include "base/command_line.h"
55 #include "chrome/browser/web_applications/web_app_mac.h"
56 #include "chrome/common/chrome_switches.h"
57 #endif
58
59 #if defined(USE_ASH)
60 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
61 #endif
62
41 namespace { 63 namespace {
42 64
43 // Overlays a shortcut icon over the bottom left corner of a given image. 65 // Overlays a shortcut icon over the bottom left corner of a given image.
44 class GeneratedIconImageSource : public gfx::CanvasImageSource { 66 class GeneratedIconImageSource : public gfx::CanvasImageSource {
45 public: 67 public:
46 explicit GeneratedIconImageSource(char letter, SkColor color, int output_size) 68 explicit GeneratedIconImageSource(char letter, SkColor color, int output_size)
47 : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false), 69 : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false),
48 letter_(letter), 70 letter_(letter),
49 color_(color), 71 color_(color),
50 output_size_(output_size) {} 72 output_size_(output_size) {}
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 // Do nothing if there is already an icon of |output_size|. 233 // Do nothing if there is already an icon of |output_size|.
212 if (bitmaps->count(output_size)) 234 if (bitmaps->count(output_size))
213 return; 235 return;
214 236
215 gfx::ImageSkia icon_image( 237 gfx::ImageSkia icon_image(
216 new GeneratedIconImageSource(letter, color, output_size), 238 new GeneratedIconImageSource(letter, color, output_size),
217 gfx::Size(output_size, output_size)); 239 gfx::Size(output_size, output_size));
218 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]); 240 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]);
219 } 241 }
220 242
221 BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service, 243 BookmarkAppHelper::BookmarkAppHelper(Profile* profile,
222 WebApplicationInfo web_app_info, 244 WebApplicationInfo web_app_info,
223 content::WebContents* contents) 245 content::WebContents* contents)
224 : contents_(contents), 246 : profile_(profile),
247 contents_(contents),
225 web_app_info_(web_app_info), 248 web_app_info_(web_app_info),
226 crx_installer_(extensions::CrxInstaller::CreateSilent(service)) { 249 crx_installer_(extensions::CrxInstaller::CreateSilent(
250 ExtensionSystem::Get(profile)->extension_service())) {
227 registrar_.Add(this, 251 registrar_.Add(this,
228 extensions::NOTIFICATION_CRX_INSTALLER_DONE, 252 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
229 content::Source<CrxInstaller>(crx_installer_.get())); 253 content::Source<CrxInstaller>(crx_installer_.get()));
230 254
231 registrar_.Add(this, 255 registrar_.Add(this,
232 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR, 256 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
233 content::Source<CrxInstaller>(crx_installer_.get())); 257 content::Source<CrxInstaller>(crx_installer_.get()));
234 258
235 crx_installer_->set_error_on_unsupported_requirements(true); 259 crx_installer_->set_error_on_unsupported_requirements(true);
236 } 260 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 favicon_downloader_->Start(); 296 favicon_downloader_->Start();
273 } 297 }
274 298
275 void BookmarkAppHelper::OnIconsDownloaded( 299 void BookmarkAppHelper::OnIconsDownloaded(
276 bool success, 300 bool success,
277 const std::map<GURL, std::vector<SkBitmap> >& bitmaps) { 301 const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
278 // The tab has navigated away during the icon download. Cancel the bookmark 302 // The tab has navigated away during the icon download. Cancel the bookmark
279 // app creation. 303 // app creation.
280 if (!success) { 304 if (!success) {
281 favicon_downloader_.reset(); 305 favicon_downloader_.reset();
282 callback_.Run(NULL, web_app_info_); 306 callback_.Run(nullptr, web_app_info_);
283 return; 307 return;
284 } 308 }
285 309
286 std::vector<SkBitmap> downloaded_icons; 310 std::vector<SkBitmap> downloaded_icons;
287 for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin(); 311 for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
288 map_it != bitmaps.end(); 312 map_it != bitmaps.end();
289 ++map_it) { 313 ++map_it) {
290 for (std::vector<SkBitmap>::const_iterator bitmap_it = 314 for (std::vector<SkBitmap>::const_iterator bitmap_it =
291 map_it->second.begin(); 315 map_it->second.begin();
292 bitmap_it != map_it->second.end(); 316 bitmap_it != map_it->second.end();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 352
329 std::map<int, SkBitmap> generated_icons; 353 std::map<int, SkBitmap> generated_icons;
330 // Icons are always generated, replacing the icons that were downloaded. This 354 // Icons are always generated, replacing the icons that were downloaded. This
331 // is done so that the icons are consistent across machines. 355 // is done so that the icons are consistent across machines.
332 // TODO(benwells): Use blob sync once it is available to sync the downloaded 356 // TODO(benwells): Use blob sync once it is available to sync the downloaded
333 // icons, and then only generate when there are required sizes missing. 357 // icons, and then only generate when there are required sizes missing.
334 GenerateIcons(generate_sizes, web_app_info_.app_url, 358 GenerateIcons(generate_sizes, web_app_info_.app_url,
335 web_app_info_.generated_icon_color, &generated_icons); 359 web_app_info_.generated_icon_color, &generated_icons);
336 360
337 ReplaceWebAppIcons(generated_icons, &web_app_info_); 361 ReplaceWebAppIcons(generated_icons, &web_app_info_);
362 favicon_downloader_.reset();
338 363
339 // Install the app. 364 if (!contents_) {
340 crx_installer_->InstallWebApp(web_app_info_); 365 // The web contents can be null in tests.
341 favicon_downloader_.reset(); 366 OnBubbleCompleted(true, web_app_info_);
367 return;
368 }
369
370 Browser* browser = chrome::FindBrowserWithWebContents(contents_);
371 if (!browser) {
372 // The browser can be null in tests.
373 OnBubbleCompleted(true, web_app_info_);
374 return;
375 }
376 browser->window()->ShowBookmarkAppBubble(
377 web_app_info_, base::Bind(&BookmarkAppHelper::OnBubbleCompleted,
378 base::Unretained(this)));
379 }
380
381 void BookmarkAppHelper::OnBubbleCompleted(
382 bool user_accepted,
383 const WebApplicationInfo& web_app_info) {
384 if (user_accepted) {
385 web_app_info_ = web_app_info;
386 crx_installer_->InstallWebApp(web_app_info_);
387 } else {
388 callback_.Run(nullptr, web_app_info_);
389 }
390 }
391
392 void BookmarkAppHelper::FinishInstallation(const Extension* extension) {
393 // Set the default 'open as' preference for use next time the dialog is
394 // shown.
395 extensions::LaunchType launch_type = web_app_info_.open_as_window
396 ? extensions::LAUNCH_TYPE_WINDOW
397 : extensions::LAUNCH_TYPE_REGULAR;
398 profile_->GetPrefs()->SetInteger(
399 extensions::pref_names::kBookmarkAppCreationLaunchType, launch_type);
400
401 // Set the launcher type for the app.
402 extensions::SetLaunchType(profile_, extension->id(), launch_type);
403
404 if (!contents_) {
405 // The web contents can be null in tests.
406 callback_.Run(extension, web_app_info_);
407 return;
408 }
409
410 Browser* browser = chrome::FindBrowserWithWebContents(contents_);
411 if (!browser) {
412 // The browser can be null in tests.
413 callback_.Run(extension, web_app_info_);
414 return;
415 }
416
417 // Pin the app to the shelf on Ash.
418 chrome::HostDesktopType desktop = browser->host_desktop_type();
419 #if defined(USE_ASH)
420 if (desktop == chrome::HOST_DESKTOP_TYPE_ASH)
421 ChromeLauncherController::instance()->PinAppWithID(extension->id());
422 #endif
423
424 // Show the newly installed app in the app launcher, in finder (on Mac) or
425 // chrome://apps.
426 Profile* current_profile = profile_->GetOriginalProfile();
427 if (IsAppLauncherEnabled()) {
428 AppListService::Get(desktop)
429 ->ShowForAppInstall(current_profile, extension->id(), false);
430 #if defined(OS_MACOSX)
431 } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
432 switches::kEnableHostedAppShimCreation)) {
433 web_app::RevealAppShimInFinderForApp(profile_, extension);
434 #endif
435 } else {
436 chrome::NavigateParams params(current_profile,
437 GURL(chrome::kChromeUIAppsURL),
438 ui::PAGE_TRANSITION_LINK);
439 params.disposition = SINGLETON_TAB;
440 chrome::Navigate(&params);
441
442 content::NotificationService::current()->Notify(
443 chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
444 content::Source<content::WebContents>(params.target_contents),
445 content::Details<const std::string>(&extension->id()));
446 }
447
448 callback_.Run(extension, web_app_info_);
342 } 449 }
343 450
344 void BookmarkAppHelper::Observe(int type, 451 void BookmarkAppHelper::Observe(int type,
345 const content::NotificationSource& source, 452 const content::NotificationSource& source,
346 const content::NotificationDetails& details) { 453 const content::NotificationDetails& details) {
347 switch (type) { 454 switch (type) {
348 case extensions::NOTIFICATION_CRX_INSTALLER_DONE: { 455 case extensions::NOTIFICATION_CRX_INSTALLER_DONE: {
349 const Extension* extension = 456 const Extension* extension =
350 content::Details<const Extension>(details).ptr(); 457 content::Details<const Extension>(details).ptr();
351 DCHECK(extension); 458 DCHECK(extension);
352 DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(extension), 459 DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(extension),
353 web_app_info_.app_url); 460 web_app_info_.app_url);
354 callback_.Run(extension, web_app_info_); 461 FinishInstallation(extension);
355 break; 462 break;
356 } 463 }
357 case extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR: 464 case extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR:
358 callback_.Run(NULL, web_app_info_); 465 callback_.Run(nullptr, web_app_info_);
359 break; 466 break;
360 default: 467 default:
361 NOTREACHED(); 468 NOTREACHED();
362 break; 469 break;
363 } 470 }
364 } 471 }
365 472
366 void CreateOrUpdateBookmarkApp(ExtensionService* service, 473 void CreateOrUpdateBookmarkApp(ExtensionService* service,
367 WebApplicationInfo* web_app_info) { 474 WebApplicationInfo* web_app_info) {
368 scoped_refptr<extensions::CrxInstaller> installer( 475 scoped_refptr<extensions::CrxInstaller> installer(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback)); 518 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback));
412 } 519 }
413 520
414 bool IsValidBookmarkAppUrl(const GURL& url) { 521 bool IsValidBookmarkAppUrl(const GURL& url) {
415 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes); 522 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes);
416 origin_only_pattern.SetMatchAllURLs(true); 523 origin_only_pattern.SetMatchAllURLs(true);
417 return url.is_valid() && origin_only_pattern.MatchesURL(url); 524 return url.is_valid() && origin_only_pattern.MatchesURL(url);
418 } 525 }
419 526
420 } // namespace extensions 527 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698