OLD | NEW |
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/apps/app_info_dialog_views.h" | 5 #include "chrome/browser/ui/views/apps/app_info_dialog_views.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/extensions/image_loader.h" |
| 10 #include "chrome/browser/profiles/profile.h" |
8 #include "chrome/browser/ui/apps/app_info_dialog.h" | 11 #include "chrome/browser/ui/apps/app_info_dialog.h" |
9 #include "chrome/browser/ui/views/constrained_window_views.h" | 12 #include "chrome/browser/ui/views/constrained_window_views.h" |
| 13 #include "chrome/common/extensions/extension_constants.h" |
| 14 #include "chrome/common/extensions/extension_icon_set.h" |
| 15 #include "chrome/common/extensions/manifest_handlers/icons_handler.h" |
10 #include "extensions/common/extension.h" | 16 #include "extensions/common/extension.h" |
| 17 #include "extensions/common/permissions/permission_message_provider.h" |
| 18 #include "extensions/common/permissions/permission_set.h" |
11 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
12 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
13 #include "ui/views/controls/label.h" | 21 #include "ui/views/controls/label.h" |
14 #include "ui/views/layout/grid_layout.h" | 22 #include "ui/views/layout/grid_layout.h" |
15 #include "ui/views/layout/layout_constants.h" | 23 #include "ui/views/layout/layout_constants.h" |
16 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
17 | 25 |
| 26 // Size of extension icon in top left of dialog. |
| 27 const int kIconSize = 64; |
| 28 |
18 void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window, | 29 void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window, |
19 Profile* profile, | 30 Profile* profile, |
20 const extensions::Extension* app, | 31 const extensions::Extension* app, |
21 const base::Closure& close_callback) { | 32 const base::Closure& close_callback) { |
22 CreateBrowserModalDialogViews(new AppInfoView(profile, app, close_callback), | 33 CreateBrowserModalDialogViews(new AppInfoView(profile, app, close_callback), |
23 parent_window)->Show(); | 34 parent_window)->Show(); |
24 } | 35 } |
25 | 36 |
| 37 PermissionsScrollView::PermissionsScrollView(int min_height, |
| 38 int max_height, |
| 39 const extensions::Extension* app) |
| 40 : message_center::BoundedScrollView(min_height, max_height) { |
| 41 inner_scrollable_view = new views::View(); |
| 42 this->SetContents(inner_scrollable_view); |
| 43 |
| 44 // Get the permission messages for the app |
| 45 std::vector<base::string16> permission_messages = |
| 46 extensions::PermissionMessageProvider::Get()->GetWarningMessages( |
| 47 app->GetActivePermissions(), app->GetType()); |
| 48 |
| 49 // Create the layout |
| 50 views::GridLayout* layout = |
| 51 views::GridLayout::CreatePanel(inner_scrollable_view); |
| 52 inner_scrollable_view->SetLayoutManager(layout); |
| 53 |
| 54 // Create 2 columns: one for the bullet, one for the bullet text |
| 55 static const int kPermissionBulletsColumnSetId = 1; |
| 56 views::ColumnSet* permission_bullets_column_set = |
| 57 layout->AddColumnSet(kPermissionBulletsColumnSetId); |
| 58 permission_bullets_column_set->AddPaddingColumn(0, 10); |
| 59 permission_bullets_column_set->AddColumn(views::GridLayout::LEADING, |
| 60 views::GridLayout::LEADING, |
| 61 0, |
| 62 views::GridLayout::USE_PREF, |
| 63 0, // no fixed width |
| 64 0); |
| 65 permission_bullets_column_set->AddPaddingColumn(0, 5); |
| 66 permission_bullets_column_set->AddColumn(views::GridLayout::LEADING, |
| 67 views::GridLayout::LEADING, |
| 68 0, |
| 69 views::GridLayout::USE_PREF, |
| 70 0, // no fixed width |
| 71 0); |
| 72 |
| 73 // Add permissions to scrollable view |
| 74 for (std::vector<base::string16>::const_iterator it = |
| 75 permission_messages.begin(); |
| 76 it != permission_messages.end(); |
| 77 ++it) { |
| 78 views::Label* permission_label = new views::Label(*it); |
| 79 |
| 80 permission_label->SetMultiLine(true); |
| 81 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 82 permission_label->SizeToFit(250); |
| 83 |
| 84 layout->StartRow(0, kPermissionBulletsColumnSetId); |
| 85 // Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text. |
| 86 layout->AddView(new views::Label(l10n_util::GetStringFUTF16( |
| 87 IDS_EXTENSION_PERMISSION_LINE, base::string16()))); |
| 88 // Place the text second, so multi-lined permissions line up below the |
| 89 // bullet. |
| 90 layout->AddView(permission_label); |
| 91 |
| 92 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 93 } |
| 94 } |
| 95 |
| 96 PermissionsScrollView::~PermissionsScrollView() {} |
| 97 |
26 AppInfoView::AppInfoView(Profile* profile, | 98 AppInfoView::AppInfoView(Profile* profile, |
27 const extensions::Extension* app, | 99 const extensions::Extension* app, |
28 const base::Closure& close_callback) | 100 const base::Closure& close_callback) |
29 : profile_(profile), | 101 : profile_(profile), |
30 app_name_label(NULL), | 102 app_name_label(NULL), |
31 app_description_label(NULL), | 103 app_description_label(NULL), |
32 app_(app), | 104 app_(app), |
33 close_callback_(close_callback) { | 105 close_callback_(close_callback), |
| 106 weak_ptr_factory_(this) { |
34 // Create controls | 107 // Create controls |
35 app_name_label = new views::Label(base::UTF8ToUTF16(app_->name())); | 108 app_name_label = new views::Label(base::UTF8ToUTF16(app_->name())); |
36 app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 109 app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
37 | 110 |
38 app_description_label = | 111 app_description_label = |
39 new views::Label(base::UTF8ToUTF16(app_->description())); | 112 new views::Label(base::UTF8ToUTF16(app_->description())); |
40 app_description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 113 app_description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
41 | 114 |
42 // Layout controls | 115 app_version_label = |
| 116 new views::Label(base::UTF8ToUTF16(app_->VersionString())); |
| 117 app_version_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 118 |
| 119 app_icon = new views::ImageView(); |
| 120 app_icon->SetImageSize(gfx::Size(kIconSize, kIconSize)); |
| 121 |
| 122 permission_list_heading = new views::Label( |
| 123 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_CAN_ACCESS)); |
| 124 permission_list_heading->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 125 |
| 126 permissions_scroll_view = new PermissionsScrollView(0, 100, app); |
| 127 |
| 128 // Load the app icon asynchronously. For the response, check OnImageLoaded. |
| 129 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource( |
| 130 app, |
| 131 extension_misc::EXTENSION_ICON_LARGE, |
| 132 ExtensionIconSet::MATCH_BIGGER); |
| 133 int pixel_size = |
| 134 static_cast<int>(kIconSize * gfx::ImageSkia::GetMaxSupportedScale()); |
| 135 extensions::ImageLoader::Get(profile) |
| 136 ->LoadImageAsync(app, |
| 137 image, |
| 138 gfx::Size(pixel_size, pixel_size), |
| 139 base::Bind(&AppInfoView::OnAppImageLoaded, AsWeakPtr())); |
| 140 |
| 141 // Create the layout |
43 views::GridLayout* layout = views::GridLayout::CreatePanel(this); | 142 views::GridLayout* layout = views::GridLayout::CreatePanel(this); |
44 SetLayoutManager(layout); | 143 SetLayoutManager(layout); |
45 | 144 |
| 145 // Header column set with app icon and information |
46 static const int kHeaderColumnSetId = 0; | 146 static const int kHeaderColumnSetId = 0; |
47 views::ColumnSet* column_set = layout->AddColumnSet(kHeaderColumnSetId); | 147 views::ColumnSet* header_column_set = |
48 column_set->AddColumn(views::GridLayout::FILL, | 148 layout->AddColumnSet(kHeaderColumnSetId); |
49 views::GridLayout::CENTER, | 149 header_column_set->AddColumn(views::GridLayout::FILL, |
50 100.0f, | 150 views::GridLayout::CENTER, |
51 views::GridLayout::FIXED, | 151 0, |
52 0, | 152 views::GridLayout::FIXED, |
53 0); | 153 kIconSize, |
| 154 0); |
| 155 header_column_set->AddPaddingColumn(0, |
| 156 views::kRelatedControlHorizontalSpacing); |
| 157 header_column_set->AddColumn(views::GridLayout::FILL, |
| 158 views::GridLayout::CENTER, |
| 159 100.0f, |
| 160 views::GridLayout::FIXED, |
| 161 0, |
| 162 0); |
| 163 |
| 164 // Column set with scrollable permissions |
| 165 static const int kPermissionsColumnSetId = 1; |
| 166 views::ColumnSet* permissions_column_set = |
| 167 layout->AddColumnSet(kPermissionsColumnSetId); |
| 168 permissions_column_set->AddColumn(views::GridLayout::FILL, |
| 169 views::GridLayout::CENTER, |
| 170 100.0f, |
| 171 views::GridLayout::FIXED, |
| 172 0, |
| 173 0); |
| 174 |
| 175 // The app icon takes up 3 rows |
| 176 layout->StartRow(0, kHeaderColumnSetId); |
| 177 layout->AddView(app_icon, 1, 3); |
| 178 |
| 179 // The app information fills up the right side of the icon |
| 180 layout->AddView(app_name_label); |
54 | 181 |
55 layout->StartRow(0, kHeaderColumnSetId); | 182 layout->StartRow(0, kHeaderColumnSetId); |
56 layout->AddView(app_name_label); | 183 layout->SkipColumns(1); |
| 184 layout->AddView(app_version_label); |
57 | 185 |
58 layout->AddPaddingRow(0, views::kPanelSubVerticalSpacing); | |
59 layout->StartRow(0, kHeaderColumnSetId); | 186 layout->StartRow(0, kHeaderColumnSetId); |
| 187 layout->SkipColumns(1); |
60 layout->AddView(app_description_label); | 188 layout->AddView(app_description_label); |
| 189 |
| 190 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 191 |
| 192 layout->StartRow(0, kPermissionsColumnSetId); |
| 193 layout->AddView(permission_list_heading); |
| 194 |
| 195 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 196 |
| 197 layout->StartRow(0, kPermissionsColumnSetId); |
| 198 layout->AddView(permissions_scroll_view); |
61 } | 199 } |
62 | 200 |
63 AppInfoView::~AppInfoView() {} | 201 AppInfoView::~AppInfoView() {} |
64 | 202 |
65 bool AppInfoView::Cancel() { | 203 bool AppInfoView::Cancel() { |
66 if (!close_callback_.is_null()) | 204 if (!close_callback_.is_null()) |
67 close_callback_.Run(); | 205 close_callback_.Run(); |
68 return true; | 206 return true; |
69 } | 207 } |
70 | 208 |
71 gfx::Size AppInfoView::GetPreferredSize() { | 209 gfx::Size AppInfoView::GetPreferredSize() { |
72 static const int kDialogWidth = 360; | 210 static const int kDialogWidth = 360; |
73 int height = | 211 int height = |
74 GetLayoutManager()->GetPreferredHeightForWidth(this, kDialogWidth); | 212 GetLayoutManager()->GetPreferredHeightForWidth(this, kDialogWidth); |
75 return gfx::Size(kDialogWidth, height); | 213 return gfx::Size(kDialogWidth, height); |
76 } | 214 } |
77 | 215 |
78 base::string16 AppInfoView::GetDialogButtonLabel(ui::DialogButton button) | 216 base::string16 AppInfoView::GetDialogButtonLabel(ui::DialogButton button) |
79 const { | 217 const { |
80 if (button == ui::DIALOG_BUTTON_CANCEL) { | 218 if (button == ui::DIALOG_BUTTON_CANCEL) { |
81 return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_CLOSE_BUTTON); | 219 return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_CLOSE_BUTTON); |
82 } | 220 } |
83 return views::DialogDelegateView::GetDialogButtonLabel(button); | 221 return views::DialogDelegateView::GetDialogButtonLabel(button); |
84 } | 222 } |
85 | 223 |
86 int AppInfoView::GetDialogButtons() const { | 224 int AppInfoView::GetDialogButtons() const { return ui::DIALOG_BUTTON_CANCEL; } |
87 return ui::DIALOG_BUTTON_CANCEL; | |
88 } | |
89 | 225 |
90 bool AppInfoView::IsDialogButtonEnabled(ui::DialogButton button) const { | 226 bool AppInfoView::IsDialogButtonEnabled(ui::DialogButton button) const { |
91 return true; | 227 return true; |
92 } | 228 } |
93 | 229 |
94 ui::ModalType AppInfoView::GetModalType() const { | 230 ui::ModalType AppInfoView::GetModalType() const { |
95 return ui::MODAL_TYPE_WINDOW; | 231 return ui::MODAL_TYPE_WINDOW; |
96 } | 232 } |
97 | 233 |
98 base::string16 AppInfoView::GetWindowTitle() const { | 234 base::string16 AppInfoView::GetWindowTitle() const { |
99 return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_TITLE); | 235 return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_TITLE); |
100 } | 236 } |
| 237 |
| 238 void AppInfoView::OnAppImageLoaded(const gfx::Image& image) { |
| 239 const SkBitmap* bitmap = image.ToSkBitmap(); |
| 240 if (image.IsEmpty()) { |
| 241 bitmap = &extensions::IconsInfo::GetDefaultAppIcon() |
| 242 .GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale()) |
| 243 .sk_bitmap(); |
| 244 } |
| 245 |
| 246 app_icon->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap)); |
| 247 } |
OLD | NEW |