summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/app_shortcut_manager.cc
blob: bec3e3dd46ae409e55146ead001871c40e20054e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (c) 2012 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/app_shortcut_manager.h"

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_resource.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "grit/theme_resources.h"
#include "skia/ext/image_operations.h"
#include "ui/base/resource/resource_bundle.h"

namespace {
// Allow tests to disable shortcut creation, to prevent developers' desktops
// becoming overrun with shortcuts.
bool disable_shortcut_creation_for_tests = false;

#if defined(OS_MACOSX)
const int kDesiredSizes[] = {16, 32, 128, 256, 512};
#else
const int kDesiredSizes[] = {32};
#endif
}  // namespace

AppShortcutManager::AppShortcutManager(Profile* profile)
    : profile_(profile),
      tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
                 content::Source<Profile>(profile_));
}

void AppShortcutManager::OnImageLoaded(const gfx::Image& image,
                                       const std::string& extension_id,
                                       int index) {
  // If the image failed to load (e.g. if the resource being loaded was empty)
  // use the standard application icon.
  if (image.IsEmpty()) {
    gfx::Image default_icon =
        ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON);
    int size = kDesiredSizes[arraysize(kDesiredSizes) - 1];
    SkBitmap bmp = skia::ImageOperations::Resize(
          *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
          size, size);
    shortcut_info_.favicon = gfx::Image(bmp);
  } else {
    shortcut_info_.favicon = image;
  }

  web_app::CreateShortcut(profile_->GetPath(), shortcut_info_);
}

void AppShortcutManager::Observe(int type,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  DCHECK(type == chrome::NOTIFICATION_EXTENSION_INSTALLED);
  const Extension* extension = content::Details<const Extension>(details).ptr();
  if (!disable_shortcut_creation_for_tests && extension->is_platform_app() &&
      extension->location() != Extension::LOAD)
    InstallApplicationShortcuts(extension);
}

// static
void AppShortcutManager::SetShortcutCreationDisabledForTesting(bool disabled) {
  disable_shortcut_creation_for_tests = disabled;
}

void AppShortcutManager::InstallApplicationShortcuts(
    const Extension* extension) {
#if defined(OS_MACOSX)
  // TODO(sail): For now only install shortcuts if enable platform apps is true.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnablePlatformApps)) {
    return;
  }
#endif

  shortcut_info_.extension_id = extension->id();
  shortcut_info_.url = GURL(extension->launch_web_url());
  shortcut_info_.title = UTF8ToUTF16(extension->name());
  shortcut_info_.description = UTF8ToUTF16(extension->description());
  shortcut_info_.extension_path = extension->path();
  shortcut_info_.is_platform_app = extension->is_platform_app();
  shortcut_info_.create_in_applications_menu = true;
  shortcut_info_.create_in_quick_launch_bar = true;
  shortcut_info_.create_on_desktop = true;

  std::vector<ImageLoadingTracker::ImageInfo> info_list;
  for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) {
    int size = kDesiredSizes[i];
    ExtensionResource resource = extension->GetIconResource(
        size, ExtensionIconSet::MATCH_EXACTLY);
    if (!resource.empty()) {
      info_list.push_back(
          ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size)));
    }
  }

  if (info_list.empty()) {
    size_t i = arraysize(kDesiredSizes) - 1;
    int size = kDesiredSizes[i];

    // If there is no icon at the desired sizes, we will resize what we can get.
    // Making a large icon smaller is prefered to making a small icon larger, so
    // look for a larger icon first:
    ExtensionResource resource = extension->GetIconResource(
        size, ExtensionIconSet::MATCH_BIGGER);
    if (resource.empty()) {
      resource = extension->GetIconResource(
          size, ExtensionIconSet::MATCH_SMALLER);
    }
    info_list.push_back(
        ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size)));
  }

  // |icon_resources| may still be empty at this point, in which case LoadImage
  // will call the OnImageLoaded callback with an empty image and exit
  // immediately.
  tracker_.LoadImages(extension, info_list, ImageLoadingTracker::DONT_CACHE);
}