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

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: 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 18 matching lines...) Expand all
153 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_STORE_LINK).c_str()); 158 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_STORE_LINK).c_str());
154 gtk_util::ForceFontSizePixels(store_link, kRatingTextSize); 159 gtk_util::ForceFontSizePixels(store_link, kRatingTextSize);
155 GtkWidget* store_link_hbox = gtk_hbox_new(FALSE, 0); 160 GtkWidget* store_link_hbox = gtk_hbox_new(FALSE, 0);
156 // Stick it in an hbox so it doesn't expand to the whole width. 161 // Stick it in an hbox so it doesn't expand to the whole width.
157 gtk_box_pack_start(GTK_BOX(store_link_hbox), store_link, FALSE, FALSE, 0); 162 gtk_box_pack_start(GTK_BOX(store_link_hbox), store_link, FALSE, FALSE, 0);
158 gtk_box_pack_start(GTK_BOX(heading_vbox), store_link_hbox, FALSE, FALSE, 0); 163 gtk_box_pack_start(GTK_BOX(heading_vbox), store_link_hbox, FALSE, FALSE, 0);
159 g_signal_connect(store_link, "clicked", 164 g_signal_connect(store_link, "clicked",
160 G_CALLBACK(OnStoreLinkClickThunk), this); 165 G_CALLBACK(OnStoreLinkClickThunk), this);
161 } 166 }
162 167
163 // Resize the icon if necessary. 168 if (is_bundle_install) {
164 SkBitmap scaled_icon = *skia_icon; 169 // Add the list of extensions to be installed.
165 if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) { 170 GtkWidget* extensions_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing);
166 scaled_icon = skia::ImageOperations::Resize(scaled_icon, 171 gtk_box_pack_start(GTK_BOX(heading_vbox), extensions_vbox, FALSE, FALSE,
167 skia::ImageOperations::RESIZE_LANCZOS3, 172 ui::kControlSpacing);
168 kImageSize, kImageSize); 173
174 BundleInstaller::ItemList items = prompt.bundle()->GetItemsWithState(
175 BundleInstaller::Item::STATE_PENDING);
176 for (size_t i = 0; i < items.size(); ++i) {
177 string16 extension_name = UTF8ToUTF16(items[i].localized_name);
178 base::i18n::AdjustStringForLocaleDirection(&extension_name);
179
180 GtkWidget* extension_label = gtk_label_new(UTF16ToUTF8(
181 l10n_util::GetStringFUTF16(
182 IDS_EXTENSION_PERMISSION_LINE, extension_name)).c_str());
183 gtk_util::SetLabelWidth(extension_label, kLeftColumnMinWidth);
184 gtk_box_pack_start(GTK_BOX(extensions_vbox), extension_label,
185 FALSE, FALSE, kExtensionsPadding);
186 }
169 } 187 }
170 188
171 // Put icon in the right column. 189 if (!is_bundle_install) {
172 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon); 190 // Resize the icon if necessary.
173 GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf); 191 SkBitmap scaled_icon = prompt.icon();
174 g_object_unref(pixbuf); 192 if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) {
175 gtk_box_pack_start(GTK_BOX(top_content_hbox), icon, FALSE, FALSE, 0); 193 scaled_icon = skia::ImageOperations::Resize(
176 // Top justify the image. 194 scaled_icon, skia::ImageOperations::RESIZE_LANCZOS3,
177 gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0); 195 kImageSize, kImageSize);
196 }
197
198 // Put icon in the right column.
199 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon);
200 GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
201 g_object_unref(pixbuf);
202 gtk_box_pack_start(GTK_BOX(top_content_hbox), icon, FALSE, FALSE, 0);
203 // Top justify the image.
204 gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
205 }
178 206
179 // Permissions are shown separated by a divider for inline installs, or 207 // Permissions are shown separated by a divider for inline installs, or
180 // directly under the heading for regular installs (where we don't have 208 // directly under the heading for regular installs (where we don't have
181 // the store data) 209 // the store data)
182 if (show_permissions) { 210 if (show_permissions) {
183 GtkWidget* permissions_container; 211 GtkWidget* permissions_container;
184 if (is_inline_install) { 212 if (is_inline_install) {
185 permissions_container = content_vbox; 213 permissions_container = content_vbox;
186 gtk_box_pack_start(GTK_BOX(content_vbox), gtk_hseparator_new(), 214 gtk_box_pack_start(GTK_BOX(content_vbox), gtk_hseparator_new(),
187 FALSE, FALSE, ui::kControlSpacing); 215 FALSE, FALSE, ui::kControlSpacing);
188 } else { 216 } else {
189 permissions_container = left_column_area; 217 permissions_container = left_column_area;
190 } 218 }
191 219
192 GtkWidget* permissions_header = gtk_util::CreateBoldLabel( 220 GtkWidget* permissions_header = gtk_util::CreateBoldLabel(
193 UTF16ToUTF8(prompt.GetPermissionsHeader()).c_str()); 221 UTF16ToUTF8(prompt.GetPermissionsHeading()).c_str());
194 gtk_util::SetLabelWidth(permissions_header, kLeftColumnMinWidth); 222 gtk_util::SetLabelWidth(permissions_header, kLeftColumnMinWidth);
195 gtk_box_pack_start(GTK_BOX(permissions_container), permissions_header, 223 gtk_box_pack_start(GTK_BOX(permissions_container), permissions_header,
196 FALSE, FALSE, 0); 224 FALSE, FALSE, 0);
197 225
198 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { 226 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
199 GtkWidget* permission_label = gtk_label_new(UTF16ToUTF8( 227 GtkWidget* permission_label = gtk_label_new(UTF16ToUTF8(
200 prompt.GetPermission(i)).c_str()); 228 prompt.GetPermission(i)).c_str());
201 gtk_util::SetLabelWidth(permission_label, kLeftColumnMinWidth); 229 gtk_util::SetLabelWidth(permission_label, kLeftColumnMinWidth);
202 gtk_box_pack_start(GTK_BOX(permissions_container), permission_label, 230 gtk_box_pack_start(GTK_BOX(permissions_container), permission_label,
203 FALSE, FALSE, kPermissionsPadding); 231 FALSE, FALSE, kPermissionsPadding);
(...skipping 17 matching lines...) Expand all
221 } else { 249 } else {
222 delegate_->InstallUIAbort(true); 250 delegate_->InstallUIAbort(true);
223 } 251 }
224 252
225 gtk_widget_destroy(dialog_); 253 gtk_widget_destroy(dialog_);
226 delete this; 254 delete this;
227 } 255 }
228 256
229 void ExtensionInstallDialog::OnStoreLinkClick(GtkWidget* sender) { 257 void ExtensionInstallDialog::OnStoreLinkClick(GtkWidget* sender) {
230 GURL store_url( 258 GURL store_url(
231 extension_urls::GetWebstoreItemDetailURLPrefix() + extension_->id()); 259 extension_urls::GetWebstoreItemDetailURLPrefix() + extension_id_);
232 BrowserList::GetLastActive()->OpenURL(OpenURLParams( 260 BrowserList::GetLastActive()->OpenURL(OpenURLParams(
233 store_url, content::Referrer(), NEW_FOREGROUND_TAB, 261 store_url, content::Referrer(), NEW_FOREGROUND_TAB,
234 content::PAGE_TRANSITION_LINK, false)); 262 content::PAGE_TRANSITION_LINK, false));
235 263
236 OnResponse(dialog_, GTK_RESPONSE_CLOSE); 264 OnResponse(dialog_, GTK_RESPONSE_CLOSE);
237 } 265 }
238 266
239 } // namespace 267 } // namespace
240 268
241 void ShowExtensionInstallDialogImpl( 269 void ShowExtensionInstallDialogImpl(
242 Profile* profile, 270 Profile* profile,
243 ExtensionInstallUI::Delegate* delegate, 271 ExtensionInstallUI::Delegate* delegate,
244 const Extension* extension,
245 SkBitmap* icon,
246 const ExtensionInstallUI::Prompt& prompt) { 272 const ExtensionInstallUI::Prompt& prompt) {
247 Browser* browser = BrowserList::GetLastActiveWithProfile(profile); 273 Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
248 if (!browser) { 274 if (!browser) {
249 delegate->InstallUIAbort(false); 275 delegate->InstallUIAbort(false);
250 return; 276 return;
251 } 277 }
252 278
253 BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>( 279 BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
254 browser->window()); 280 browser->window());
255 if (!browser_window) { 281 if (!browser_window) {
256 delegate->InstallUIAbort(false); 282 delegate->InstallUIAbort(false);
257 return; 283 return;
258 } 284 }
259 285
260 new ExtensionInstallDialog(browser_window->window(), 286 new ExtensionInstallDialog(browser_window->window(), delegate, prompt);
261 delegate,
262 extension,
263 icon,
264 prompt);
265 } 287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698