app_info_permissions_panel.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 const int kSpacingBetweenBulletAndStartOfText = 5; 60 views::View* list_view = CreateVerticalStack(); 61 62 for (std::vector<base::string16>::const_iterator it = messages.begin(); 63 it != messages.end(); 64 ++it) { 65 views::Label* permission_label = new views::Label(*it); 66 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 67 permission_label->SetMultiLine(true); 68 69 // Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text, and 70 // place it in it's own view so it doesn't align vertically with the 71 // multilined permissions text. 72 views::Label* bullet_label = new views::Label(l10n_util::GetStringFUTF16( 73 IDS_EXTENSION_PERMISSION_LINE, base::string16())); 74 views::View* bullet_label_top_aligned = CreateVerticalStack(); 75 bullet_label_top_aligned->AddChildView(bullet_label); 76 77 // Place the bullet and the text so all permissions line up at the bullet. 78 views::View* bulleted_list_item = new views::View(); 79 bulleted_list_item->SetLayoutManager( 80 new views::BoxLayout(views::BoxLayout::kHorizontal, 81 0, 82 0, 83 kSpacingBetweenBulletAndStartOfText)); 84 bulleted_list_item->AddChildView(bullet_label_top_aligned); 85 bulleted_list_item->AddChildView(permission_label); 86 87 list_view->AddChildView(bulleted_list_item); 88 } 89 90 return list_view; 91} 92 93void AppInfoPermissionsPanel::CreateActivePermissionsControl() { 94 std::vector<base::string16> permission_strings = 95 GetActivePermissionMessages(); 96 if (permission_strings.empty()) { 97 views::Label* no_permissions_text = new views::Label( 98 l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_NO_PERMISSIONS_TEXT)); 99 no_permissions_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 100 active_permissions_list_ = no_permissions_text; 101 } else { 102 active_permissions_heading_ = CreateHeading(l10n_util::GetStringUTF16( 103 IDS_APPLICATION_INFO_ACTIVE_PERMISSIONS_TEXT)); 104 active_permissions_list_ = CreateBulletedListView(permission_strings); 105 } 106} 107 108void AppInfoPermissionsPanel::CreateRetainedFilesControl() { 109 const std::vector<base::string16> retained_file_permission_messages = 110 GetRetainedFilePaths(); 111 112 if (!retained_file_permission_messages.empty()) { 113 revoke_file_permissions_button_ = new views::LabelButton( 114 this, 115 l10n_util::GetStringUTF16( 116 IDS_APPLICATION_INFO_REVOKE_RETAINED_FILE_PERMISSIONS_BUTTON_TEXT)); 117 revoke_file_permissions_button_->SetStyle(views::Button::STYLE_BUTTON); 118 119 retained_files_heading_ = CreateHeading(l10n_util::GetStringUTF16( 120 IDS_APPLICATION_INFO_RETAINED_FILE_PERMISSIONS_TEXT)); 121 retained_files_list_ = 122 CreateBulletedListView(retained_file_permission_messages); 123 } 124} 125 126void AppInfoPermissionsPanel::LayoutActivePermissionsControl() { 127 if (active_permissions_list_) { 128 views::View* vertical_stack = CreateVerticalStack(); 129 if (active_permissions_heading_) 130 vertical_stack->AddChildView(active_permissions_heading_); 131 vertical_stack->AddChildView(active_permissions_list_); 132 133 AddChildView(vertical_stack); 134 } 135} 136 137void AppInfoPermissionsPanel::LayoutRetainedFilesControl() { 138 if (retained_files_list_) { 139 DCHECK(retained_files_heading_); 140 DCHECK(revoke_file_permissions_button_); 141 142 // Add a sub-view so the revoke button is right-aligned. 143 views::View* right_aligned_button = new views::View(); 144 views::BoxLayout* right_aligned_horizontal_layout = 145 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); 146 right_aligned_horizontal_layout->set_main_axis_alignment( 147 views::BoxLayout::MAIN_AXIS_ALIGNMENT_END); 148 right_aligned_button->SetLayoutManager(right_aligned_horizontal_layout); 149 right_aligned_button->AddChildView(revoke_file_permissions_button_); 150 151 views::View* vertical_stack = CreateVerticalStack(); 152 vertical_stack->AddChildView(retained_files_heading_); 153 vertical_stack->AddChildView(retained_files_list_); 154 vertical_stack->AddChildView(right_aligned_button); 155 156 AddChildView(vertical_stack); 157 } 158} 159 160void AppInfoPermissionsPanel::ButtonPressed(views::Button* sender, 161 const ui::Event& event) { 162 if (sender == revoke_file_permissions_button_) { 163 RevokeFilePermissions(); 164 } else { 165 NOTREACHED(); 166 } 167} 168 169const std::vector<base::string16> 170AppInfoPermissionsPanel::GetActivePermissionMessages() const { 171 return app_->permissions_data()->GetPermissionMessageStrings(); 172} 173 174const std::vector<base::string16> 175AppInfoPermissionsPanel::GetRetainedFilePaths() const { 176 std::vector<base::string16> retained_file_paths; 177 if (app_->permissions_data()->HasAPIPermission( 178 extensions::APIPermission::kFileSystem)) { 179 std::vector<apps::SavedFileEntry> retained_file_entries = 180 apps::SavedFilesService::Get(profile_)->GetAllFileEntries(app_->id()); 181 for (std::vector<apps::SavedFileEntry>::const_iterator it = 182 retained_file_entries.begin(); 183 it != retained_file_entries.end(); 184 ++it) { 185 retained_file_paths.push_back(it->path.LossyDisplayName()); 186 } 187 } 188 return retained_file_paths; 189} 190 191void AppInfoPermissionsPanel::RevokeFilePermissions() { 192 apps::SavedFilesService::Get(profile_)->ClearQueue(app_); 193 194 // TODO(benwells): Fix this to call something like 195 // AppLoadService::RestartApplicationIfRunning. 196 if (apps::AppRestoreService::Get(profile_)->IsAppRestorable(app_->id())) 197 apps::AppLoadService::Get(profile_)->RestartApplication(app_->id()); 198 199 GetWidget()->Close(); 200} 201