app_info_permissions_panel.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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. 4 5#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.h" 6 7#include <string> 8#include <vector> 9 10#include "apps/app_load_service.h" 11#include "apps/app_restore_service.h" 12#include "apps/saved_files_service.h" 13#include "base/files/file_path.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 "grit/generated_resources.h" 18#include "ui/base/l10n/l10n_util.h" 19#include "ui/views/controls/button/label_button.h" 20#include "ui/views/controls/label.h" 21#include "ui/views/layout/box_layout.h" 22#include "ui/views/layout/layout_constants.h" 23#include "ui/views/view.h" 24#include "ui/views/widget/widget.h" 25 26AppInfoPermissionsPanel::AppInfoPermissionsPanel( 27 Profile* profile, 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(); 38 39 // Layout elements. 40 SetLayoutManager( 41 new views::BoxLayout(views::BoxLayout::kVertical, 42 0, 43 0, 44 views::kUnrelatedControlVerticalSpacing)); 45 46 LayoutActivePermissionsControl(); 47 LayoutRetainedFilesControl(); 48} 49 50AppInfoPermissionsPanel::~AppInfoPermissionsPanel() { 51 // Destroy view children before their models. 52 RemoveAllChildViews(true); 53} 54 55// Given a list of strings, returns a view containing a list of these strings 56// as bulleted items. 57views::View* AppInfoPermissionsPanel::CreateBulletedListView( 58 const std::vector<base::string16>& messages, 59 bool allow_multiline, 60 gfx::ElideBehavior elide_behavior) { 61 const int kSpacingBetweenBulletAndStartOfText = 5; 62 views::View* list_view = CreateVerticalStack(); 63 64 for (std::vector<base::string16>::const_iterator it = messages.begin(); 65 it != messages.end(); 66 ++it) { 67 views::Label* permission_label = new views::Label(*it); 68 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 69 70 if (allow_multiline) 71 permission_label->SetMultiLine(true); 72 else 73 permission_label->SetElideBehavior(elide_behavior); 74 75 // Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text, and 76 // place it in it's own view so it doesn't align vertically with the 77 // multilined permissions text. 78 views::Label* bullet_label = new views::Label(l10n_util::GetStringFUTF16( 79 IDS_EXTENSION_PERMISSION_LINE, base::string16())); 80 views::View* bullet_label_top_aligned = CreateVerticalStack(); 81 bullet_label_top_aligned->AddChildView(bullet_label); 82 83 // Place the bullet and the text so all permissions line up at the bullet. 84 views::View* bulleted_list_item = new views::View(); 85 bulleted_list_item->SetLayoutManager( 86 new views::BoxLayout(views::BoxLayout::kHorizontal, 87 0, 88 0, 89 kSpacingBetweenBulletAndStartOfText)); 90 bulleted_list_item->AddChildView(bullet_label_top_aligned); 91 bulleted_list_item->AddChildView(permission_label); 92 93 list_view->AddChildView(bulleted_list_item); 94 } 95 96 return list_view; 97} 98 99void AppInfoPermissionsPanel::CreateActivePermissionsControl() { 100 std::vector<base::string16> permission_strings = 101 GetActivePermissionMessages(); 102 if (permission_strings.empty()) { 103 views::Label* no_permissions_text = new views::Label( 104 l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_NO_PERMISSIONS_TEXT)); 105 no_permissions_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 106 active_permissions_list_ = no_permissions_text; 107 } else { 108 active_permissions_heading_ = CreateHeading(l10n_util::GetStringUTF16( 109 IDS_APPLICATION_INFO_ACTIVE_PERMISSIONS_TEXT)); 110 active_permissions_list_ = 111 CreateBulletedListView(permission_strings, true, gfx::TRUNCATE); 112 } 113} 114 115void AppInfoPermissionsPanel::CreateRetainedFilesControl() { 116 const std::vector<base::string16> retained_file_permission_messages = 117 GetRetainedFilePaths(); 118 119 if (!retained_file_permission_messages.empty()) { 120 revoke_file_permissions_button_ = new views::LabelButton( 121 this, 122 l10n_util::GetStringUTF16( 123 IDS_APPLICATION_INFO_REVOKE_RETAINED_FILE_PERMISSIONS_BUTTON_TEXT)); 124 revoke_file_permissions_button_->SetStyle(views::Button::STYLE_BUTTON); 125 126 retained_files_heading_ = CreateHeading(l10n_util::GetStringUTF16( 127 IDS_APPLICATION_INFO_RETAINED_FILE_PERMISSIONS_TEXT)); 128 retained_files_list_ = CreateBulletedListView( 129 retained_file_permission_messages, false, gfx::ELIDE_MIDDLE); 130 } 131} 132 133void AppInfoPermissionsPanel::LayoutActivePermissionsControl() { 134 if (active_permissions_list_) { 135 views::View* vertical_stack = CreateVerticalStack(); 136 if (active_permissions_heading_) 137 vertical_stack->AddChildView(active_permissions_heading_); 138 vertical_stack->AddChildView(active_permissions_list_); 139 140 AddChildView(vertical_stack); 141 } 142} 143 144void AppInfoPermissionsPanel::LayoutRetainedFilesControl() { 145 if (retained_files_list_) { 146 DCHECK(retained_files_heading_); 147 DCHECK(revoke_file_permissions_button_); 148 149 // Add a sub-view so the revoke button is right-aligned. 150 views::View* right_aligned_button = new views::View(); 151 views::BoxLayout* right_aligned_horizontal_layout = 152 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); 153 right_aligned_horizontal_layout->set_main_axis_alignment( 154 views::BoxLayout::MAIN_AXIS_ALIGNMENT_END); 155 right_aligned_button->SetLayoutManager(right_aligned_horizontal_layout); 156 right_aligned_button->AddChildView(revoke_file_permissions_button_); 157 158 views::View* vertical_stack = CreateVerticalStack(); 159 vertical_stack->AddChildView(retained_files_heading_); 160 vertical_stack->AddChildView(retained_files_list_); 161 vertical_stack->AddChildView(right_aligned_button); 162 163 AddChildView(vertical_stack); 164 } 165} 166 167void AppInfoPermissionsPanel::ButtonPressed(views::Button* sender, 168 const ui::Event& event) { 169 if (sender == revoke_file_permissions_button_) { 170 RevokeFilePermissions(); 171 } else { 172 NOTREACHED(); 173 } 174} 175 176const std::vector<base::string16> 177AppInfoPermissionsPanel::GetActivePermissionMessages() const { 178 return app_->permissions_data()->GetPermissionMessageStrings(); 179} 180 181const std::vector<base::string16> 182AppInfoPermissionsPanel::GetRetainedFilePaths() const { 183 std::vector<base::string16> retained_file_paths; 184 if (app_->permissions_data()->HasAPIPermission( 185 extensions::APIPermission::kFileSystem)) { 186 std::vector<apps::SavedFileEntry> retained_file_entries = 187 apps::SavedFilesService::Get(profile_)->GetAllFileEntries(app_->id()); 188 for (std::vector<apps::SavedFileEntry>::const_iterator it = 189 retained_file_entries.begin(); 190 it != retained_file_entries.end(); 191 ++it) { 192 retained_file_paths.push_back(it->path.LossyDisplayName()); 193 } 194 } 195 return retained_file_paths; 196} 197 198void AppInfoPermissionsPanel::RevokeFilePermissions() { 199 apps::SavedFilesService::Get(profile_)->ClearQueue(app_); 200 201 // TODO(benwells): Fix this to call something like 202 // AppLoadService::RestartApplicationIfRunning. 203 if (apps::AppRestoreService::Get(profile_)->IsAppRestorable(app_->id())) 204 apps::AppLoadService::Get(profile_)->RestartApplication(app_->id()); 205 206 GetWidget()->Close(); 207} 208