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

Side by Side Diff: chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc

Issue 9456019: Add GTK interface for installing bundles of extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix compile Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <gtk/gtk.h> 5 #include <gtk/gtk.h>
6 6
7 #include "base/i18n/rtl.h"
7 #include "base/string_util.h" 8 #include "base/string_util.h"
8 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/extensions/bundle_installer.h"
9 #include "chrome/browser/extensions/extension_install_dialog.h" 11 #include "chrome/browser/extensions/extension_install_dialog.h"
10 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser_list.h" 13 #include "chrome/browser/ui/browser_list.h"
12 #include "chrome/browser/ui/browser_window.h" 14 #include "chrome/browser/ui/browser_window.h"
13 #include "chrome/browser/ui/gtk/browser_window_gtk.h" 15 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
14 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" 16 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
15 #include "chrome/browser/ui/gtk/gtk_util.h" 17 #include "chrome/browser/ui/gtk/gtk_util.h"
16 #include "chrome/common/extensions/extension.h" 18 #include "chrome/common/extensions/extension.h"
17 #include "grit/generated_resources.h" 19 #include "grit/generated_resources.h"
18 #include "skia/ext/image_operations.h" 20 #include "skia/ext/image_operations.h"
19 #include "ui/base/gtk/gtk_hig_constants.h" 21 #include "ui/base/gtk/gtk_hig_constants.h"
20 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h" 23 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/gtk_util.h" 24 #include "ui/gfx/gtk_util.h"
23 25
24 using content::OpenURLParams; 26 using content::OpenURLParams;
27 using extensions::BundleInstaller;
25 28
26 namespace { 29 namespace {
27 30
28 const int kLeftColumnMinWidth = 250; 31 const int kLeftColumnMinWidth = 250;
29 const int kImageSize = 69; 32 const int kImageSize = 69;
30 33
31 // Additional padding (beyond on ui::kControlSpacing) all sides of each 34 // Additional padding (beyond on ui::kControlSpacing) all sides of each
32 // permission in the permissions list. 35 // permission in the permissions list.
33 const int kPermissionsPadding = 2; 36 const int kPermissionsPadding = 2;
37 const int kExtensionsPadding = kPermissionsPadding;
34 38
35 const double kRatingTextSize = 12.1; // 12.1px = 9pt @ 96dpi 39 const double kRatingTextSize = 12.1; // 12.1px = 9pt @ 96dpi
36 40
37 // Adds a Skia image as an icon control to the given container. 41 // Adds a Skia image as an icon control to the given container.
38 void AddResourceIcon(const SkBitmap* icon, void* data) { 42 void AddResourceIcon(const SkBitmap* icon, void* data) {
39 GtkWidget* container = static_cast<GtkWidget*>(data); 43 GtkWidget* container = static_cast<GtkWidget*>(data);
40 GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(icon); 44 GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
41 GtkWidget* icon_widget = gtk_image_new_from_pixbuf(icon_pixbuf); 45 GtkWidget* icon_widget = gtk_image_new_from_pixbuf(icon_pixbuf);
42 g_object_unref(icon_pixbuf); 46 g_object_unref(icon_pixbuf);
43 gtk_box_pack_start(GTK_BOX(container), icon_widget, FALSE, FALSE, 0); 47 gtk_box_pack_start(GTK_BOX(container), icon_widget, FALSE, FALSE, 0);
44 } 48 }
45 49
46 // Displays the dialog when constructed, deletes itself when dialog is 50 // Displays the dialog when constructed, deletes itself when dialog is
47 // dismissed. Success/failure is passed back through the ExtensionInstallUI:: 51 // dismissed. Success/failure is passed back through the ExtensionInstallUI::
48 // Delegate instance. 52 // Delegate instance.
49 class ExtensionInstallDialog { 53 class ExtensionInstallDialog {
50 public: 54 public:
51 ExtensionInstallDialog(GtkWindow* parent, 55 ExtensionInstallDialog(GtkWindow* parent,
52 ExtensionInstallUI::Delegate *delegate, 56 ExtensionInstallUI::Delegate *delegate,
53 const Extension* extension,
54 SkBitmap* skia_icon,
55 const ExtensionInstallUI::Prompt& prompt); 57 const ExtensionInstallUI::Prompt& prompt);
56 private: 58 private:
57 ~ExtensionInstallDialog(); 59 ~ExtensionInstallDialog();
58 60
59 CHROMEGTK_CALLBACK_1(ExtensionInstallDialog, void, OnResponse, int); 61 CHROMEGTK_CALLBACK_1(ExtensionInstallDialog, void, OnResponse, int);
60 CHROMEGTK_CALLBACK_0(ExtensionInstallDialog, void, OnStoreLinkClick); 62 CHROMEGTK_CALLBACK_0(ExtensionInstallDialog, void, OnStoreLinkClick);
61 63
62 ExtensionInstallUI::Delegate* delegate_; 64 ExtensionInstallUI::Delegate* delegate_;
63 const Extension* extension_; 65 std::string extension_id_; // Set for INLINE_INSTALL_PROMPT.
64 GtkWidget* dialog_; 66 GtkWidget* dialog_;
65 }; 67 };
66 68
67 ExtensionInstallDialog::ExtensionInstallDialog( 69 ExtensionInstallDialog::ExtensionInstallDialog(
68 GtkWindow* parent, 70 GtkWindow* parent,
69 ExtensionInstallUI::Delegate *delegate, 71 ExtensionInstallUI::Delegate *delegate,
70 const Extension* extension,
71 SkBitmap* skia_icon,
72 const ExtensionInstallUI::Prompt& prompt) 72 const ExtensionInstallUI::Prompt& prompt)
73 : delegate_(delegate), 73 : delegate_(delegate),
74 extension_(extension) { 74 dialog_(NULL) {
75 bool show_permissions = prompt.GetPermissionCount() > 0; 75 bool show_permissions = prompt.GetPermissionCount() > 0;
76 bool is_inline_install = 76 bool is_inline_install =
77 prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; 77 prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT;
78 bool is_bundle_install =
79 prompt.type() == ExtensionInstallUI::BUNDLE_INSTALL_PROMPT;
80
81 if (is_inline_install)
82 extension_id_ = prompt.extension()->id();
78 83
79 // Build the dialog. 84 // Build the dialog.
80 dialog_ = gtk_dialog_new_with_buttons( 85 dialog_ = gtk_dialog_new_with_buttons(
81 UTF16ToUTF8(prompt.GetDialogTitle(extension)).c_str(), 86 UTF16ToUTF8(prompt.GetDialogTitle()).c_str(),
82 parent, 87 parent,
83 GTK_DIALOG_MODAL, 88 GTK_DIALOG_MODAL,
84 NULL); 89 NULL);
85 GtkWidget* close_button = gtk_dialog_add_button( 90 GtkWidget* close_button = gtk_dialog_add_button(
86 GTK_DIALOG(dialog_), 91 GTK_DIALOG(dialog_),
87 prompt.HasAbortButtonLabel() ? 92 prompt.HasAbortButtonLabel() ?
88 UTF16ToUTF8(prompt.GetAbortButtonLabel()).c_str() : GTK_STOCK_CANCEL, 93 UTF16ToUTF8(prompt.GetAbortButtonLabel()).c_str() : GTK_STOCK_CANCEL,
89 GTK_RESPONSE_CLOSE); 94 GTK_RESPONSE_CLOSE);
90 gtk_dialog_add_button( 95 gtk_dialog_add_button(
91 GTK_DIALOG(dialog_), 96 GTK_DIALOG(dialog_),
(...skipping 22 matching lines...) Expand all
114 TRUE, TRUE, 0); 119 TRUE, TRUE, 0);
115 120
116 GtkWidget* heading_vbox = gtk_vbox_new(FALSE, 0); 121 GtkWidget* heading_vbox = gtk_vbox_new(FALSE, 0);
117 // If we are not going to show anything else, vertically center the title. 122 // If we are not going to show anything else, vertically center the title.
118 bool center_heading = !show_permissions && !is_inline_install; 123 bool center_heading = !show_permissions && !is_inline_install;
119 gtk_box_pack_start(GTK_BOX(left_column_area), heading_vbox, center_heading, 124 gtk_box_pack_start(GTK_BOX(left_column_area), heading_vbox, center_heading,
120 center_heading, 0); 125 center_heading, 0);
121 126
122 // Heading 127 // Heading
123 GtkWidget* heading_label = gtk_util::CreateBoldLabel( 128 GtkWidget* heading_label = gtk_util::CreateBoldLabel(
124 UTF16ToUTF8(prompt.GetHeading(extension_->name())).c_str()); 129 UTF16ToUTF8(prompt.GetHeading().c_str()));
125 gtk_label_set_line_wrap(GTK_LABEL(heading_label), true); 130 gtk_label_set_line_wrap(GTK_LABEL(heading_label), true);
126 gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5); 131 gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5);
127 gtk_box_pack_start(GTK_BOX(heading_vbox), heading_label, center_heading, 132 gtk_box_pack_start(GTK_BOX(heading_vbox), heading_label, center_heading,
128 center_heading, 0); 133 center_heading, 0);
129 134
130 if (is_inline_install) { 135 if (is_inline_install) {
131 // Average rating (as stars) and number of ratings. 136 // Average rating (as stars) and number of ratings.
132 GtkWidget* stars_hbox = gtk_hbox_new(FALSE, 0); 137 GtkWidget* stars_hbox = gtk_hbox_new(FALSE, 0);
133 gtk_box_pack_start(GTK_BOX(heading_vbox), stars_hbox, FALSE, FALSE, 0); 138 gtk_box_pack_start(GTK_BOX(heading_vbox), stars_hbox, FALSE, FALSE, 0);
134 prompt.AppendRatingStars(AddResourceIcon, stars_hbox); 139 prompt.AppendRatingStars(AddResourceIcon, stars_hbox);
(...skipping 17 matching lines...) Expand all
152 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_STORE_LINK).c_str()); 157 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_STORE_LINK).c_str());
153 gtk_util::ForceFontSizePixels(store_link, kRatingTextSize); 158 gtk_util::ForceFontSizePixels(store_link, kRatingTextSize);
154 GtkWidget* store_link_hbox = gtk_hbox_new(FALSE, 0); 159 GtkWidget* store_link_hbox = gtk_hbox_new(FALSE, 0);
155 // Stick it in an hbox so it doesn't expand to the whole width. 160 // Stick it in an hbox so it doesn't expand to the whole width.
156 gtk_box_pack_start(GTK_BOX(store_link_hbox), store_link, FALSE, FALSE, 0); 161 gtk_box_pack_start(GTK_BOX(store_link_hbox), store_link, FALSE, FALSE, 0);
157 gtk_box_pack_start(GTK_BOX(heading_vbox), store_link_hbox, FALSE, FALSE, 0); 162 gtk_box_pack_start(GTK_BOX(heading_vbox), store_link_hbox, FALSE, FALSE, 0);
158 g_signal_connect(store_link, "clicked", 163 g_signal_connect(store_link, "clicked",
159 G_CALLBACK(OnStoreLinkClickThunk), this); 164 G_CALLBACK(OnStoreLinkClickThunk), this);
160 } 165 }
161 166
162 // Resize the icon if necessary. 167 if (is_bundle_install) {
163 SkBitmap scaled_icon = *skia_icon; 168 // Add the list of extensions to be installed.
164 if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) { 169 GtkWidget* extensions_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing);
165 scaled_icon = skia::ImageOperations::Resize(scaled_icon, 170 gtk_box_pack_start(GTK_BOX(heading_vbox), extensions_vbox, FALSE, FALSE,
166 skia::ImageOperations::RESIZE_LANCZOS3, 171 ui::kControlSpacing);
167 kImageSize, kImageSize); 172
173 BundleInstaller::ItemList items = prompt.bundle()->GetItemsWithState(
174 BundleInstaller::Item::STATE_PENDING);
175 for (size_t i = 0; i < items.size(); ++i) {
176 string16 extension_name = UTF8ToUTF16(items[i].localized_name);
177 base::i18n::AdjustStringForLocaleDirection(&extension_name);
178
179 GtkWidget* extension_label = gtk_label_new(UTF16ToUTF8(
180 l10n_util::GetStringFUTF16(
181 IDS_EXTENSION_PERMISSION_LINE, extension_name)).c_str());
182 gtk_util::SetLabelWidth(extension_label, kLeftColumnMinWidth);
183 gtk_box_pack_start(GTK_BOX(extensions_vbox), extension_label,
184 FALSE, FALSE, kExtensionsPadding);
185 }
168 } 186 }
169 187
170 // Put icon in the right column. 188 if (!is_bundle_install) {
171 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon); 189 // Resize the icon if necessary.
172 GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf); 190 SkBitmap scaled_icon = prompt.icon();
173 g_object_unref(pixbuf); 191 if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) {
174 gtk_box_pack_start(GTK_BOX(top_content_hbox), icon, FALSE, FALSE, 0); 192 scaled_icon = skia::ImageOperations::Resize(
175 // Top justify the image. 193 scaled_icon, skia::ImageOperations::RESIZE_LANCZOS3,
176 gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0); 194 kImageSize, kImageSize);
195 }
196
197 // Put icon in the right column.
198 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon);
199 GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
200 g_object_unref(pixbuf);
201 gtk_box_pack_start(GTK_BOX(top_content_hbox), icon, FALSE, FALSE, 0);
202 // Top justify the image.
203 gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
204 }
177 205
178 // Permissions are shown separated by a divider for inline installs, or 206 // Permissions are shown separated by a divider for inline installs, or
179 // directly under the heading for regular installs (where we don't have 207 // directly under the heading for regular installs (where we don't have
180 // the store data) 208 // the store data)
181 if (show_permissions) { 209 if (show_permissions) {
182 GtkWidget* permissions_container; 210 GtkWidget* permissions_container;
183 if (is_inline_install) { 211 if (is_inline_install) {
184 permissions_container = content_vbox; 212 permissions_container = content_vbox;
185 gtk_box_pack_start(GTK_BOX(content_vbox), gtk_hseparator_new(), 213 gtk_box_pack_start(GTK_BOX(content_vbox), gtk_hseparator_new(),
186 FALSE, FALSE, ui::kControlSpacing); 214 FALSE, FALSE, ui::kControlSpacing);
187 } else { 215 } else {
188 permissions_container = left_column_area; 216 permissions_container = left_column_area;
189 } 217 }
190 218
191 GtkWidget* permissions_header = gtk_util::CreateBoldLabel( 219 GtkWidget* permissions_header = gtk_util::CreateBoldLabel(
192 UTF16ToUTF8(prompt.GetPermissionsHeader()).c_str()); 220 UTF16ToUTF8(prompt.GetPermissionsHeading()).c_str());
193 gtk_util::SetLabelWidth(permissions_header, kLeftColumnMinWidth); 221 gtk_util::SetLabelWidth(permissions_header, kLeftColumnMinWidth);
194 gtk_box_pack_start(GTK_BOX(permissions_container), permissions_header, 222 gtk_box_pack_start(GTK_BOX(permissions_container), permissions_header,
195 FALSE, FALSE, 0); 223 FALSE, FALSE, 0);
196 224
197 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { 225 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
198 GtkWidget* permission_label = gtk_label_new(UTF16ToUTF8( 226 GtkWidget* permission_label = gtk_label_new(UTF16ToUTF8(
199 prompt.GetPermission(i)).c_str()); 227 prompt.GetPermission(i)).c_str());
200 gtk_util::SetLabelWidth(permission_label, kLeftColumnMinWidth); 228 gtk_util::SetLabelWidth(permission_label, kLeftColumnMinWidth);
201 gtk_box_pack_start(GTK_BOX(permissions_container), permission_label, 229 gtk_box_pack_start(GTK_BOX(permissions_container), permission_label,
202 FALSE, FALSE, kPermissionsPadding); 230 FALSE, FALSE, kPermissionsPadding);
(...skipping 17 matching lines...) Expand all
220 } else { 248 } else {
221 delegate_->InstallUIAbort(true); 249 delegate_->InstallUIAbort(true);
222 } 250 }
223 251
224 gtk_widget_destroy(dialog_); 252 gtk_widget_destroy(dialog_);
225 delete this; 253 delete this;
226 } 254 }
227 255
228 void ExtensionInstallDialog::OnStoreLinkClick(GtkWidget* sender) { 256 void ExtensionInstallDialog::OnStoreLinkClick(GtkWidget* sender) {
229 GURL store_url( 257 GURL store_url(
230 extension_urls::GetWebstoreItemDetailURLPrefix() + extension_->id()); 258 extension_urls::GetWebstoreItemDetailURLPrefix() + extension_id_);
231 BrowserList::GetLastActive()->OpenURL(OpenURLParams( 259 BrowserList::GetLastActive()->OpenURL(OpenURLParams(
232 store_url, content::Referrer(), NEW_FOREGROUND_TAB, 260 store_url, content::Referrer(), NEW_FOREGROUND_TAB,
233 content::PAGE_TRANSITION_LINK, false)); 261 content::PAGE_TRANSITION_LINK, false));
234 262
235 OnResponse(dialog_, GTK_RESPONSE_CLOSE); 263 OnResponse(dialog_, GTK_RESPONSE_CLOSE);
236 } 264 }
237 265
238 } // namespace 266 } // namespace
239 267
240 void ShowExtensionInstallDialogImpl( 268 void ShowExtensionInstallDialogImpl(
241 Profile* profile, 269 Profile* profile,
242 ExtensionInstallUI::Delegate* delegate, 270 ExtensionInstallUI::Delegate* delegate,
243 const Extension* extension,
244 SkBitmap* icon,
245 const ExtensionInstallUI::Prompt& prompt) { 271 const ExtensionInstallUI::Prompt& prompt) {
246 Browser* browser = BrowserList::GetLastActiveWithProfile(profile); 272 Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
247 if (!browser) { 273 if (!browser) {
248 delegate->InstallUIAbort(false); 274 delegate->InstallUIAbort(false);
249 return; 275 return;
250 } 276 }
251 277
252 BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>( 278 BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
253 browser->window()); 279 browser->window());
254 if (!browser_window) { 280 if (!browser_window) {
255 delegate->InstallUIAbort(false); 281 delegate->InstallUIAbort(false);
256 return; 282 return;
257 } 283 }
258 284
259 new ExtensionInstallDialog(browser_window->window(), 285 new ExtensionInstallDialog(browser_window->window(), delegate, prompt);
260 delegate,
261 extension,
262 icon,
263 prompt);
264 } 286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698