Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / extensions / bookmark_app_bubble_view.cc
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/extensions/bookmark_app_bubble_view.h"
6
7 #include "base/strings/string16.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/app_icon_loader_impl.h"
10 #include "chrome/browser/extensions/bookmark_app_helper.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/launch_util.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "extensions/browser/extension_prefs.h"
16 #include "extensions/browser/extension_registry.h"
17 #include "extensions/browser/extension_system.h"
18 #include "extensions/browser/pref_names.h"
19 #include "extensions/browser/uninstall_reason.h"
20 #include "extensions/common/constants.h"
21 #include "grit/generated_resources.h"
22 #include "grit/theme_resources.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/events/keycodes/keyboard_codes.h"
26 #include "ui/views/controls/button/checkbox.h"
27 #include "ui/views/controls/button/label_button.h"
28 #include "ui/views/controls/image_view.h"
29 #include "ui/views/controls/label.h"
30 #include "ui/views/controls/textfield/textfield.h"
31 #include "ui/views/layout/grid_layout.h"
32 #include "ui/views/layout/layout_constants.h"
33 #include "ui/views/widget/widget.h"
34
35 using views::ColumnSet;
36 using views::GridLayout;
37
38 namespace {
39
40 // Minimum width of the the bubble.
41 const int kMinBubbleWidth = 300;
42 // Minimum width of the the textfield.
43 const int kMinTextfieldWidth = 200;
44 // Size of the icon.
45 const int kIconSize = extension_misc::EXTENSION_ICON_MEDIUM;
46
47 ExtensionService* GetExtensionService(Profile* profile) {
48   return extensions::ExtensionSystem::Get(profile)->extension_service();
49 }
50
51 }  // namespace
52
53 BookmarkAppBubbleView* BookmarkAppBubbleView::bookmark_app_bubble_ = NULL;
54
55 BookmarkAppBubbleView::~BookmarkAppBubbleView() {
56 }
57
58 // static
59 void BookmarkAppBubbleView::ShowBubble(views::View* anchor_view,
60                                        Profile* profile,
61                                        const WebApplicationInfo& web_app_info,
62                                        const std::string& extension_id) {
63   if (bookmark_app_bubble_ != NULL)
64     return;
65
66   bookmark_app_bubble_ = new BookmarkAppBubbleView(
67       anchor_view, profile, web_app_info, extension_id);
68   views::BubbleDelegateView::CreateBubble(bookmark_app_bubble_)->Show();
69   // Select the entire title textfield contents when the bubble is first shown.
70   bookmark_app_bubble_->title_tf_->SelectAll(true);
71   bookmark_app_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
72 }
73
74 BookmarkAppBubbleView::BookmarkAppBubbleView(
75     views::View* anchor_view,
76     Profile* profile,
77     const WebApplicationInfo& web_app_info,
78     const std::string& extension_id)
79     : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
80       profile_(profile),
81       web_app_info_(web_app_info),
82       extension_id_(extension_id),
83       add_button_(NULL),
84       cancel_button_(NULL),
85       open_as_tab_checkbox_(NULL),
86       title_tf_(NULL),
87       remove_app_(true),
88       app_icon_loader_(new extensions::AppIconLoaderImpl(profile,
89                                                          kIconSize,
90                                                          this)) {
91   const SkColor background_color = GetNativeTheme()->GetSystemColor(
92       ui::NativeTheme::kColorId_DialogBackground);
93   set_arrow(views::BubbleBorder::TOP_CENTER);
94   set_color(background_color);
95   set_background(views::Background::CreateSolidBackground(background_color));
96   set_margins(gfx::Insets(views::kPanelVertMargin, 0, 0, 0));
97 }
98
99 void BookmarkAppBubbleView::Init() {
100   views::Label* title_label = new views::Label(
101       l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_TITLE));
102   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
103   title_label->SetFontList(rb->GetFontList(ui::ResourceBundle::MediumFont));
104   title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
105
106   add_button_ =
107       new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_ADD));
108   add_button_->SetStyle(views::Button::STYLE_BUTTON);
109   add_button_->SetIsDefault(true);
110
111   cancel_button_ =
112       new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_CANCEL));
113   cancel_button_->SetStyle(views::Button::STYLE_BUTTON);
114
115   GridLayout* layout = new GridLayout(this);
116   SetLayoutManager(layout);
117
118   // Column sets used in the layout of the bubble.
119   enum ColumnSetID {
120     TITLE_COLUMN_SET_ID,
121     TITLE_TEXT_COLUMN_SET_ID,
122     CONTENT_COLUMN_SET_ID
123   };
124
125   // The column layout used for the title and checkbox.
126   ColumnSet* cs = layout->AddColumnSet(TITLE_COLUMN_SET_ID);
127   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
128   cs->AddColumn(
129       GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
130   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
131
132   // The column layout used for the icon and text box.
133   cs = layout->AddColumnSet(TITLE_TEXT_COLUMN_SET_ID);
134   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
135   cs->AddColumn(GridLayout::LEADING,
136                 GridLayout::CENTER,
137                 0,
138                 GridLayout::USE_PREF,
139                 0,
140                 0);
141   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
142   cs->AddColumn(GridLayout::FILL,
143                 GridLayout::CENTER,
144                 1,
145                 GridLayout::USE_PREF,
146                 0,
147                 kMinTextfieldWidth);
148   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
149
150   // The column layout used for the row with buttons.
151   cs = layout->AddColumnSet(CONTENT_COLUMN_SET_ID);
152   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
153   cs->AddColumn(
154       GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
155   cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
156   cs->AddColumn(
157       GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
158   cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
159   cs->AddColumn(
160       GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
161   cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
162
163   layout->StartRow(0, TITLE_COLUMN_SET_ID);
164   layout->AddView(title_label);
165   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
166
167   const extensions::Extension* extension =
168       extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
169           extension_id_, extensions::ExtensionRegistry::EVERYTHING);
170
171   layout->StartRow(0, TITLE_TEXT_COLUMN_SET_ID);
172   icon_image_view_ = new views::ImageView();
173   icon_image_view_->SetImageSize(gfx::Size(kIconSize, kIconSize));
174   layout->AddView(icon_image_view_);
175   app_icon_loader_->FetchImage(extension_id_);
176
177   title_tf_ = new views::Textfield();
178   title_tf_->SetText(extension ? base::UTF8ToUTF16(extension->name())
179                                : web_app_info_.title);
180   layout->AddView(title_tf_);
181   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
182
183   layout->StartRow(0, CONTENT_COLUMN_SET_ID);
184   open_as_tab_checkbox_ = new views::Checkbox(
185       l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB));
186   open_as_tab_checkbox_->SetChecked(
187       profile_->GetPrefs()->GetInteger(
188           extensions::pref_names::kBookmarkAppCreationLaunchType) ==
189               extensions::LAUNCH_TYPE_REGULAR);
190   layout->AddView(open_as_tab_checkbox_);
191   layout->AddView(add_button_);
192   layout->AddView(cancel_button_);
193   layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
194
195   AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
196 }
197
198 views::View* BookmarkAppBubbleView::GetInitiallyFocusedView() {
199   return title_tf_;
200 }
201
202 void BookmarkAppBubbleView::WindowClosing() {
203   // We have to reset |bookmark_app_bubble_| here, not in our destructor,
204   // because we'll be destroyed asynchronously and the shown state will be
205   // checked before then.
206   DCHECK_EQ(bookmark_app_bubble_, this);
207   bookmark_app_bubble_ = NULL;
208
209   if (remove_app_) {
210     GetExtensionService(profile_)
211         ->UninstallExtension(extension_id_,
212                              extensions::UNINSTALL_REASON_INSTALL_CANCELED,
213                              base::Bind(&base::DoNothing),
214                              NULL);
215   } else {
216     ApplyEdits();
217   }
218 }
219
220 bool BookmarkAppBubbleView::AcceleratorPressed(
221     const ui::Accelerator& accelerator) {
222   if (accelerator.key_code() == ui::VKEY_RETURN) {
223     HandleButtonPressed(add_button_);
224   }
225
226   return BubbleDelegateView::AcceleratorPressed(accelerator);
227 }
228
229 gfx::Size BookmarkAppBubbleView::GetMinimumSize() const {
230   gfx::Size size(views::BubbleDelegateView::GetPreferredSize());
231   size.SetToMax(gfx::Size(kMinBubbleWidth, 0));
232   return size;
233 }
234
235 void BookmarkAppBubbleView::ButtonPressed(views::Button* sender,
236                                           const ui::Event& event) {
237   HandleButtonPressed(sender);
238 }
239
240 void BookmarkAppBubbleView::SetAppImage(const std::string& id,
241                                         const gfx::ImageSkia& image) {
242   DCHECK_EQ(extension_id_, id);
243   icon_image_view_->SetImage(image);
244 }
245
246 void BookmarkAppBubbleView::HandleButtonPressed(views::Button* sender) {
247   // Unset |remove_app_| so we don't delete the bookmark after the window
248   // closes.
249   if (sender == add_button_)
250     remove_app_ = false;
251
252   GetWidget()->Close();
253 }
254
255 void BookmarkAppBubbleView::ApplyEdits() {
256   // Set the launch type based on the checkbox.
257   extensions::LaunchType launch_type = open_as_tab_checkbox_->checked()
258       ? extensions::LAUNCH_TYPE_REGULAR
259       : extensions::LAUNCH_TYPE_WINDOW;
260   profile_->GetPrefs()->SetInteger(
261           extensions::pref_names::kBookmarkAppCreationLaunchType, launch_type);
262   extensions::SetLaunchType(GetExtensionService(profile_),
263                             extension_id_,
264                             launch_type);
265
266   const extensions::Extension* extension =
267       extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
268           extension_id_, extensions::ExtensionRegistry::EVERYTHING);
269   if (extension && base::UTF8ToUTF16(extension->name()) == title_tf_->text())
270     return;
271
272   // Reinstall the app with an updated name.
273   WebApplicationInfo install_info(web_app_info_);
274   install_info.title = title_tf_->text();
275
276   extensions::CreateOrUpdateBookmarkApp(GetExtensionService(profile_),
277                                         install_info);
278 }