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
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h"
6
7#include "ash/shelf/shelf_delegate.h"
8#include "ash/shell.h"
9#include "chrome/browser/extensions/extension_service.h"
10#include "chrome/browser/profiles/profile.h"
11#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
12#include "chrome/browser/ui/browser_dialogs.h"
13#include "chrome/browser/ui/host_desktop.h"
14#include "chrome/common/extensions/extension_constants.h"
15#include "chrome/grit/generated_resources.h"
16#include "extensions/browser/extension_system.h"
17#include "extensions/browser/management_policy.h"
18#include "extensions/browser/uninstall_reason.h"
19#include "extensions/common/extension.h"
20#include "ui/base/l10n/l10n_util.h"
21#include "ui/events/event.h"
22#include "ui/views/controls/button/label_button.h"
23#include "ui/views/layout/box_layout.h"
24#include "ui/views/layout/layout_constants.h"
25#include "ui/views/view.h"
26#include "ui/views/widget/widget.h"
27
28AppInfoFooterPanel::AppInfoFooterPanel(gfx::NativeWindow parent_window,
29                                       Profile* profile,
30                                       const extensions::Extension* app)
31    : AppInfoPanel(profile, app),
32      parent_window_(parent_window),
33      create_shortcuts_button_(NULL),
34      pin_to_shelf_button_(NULL),
35      unpin_from_shelf_button_(NULL),
36      remove_button_(NULL),
37      weak_ptr_factory_(this) {
38  CreateButtons();
39
40  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
41                                        views::kButtonHEdgeMargin,
42                                        views::kButtonVEdgeMargin,
43                                        views::kRelatedButtonHSpacing));
44
45  LayoutButtons();
46}
47
48AppInfoFooterPanel::~AppInfoFooterPanel() {
49}
50
51void AppInfoFooterPanel::CreateButtons() {
52  if (CanCreateShortcuts()) {
53    create_shortcuts_button_ = new views::LabelButton(
54        this,
55        l10n_util::GetStringUTF16(
56            IDS_APPLICATION_INFO_CREATE_SHORTCUTS_BUTTON_TEXT));
57    create_shortcuts_button_->SetStyle(views::Button::STYLE_BUTTON);
58  }
59
60  if (CanSetPinnedToShelf()) {
61    pin_to_shelf_button_ = new views::LabelButton(
62        this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN));
63    pin_to_shelf_button_->SetStyle(views::Button::STYLE_BUTTON);
64    unpin_from_shelf_button_ = new views::LabelButton(
65        this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN));
66    unpin_from_shelf_button_->SetStyle(views::Button::STYLE_BUTTON);
67  }
68
69  if (CanUninstallApp()) {
70    remove_button_ = new views::LabelButton(
71        this,
72        l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT));
73    remove_button_->SetStyle(views::Button::STYLE_BUTTON);
74  }
75}
76
77void AppInfoFooterPanel::LayoutButtons() {
78  if (create_shortcuts_button_)
79    AddChildView(create_shortcuts_button_);
80
81  if (pin_to_shelf_button_)
82    AddChildView(pin_to_shelf_button_);
83  if (unpin_from_shelf_button_)
84    AddChildView(unpin_from_shelf_button_);
85  UpdatePinButtons();
86
87  if (remove_button_)
88    AddChildView(remove_button_);
89}
90
91void AppInfoFooterPanel::UpdatePinButtons() {
92  if (pin_to_shelf_button_ && unpin_from_shelf_button_) {
93    bool is_pinned =
94        !ash::Shell::GetInstance()->GetShelfDelegate()->IsAppPinned(app_->id());
95    pin_to_shelf_button_->SetVisible(is_pinned);
96    unpin_from_shelf_button_->SetVisible(!is_pinned);
97  }
98}
99
100void AppInfoFooterPanel::ButtonPressed(views::Button* sender,
101                                       const ui::Event& event) {
102  if (sender == create_shortcuts_button_) {
103    CreateShortcuts();
104  } else if (sender == pin_to_shelf_button_) {
105    SetPinnedToShelf(true);
106  } else if (sender == unpin_from_shelf_button_) {
107    SetPinnedToShelf(false);
108  } else if (sender == remove_button_) {
109    UninstallApp();
110  } else {
111    NOTREACHED();
112  }
113}
114
115void AppInfoFooterPanel::ExtensionUninstallAccepted() {
116  ExtensionService* service =
117      extensions::ExtensionSystem::Get(profile_)->extension_service();
118  service->UninstallExtension(app_->id(),
119                              extensions::UNINSTALL_REASON_USER_INITIATED,
120                              base::Bind(&base::DoNothing),
121                              NULL);
122
123  // Close the App Info dialog as well (which will free the dialog too).
124  GetWidget()->Close();
125}
126
127void AppInfoFooterPanel::ExtensionUninstallCanceled() {
128  extension_uninstall_dialog_.reset();
129}
130
131void AppInfoFooterPanel::CreateShortcuts() {
132  DCHECK(CanCreateShortcuts());
133  chrome::ShowCreateChromeAppShortcutsDialog(GetWidget()->GetNativeWindow(),
134                                             profile_,
135                                             app_,
136                                             base::Callback<void(bool)>());
137}
138
139bool AppInfoFooterPanel::CanCreateShortcuts() const {
140  // Ash platforms can't create shortcuts.
141  return (chrome::GetHostDesktopTypeForNativeWindow(parent_window_) !=
142          chrome::HOST_DESKTOP_TYPE_ASH);
143}
144
145void AppInfoFooterPanel::SetPinnedToShelf(bool value) {
146  DCHECK(CanSetPinnedToShelf());
147  ash::ShelfDelegate* shelf_delegate =
148      ash::Shell::GetInstance()->GetShelfDelegate();
149  DCHECK(shelf_delegate);
150  if (value)
151    shelf_delegate->PinAppWithID(app_->id());
152  else
153    shelf_delegate->UnpinAppWithID(app_->id());
154
155  UpdatePinButtons();
156  Layout();
157}
158
159bool AppInfoFooterPanel::CanSetPinnedToShelf() const {
160  // Non-Ash platforms don't have a shelf.
161  if (chrome::GetHostDesktopTypeForNativeWindow(parent_window_) !=
162      chrome::HOST_DESKTOP_TYPE_ASH) {
163    return false;
164  }
165
166  // The Chrome app can't be unpinned.
167  return app_->id() != extension_misc::kChromeAppId &&
168         ash::Shell::GetInstance()->GetShelfDelegate()->CanPin();
169}
170
171void AppInfoFooterPanel::UninstallApp() {
172  DCHECK(CanUninstallApp());
173  extension_uninstall_dialog_.reset(
174      extensions::ExtensionUninstallDialog::Create(
175          profile_, GetWidget()->GetNativeWindow(), this));
176  extension_uninstall_dialog_->ConfirmUninstall(app_);
177}
178
179bool AppInfoFooterPanel::CanUninstallApp() const {
180  return extensions::ExtensionSystem::Get(profile_)
181      ->management_policy()
182      ->UserMayModifySettings(app_, NULL);
183}
184