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.
5 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.h"
10 #include "apps/app_load_service.h"
11 #include "apps/saved_files_service.h"
12 #include "base/files/file_path.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "extensions/common/extension.h"
15 #include "extensions/common/permissions/api_permission.h"
16 #include "extensions/common/permissions/permissions_data.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/views/controls/button/label_button.h"
19 #include "ui/views/controls/label.h"
20 #include "ui/views/layout/box_layout.h"
21 #include "ui/views/layout/grid_layout.h"
22 #include "ui/views/layout/layout_constants.h"
23 #include "ui/views/view.h"
24 #include "ui/views/widget/widget.h"
26 AppInfoPermissionsPanel::AppInfoPermissionsPanel(
28 const extensions::Extension* app)
29 : AppInfoPanel(profile, app),
30 active_permissions_heading_(NULL),
31 active_permissions_list_(NULL),
32 retained_files_heading_(NULL),
33 retained_files_list_(NULL),
34 revoke_file_permissions_button_(NULL) {
35 // Create UI elements.
36 CreateActivePermissionsControl();
37 CreateRetainedFilesControl();
41 new views::BoxLayout(views::BoxLayout::kVertical,
44 views::kUnrelatedControlVerticalSpacing));
46 LayoutActivePermissionsControl();
47 LayoutRetainedFilesControl();
50 AppInfoPermissionsPanel::~AppInfoPermissionsPanel() {
51 // Destroy view children before their models.
52 RemoveAllChildViews(true);
55 // Given a list of strings, returns a view containing a list of these strings
57 views::View* AppInfoPermissionsPanel::CreateBulletedListView(
58 const std::vector<base::string16>& messages,
60 gfx::ElideBehavior elide_behavior) {
61 const int kSpacingBetweenBulletAndStartOfText = 5;
63 views::View* list_view = new views::View();
64 views::GridLayout* layout = new views::GridLayout(list_view);
65 list_view->SetLayoutManager(layout);
67 // Create 2 columns: one for the bullet, one for the bullet text.
68 static const int kColumnSetId = 1;
69 views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
70 column_set->AddColumn(views::GridLayout::FILL,
71 views::GridLayout::LEADING,
73 views::GridLayout::USE_PREF,
76 column_set->AddPaddingColumn(0, kSpacingBetweenBulletAndStartOfText);
77 column_set->AddColumn(views::GridLayout::FILL,
78 views::GridLayout::LEADING,
80 views::GridLayout::USE_PREF,
84 for (std::vector<base::string16>::const_iterator it = messages.begin();
87 views::Label* permission_label = new views::Label(*it);
88 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
91 permission_label->SetMultiLine(true);
93 permission_label->SetElideBehavior(elide_behavior);
95 // Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text.
96 views::Label* bullet_label = new views::Label(l10n_util::GetStringFUTF16(
97 IDS_EXTENSION_PERMISSION_LINE, base::string16()));
99 // Add a padding row before every item except the first
100 if (it != messages.begin())
101 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
103 layout->StartRow(1, kColumnSetId);
104 layout->AddView(bullet_label);
105 layout->AddView(permission_label);
111 void AppInfoPermissionsPanel::CreateActivePermissionsControl() {
112 std::vector<base::string16> permission_strings =
113 GetActivePermissionMessages();
114 if (permission_strings.empty()) {
115 views::Label* no_permissions_text = new views::Label(
116 l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_NO_PERMISSIONS_TEXT));
117 no_permissions_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
118 active_permissions_list_ = no_permissions_text;
120 active_permissions_heading_ = CreateHeading(l10n_util::GetStringUTF16(
121 IDS_APPLICATION_INFO_ACTIVE_PERMISSIONS_TEXT));
122 active_permissions_list_ =
123 CreateBulletedListView(permission_strings, true, gfx::NO_ELIDE);
127 void AppInfoPermissionsPanel::CreateRetainedFilesControl() {
128 const std::vector<base::string16> retained_file_permission_messages =
129 GetRetainedFilePaths();
131 if (!retained_file_permission_messages.empty()) {
132 revoke_file_permissions_button_ = new views::LabelButton(
134 l10n_util::GetStringUTF16(
135 IDS_APPLICATION_INFO_REVOKE_RETAINED_FILE_PERMISSIONS_BUTTON_TEXT));
136 revoke_file_permissions_button_->SetStyle(views::Button::STYLE_BUTTON);
138 retained_files_heading_ = CreateHeading(l10n_util::GetStringUTF16(
139 IDS_APPLICATION_INFO_RETAINED_FILE_PERMISSIONS_TEXT));
140 retained_files_list_ = CreateBulletedListView(
141 retained_file_permission_messages, false, gfx::ELIDE_MIDDLE);
145 void AppInfoPermissionsPanel::LayoutActivePermissionsControl() {
146 if (active_permissions_list_) {
147 views::View* vertical_stack = CreateVerticalStack();
148 if (active_permissions_heading_)
149 vertical_stack->AddChildView(active_permissions_heading_);
150 vertical_stack->AddChildView(active_permissions_list_);
152 AddChildView(vertical_stack);
156 void AppInfoPermissionsPanel::LayoutRetainedFilesControl() {
157 if (retained_files_list_) {
158 DCHECK(retained_files_heading_);
159 DCHECK(revoke_file_permissions_button_);
161 // Add a sub-view so the revoke button is right-aligned.
162 views::View* right_aligned_button = new views::View();
163 views::BoxLayout* right_aligned_horizontal_layout =
164 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
165 right_aligned_horizontal_layout->set_main_axis_alignment(
166 views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
167 right_aligned_button->SetLayoutManager(right_aligned_horizontal_layout);
168 right_aligned_button->AddChildView(revoke_file_permissions_button_);
170 views::View* vertical_stack = CreateVerticalStack();
171 vertical_stack->AddChildView(retained_files_heading_);
172 vertical_stack->AddChildView(retained_files_list_);
173 vertical_stack->AddChildView(right_aligned_button);
175 AddChildView(vertical_stack);
179 void AppInfoPermissionsPanel::ButtonPressed(views::Button* sender,
180 const ui::Event& event) {
181 if (sender == revoke_file_permissions_button_) {
182 RevokeFilePermissions();
188 const std::vector<base::string16>
189 AppInfoPermissionsPanel::GetActivePermissionMessages() const {
190 return app_->permissions_data()->GetPermissionMessageStrings();
193 const std::vector<base::string16>
194 AppInfoPermissionsPanel::GetRetainedFilePaths() const {
195 std::vector<base::string16> retained_file_paths;
196 if (app_->permissions_data()->HasAPIPermission(
197 extensions::APIPermission::kFileSystem)) {
198 std::vector<apps::SavedFileEntry> retained_file_entries =
199 apps::SavedFilesService::Get(profile_)->GetAllFileEntries(app_->id());
200 for (std::vector<apps::SavedFileEntry>::const_iterator it =
201 retained_file_entries.begin();
202 it != retained_file_entries.end();
204 retained_file_paths.push_back(it->path.LossyDisplayName());
207 return retained_file_paths;
210 void AppInfoPermissionsPanel::RevokeFilePermissions() {
211 apps::SavedFilesService::Get(profile_)->ClearQueue(app_);
212 apps::AppLoadService::Get(profile_)->RestartApplicationIfRunning(app_->id());
214 GetWidget()->Close();