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

Side by Side Diff: chrome/browser/ui/views/extensions/bookmark_app_bubble_view.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/ui/views/extensions/bookmark_app_bubble_view.h" 5 #include "chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h"
6 6
7 #include "base/strings/string16.h" 7 #include "base/strings/string16.h"
8 #include "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/app_icon_loader_impl.h"
11 #include "chrome/browser/extensions/bookmark_app_helper.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/launch_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/app_list/app_list_service.h"
16 #include "chrome/browser/ui/app_list/app_list_util.h"
17 #include "chrome/browser/ui/browser_navigator.h"
18 #include "chrome/browser/ui/host_desktop.h"
19 #include "chrome/common/extensions/extension_constants.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/grit/generated_resources.h" 9 #include "chrome/grit/generated_resources.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/web_contents.h" 10 #include "content/public/browser/web_contents.h"
24 #include "extensions/browser/extension_prefs.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/browser/pref_names.h"
28 #include "extensions/browser/uninstall_reason.h"
29 #include "extensions/common/constants.h" 11 #include "extensions/common/constants.h"
30 #include "ui/base/l10n/l10n_util.h" 12 #include "ui/base/l10n/l10n_util.h"
31 #include "ui/base/resource/resource_bundle.h" 13 #include "ui/base/resource/resource_bundle.h"
32 #include "ui/events/keycodes/keyboard_codes.h" 14 #include "ui/events/keycodes/keyboard_codes.h"
15 #include "ui/gfx/geometry/safe_integer_conversions.h"
16 #include "ui/gfx/image/image_skia.h"
17 #include "ui/gfx/image/image_skia_source.h"
33 #include "ui/views/controls/button/checkbox.h" 18 #include "ui/views/controls/button/checkbox.h"
34 #include "ui/views/controls/button/label_button.h" 19 #include "ui/views/controls/button/label_button.h"
35 #include "ui/views/controls/image_view.h" 20 #include "ui/views/controls/image_view.h"
36 #include "ui/views/controls/label.h" 21 #include "ui/views/controls/label.h"
37 #include "ui/views/controls/textfield/textfield.h" 22 #include "ui/views/controls/textfield/textfield.h"
38 #include "ui/views/layout/grid_layout.h" 23 #include "ui/views/layout/grid_layout.h"
39 #include "ui/views/layout/layout_constants.h" 24 #include "ui/views/layout/layout_constants.h"
40 #include "ui/views/widget/widget.h" 25 #include "ui/views/widget/widget.h"
41 26
42 using views::ColumnSet; 27 using views::ColumnSet;
43 using views::GridLayout; 28 using views::GridLayout;
44 29
45 namespace { 30 namespace {
46 31
47 // Minimum width of the the bubble. 32 // Minimum width of the the bubble.
48 const int kMinBubbleWidth = 300; 33 const int kMinBubbleWidth = 300;
49 // Minimum width of the the textfield. 34 // Minimum width of the the textfield.
50 const int kMinTextfieldWidth = 200; 35 const int kMinTextfieldWidth = 200;
51 // Size of the icon. 36 // Size of the icon.
52 const int kIconSize = extension_misc::EXTENSION_ICON_MEDIUM; 37 const int kIconSize = extension_misc::EXTENSION_ICON_MEDIUM;
53 38
54 ExtensionService* GetExtensionService(Profile* profile) { 39 class WebAppInfoImageSource : public gfx::ImageSkiaSource {
55 return extensions::ExtensionSystem::Get(profile)->extension_service(); 40 public:
56 } 41 WebAppInfoImageSource(int dip_size, const WebApplicationInfo& info)
42 : dip_size_(dip_size), info_(info) {}
43 ~WebAppInfoImageSource() override {}
44
45 private:
46 gfx::ImageSkiaRep GetImageForScale(float scale) override {
47 int size = gfx::ClampToInt(dip_size_ * scale);
48 for (const auto& icon_info : info_.icons) {
49 if (icon_info.width == size) {
50 return gfx::ImageSkiaRep(icon_info.data, scale);
51 }
52 }
53 return gfx::ImageSkiaRep();
54 }
55
56 int dip_size_;
57 WebApplicationInfo info_;
58 };
57 59
58 } // namespace 60 } // namespace
59 61
60 BookmarkAppBubbleView* BookmarkAppBubbleView::bookmark_app_bubble_ = NULL;
61
62 BookmarkAppBubbleView::~BookmarkAppBubbleView() { 62 BookmarkAppBubbleView::~BookmarkAppBubbleView() {
63 } 63 }
64 64
65 // static 65 // static
66 void BookmarkAppBubbleView::ShowBubble(views::View* anchor_view, 66 void BookmarkAppBubbleView::ShowBubble(
67 Profile* profile, 67 views::View* anchor_view,
68 const WebApplicationInfo& web_app_info, 68 const WebApplicationInfo& web_app_info,
69 const std::string& extension_id) { 69 const BrowserWindow::ShowBookmarkAppBubbleCallback& callback) {
70 if (bookmark_app_bubble_ != NULL) 70 // |bookmark_app_bubble| becomes owned by the BubbleDelegateView through the
71 return; 71 // views system, and is freed when the BubbleDelegateView is closed and
72 72 // subsequently destroyed.
73 bookmark_app_bubble_ = new BookmarkAppBubbleView( 73 BookmarkAppBubbleView* bookmark_app_bubble =
74 anchor_view, profile, web_app_info, extension_id); 74 new BookmarkAppBubbleView(anchor_view, web_app_info, callback);
75 views::BubbleDelegateView::CreateBubble(bookmark_app_bubble_)->Show(); 75 views::BubbleDelegateView::CreateBubble(bookmark_app_bubble)->Show();
76 // Select the entire title textfield contents when the bubble is first shown. 76 // Select the entire title textfield contents when the bubble is first shown.
77 bookmark_app_bubble_->title_tf_->SelectAll(true); 77 bookmark_app_bubble->title_tf_->SelectAll(true);
78 bookmark_app_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); 78 bookmark_app_bubble->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
79 } 79 }
80 80
81 BookmarkAppBubbleView::BookmarkAppBubbleView( 81 BookmarkAppBubbleView::BookmarkAppBubbleView(
82 views::View* anchor_view, 82 views::View* anchor_view,
83 Profile* profile,
84 const WebApplicationInfo& web_app_info, 83 const WebApplicationInfo& web_app_info,
85 const std::string& extension_id) 84 const BrowserWindow::ShowBookmarkAppBubbleCallback& callback)
86 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), 85 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
87 profile_(profile),
88 web_app_info_(web_app_info), 86 web_app_info_(web_app_info),
89 extension_id_(extension_id), 87 user_accepted_(false),
88 callback_(callback),
90 add_button_(NULL), 89 add_button_(NULL),
91 cancel_button_(NULL), 90 cancel_button_(NULL),
92 open_as_window_checkbox_(NULL), 91 open_as_window_checkbox_(NULL),
93 title_tf_(NULL), 92 title_tf_(NULL) {
94 remove_app_(true),
95 app_icon_loader_(new extensions::AppIconLoaderImpl(profile,
96 kIconSize,
97 this)) {
98 const SkColor background_color = GetNativeTheme()->GetSystemColor( 93 const SkColor background_color = GetNativeTheme()->GetSystemColor(
99 ui::NativeTheme::kColorId_DialogBackground); 94 ui::NativeTheme::kColorId_DialogBackground);
100 set_arrow(views::BubbleBorder::TOP_CENTER); 95 set_arrow(views::BubbleBorder::TOP_CENTER);
101 set_color(background_color); 96 set_color(background_color);
102 set_background(views::Background::CreateSolidBackground(background_color)); 97 set_background(views::Background::CreateSolidBackground(background_color));
103 set_margins(gfx::Insets(views::kPanelVertMargin, 0, 0, 0)); 98 set_margins(gfx::Insets(views::kPanelVertMargin, 0, 0, 0));
104 } 99 }
105 100
106 void BookmarkAppBubbleView::Init() { 101 void BookmarkAppBubbleView::Init() {
107 views::Label* title_label = new views::Label( 102 views::Label* title_label = new views::Label(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); 159 GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
165 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 160 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
166 cs->AddColumn( 161 cs->AddColumn(
167 GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); 162 GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
168 cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew); 163 cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
169 164
170 layout->StartRow(0, TITLE_COLUMN_SET_ID); 165 layout->StartRow(0, TITLE_COLUMN_SET_ID);
171 layout->AddView(title_label); 166 layout->AddView(title_label);
172 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 167 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
173 168
174 const extensions::Extension* extension =
175 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
176 extension_id_, extensions::ExtensionRegistry::EVERYTHING);
177
178 layout->StartRow(0, TITLE_TEXT_COLUMN_SET_ID); 169 layout->StartRow(0, TITLE_TEXT_COLUMN_SET_ID);
179 icon_image_view_ = new views::ImageView(); 170 icon_image_view_ = new views::ImageView();
180 icon_image_view_->SetImageSize(gfx::Size(kIconSize, kIconSize)); 171
172 gfx::Size image_size(kIconSize, kIconSize);
173 gfx::ImageSkia image(new WebAppInfoImageSource(kIconSize, web_app_info_),
174 image_size);
175 icon_image_view_->SetImageSize(image_size);
176 icon_image_view_->SetImage(image);
181 layout->AddView(icon_image_view_); 177 layout->AddView(icon_image_view_);
182 app_icon_loader_->FetchImage(extension_id_);
183 178
184 title_tf_ = new views::Textfield(); 179 title_tf_ = new views::Textfield();
185 title_tf_->SetText(extension ? base::UTF8ToUTF16(extension->name()) 180 title_tf_->SetText(web_app_info_.title);
186 : web_app_info_.title);
187 layout->AddView(title_tf_); 181 layout->AddView(title_tf_);
188 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 182 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
189 183
190 layout->StartRow(0, CONTENT_COLUMN_SET_ID); 184 layout->StartRow(0, CONTENT_COLUMN_SET_ID);
191 open_as_window_checkbox_ = new views::Checkbox( 185 open_as_window_checkbox_ = new views::Checkbox(
192 l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)); 186 l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW));
193 open_as_window_checkbox_->SetChecked( 187 open_as_window_checkbox_->SetChecked(web_app_info_.open_as_window);
194 profile_->GetPrefs()->GetInteger(
195 extensions::pref_names::kBookmarkAppCreationLaunchType) ==
196 extensions::LAUNCH_TYPE_WINDOW);
197 layout->AddView(open_as_window_checkbox_); 188 layout->AddView(open_as_window_checkbox_);
198 layout->AddView(add_button_); 189 layout->AddView(add_button_);
199 layout->AddView(cancel_button_); 190 layout->AddView(cancel_button_);
200 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 191 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
201 192
202 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)); 193 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
203 } 194 }
204 195
205 views::View* BookmarkAppBubbleView::GetInitiallyFocusedView() { 196 views::View* BookmarkAppBubbleView::GetInitiallyFocusedView() {
206 return title_tf_; 197 return title_tf_;
207 } 198 }
208 199
209 void BookmarkAppBubbleView::WindowClosing() { 200 void BookmarkAppBubbleView::WindowClosing() {
210 // We have to reset |bookmark_app_bubble_| here, not in our destructor, 201 callback_.Run(user_accepted_, web_app_info_);
211 // because we'll be destroyed asynchronously and the shown state will be
212 // checked before then.
213 DCHECK_EQ(bookmark_app_bubble_, this);
214 bookmark_app_bubble_ = NULL;
215
216 if (remove_app_) {
217 GetExtensionService(profile_)
218 ->UninstallExtension(extension_id_,
219 extensions::UNINSTALL_REASON_INSTALL_CANCELED,
220 base::Bind(&base::DoNothing),
221 NULL);
222 } else {
223 ApplyEdits();
224 }
225 } 202 }
226 203
227 bool BookmarkAppBubbleView::AcceleratorPressed( 204 bool BookmarkAppBubbleView::AcceleratorPressed(
228 const ui::Accelerator& accelerator) { 205 const ui::Accelerator& accelerator) {
229 if (accelerator.key_code() == ui::VKEY_RETURN) { 206 if (accelerator.key_code() == ui::VKEY_RETURN) {
230 HandleButtonPressed(add_button_); 207 HandleButtonPressed(add_button_);
231 } 208 }
232 209
233 return BubbleDelegateView::AcceleratorPressed(accelerator); 210 return BubbleDelegateView::AcceleratorPressed(accelerator);
234 } 211 }
235 212
236 gfx::Size BookmarkAppBubbleView::GetMinimumSize() const { 213 gfx::Size BookmarkAppBubbleView::GetMinimumSize() const {
237 gfx::Size size(views::BubbleDelegateView::GetPreferredSize()); 214 gfx::Size size(views::BubbleDelegateView::GetPreferredSize());
238 size.SetToMax(gfx::Size(kMinBubbleWidth, 0)); 215 size.SetToMax(gfx::Size(kMinBubbleWidth, 0));
239 return size; 216 return size;
240 } 217 }
241 218
242 void BookmarkAppBubbleView::ButtonPressed(views::Button* sender, 219 void BookmarkAppBubbleView::ButtonPressed(views::Button* sender,
243 const ui::Event& event) { 220 const ui::Event& event) {
244 HandleButtonPressed(sender); 221 HandleButtonPressed(sender);
245 } 222 }
246 223
247 void BookmarkAppBubbleView::SetAppImage(const std::string& id,
248 const gfx::ImageSkia& image) {
249 DCHECK_EQ(extension_id_, id);
250 icon_image_view_->SetImage(image);
251 }
252
253 void BookmarkAppBubbleView::HandleButtonPressed(views::Button* sender) { 224 void BookmarkAppBubbleView::HandleButtonPressed(views::Button* sender) {
254 // Unset |remove_app_| so we don't delete the bookmark after the window 225 if (sender == add_button_) {
255 // closes. 226 user_accepted_ = true;
256 if (sender == add_button_) 227 web_app_info_.title = title_tf_->text();
257 remove_app_ = false; 228 web_app_info_.open_as_window = open_as_window_checkbox_->checked();
229 }
258 230
259 GetWidget()->Close(); 231 GetWidget()->Close();
260 } 232 }
261
262 void BookmarkAppBubbleView::ApplyEdits() {
263 // Set the launch type based on the checkbox.
264 extensions::LaunchType launch_type = open_as_window_checkbox_->checked()
265 ? extensions::LAUNCH_TYPE_WINDOW
266 : extensions::LAUNCH_TYPE_REGULAR;
267 profile_->GetPrefs()->SetInteger(
268 extensions::pref_names::kBookmarkAppCreationLaunchType, launch_type);
269 extensions::SetLaunchType(profile_, extension_id_, launch_type);
270
271 const extensions::Extension* extension =
272 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
273 extension_id_, extensions::ExtensionRegistry::EVERYTHING);
274
275 if (!extension)
276 return;
277
278 if (base::UTF8ToUTF16(extension->name()) != title_tf_->text()) {
279 // Reinstall the app with an updated name.
280 WebApplicationInfo install_info(web_app_info_);
281 install_info.title = title_tf_->text();
282
283 // This will asynchronously reload the extension, causing the Extension*
284 // we have to be destroyed. The extension ID will stay the same so that is
285 // used later on to highlight the app.
286 extensions::CreateOrUpdateBookmarkApp(GetExtensionService(profile_),
287 &install_info);
288 }
289
290 // As the extension could be destroyed after this point, set it to null to
291 // prevent anyone trying to use it in future.
292 extension = nullptr;
293
294 // Show the newly installed app in the app launcher or chrome://apps.
295 Profile* current_profile = profile_->GetOriginalProfile();
296 if (IsAppLauncherEnabled()) {
297 chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
298 GetWidget()->GetNativeWindow());
299 AppListService::Get(desktop)
300 ->ShowForAppInstall(current_profile, extension_id_, false);
301 return;
302 }
303
304 chrome::NavigateParams params(current_profile,
305 GURL(chrome::kChromeUIAppsURL),
306 ui::PAGE_TRANSITION_LINK);
307 params.disposition = SINGLETON_TAB;
308 chrome::Navigate(&params);
309
310 content::NotificationService::current()->Notify(
311 chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
312 content::Source<content::WebContents>(params.target_contents),
313 content::Details<const std::string>(&extension_id_));
314 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h ('k') | chrome/browser/ui/views/frame/browser_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698