blob: ceab84f1519e86f2dd073fc804f686e8640a7062 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.h"
#include <string>
#include <vector>
#include "apps/app_load_service.h"
#include "apps/app_restore_service.h"
#include "apps/saved_files_service.h"
#include "base/files/file_path.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permissions_data.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
AppInfoPermissionsPanel::AppInfoPermissionsPanel(
Profile* profile,
const extensions::Extension* app)
: AppInfoPanel(profile, app),
active_permissions_heading_(NULL),
active_permissions_list_(NULL),
retained_files_heading_(NULL),
retained_files_list_(NULL),
revoke_file_permissions_button_(NULL) {
// Create UI elements.
CreateActivePermissionsControl();
CreateRetainedFilesControl();
// Layout elements.
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical,
0,
0,
views::kUnrelatedControlVerticalSpacing));
LayoutActivePermissionsControl();
LayoutRetainedFilesControl();
}
AppInfoPermissionsPanel::~AppInfoPermissionsPanel() {
// Destroy view children before their models.
RemoveAllChildViews(true);
}
// Given a list of strings, returns a view containing a list of these strings
// as bulleted items.
views::View* AppInfoPermissionsPanel::CreateBulletedListView(
const std::vector<base::string16>& messages,
bool allow_multiline,
gfx::ElideBehavior elide_behavior) {
const int kSpacingBetweenBulletAndStartOfText = 5;
views::View* list_view = new views::View();
views::GridLayout* layout = new views::GridLayout(list_view);
list_view->SetLayoutManager(layout);
// Create 2 columns: one for the bullet, one for the bullet text.
static const int kColumnSetId = 1;
views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
column_set->AddColumn(views::GridLayout::FILL,
views::GridLayout::LEADING,
0,
views::GridLayout::USE_PREF,
0,
0);
column_set->AddPaddingColumn(0, kSpacingBetweenBulletAndStartOfText);
column_set->AddColumn(views::GridLayout::FILL,
views::GridLayout::LEADING,
1,
views::GridLayout::USE_PREF,
0,
0);
for (std::vector<base::string16>::const_iterator it = messages.begin();
it != messages.end();
++it) {
views::Label* permission_label = new views::Label(*it);
permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
if (allow_multiline)
permission_label->SetMultiLine(true);
else
permission_label->SetElideBehavior(elide_behavior);
// Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text.
views::Label* bullet_label = new views::Label(l10n_util::GetStringFUTF16(
IDS_EXTENSION_PERMISSION_LINE, base::string16()));
// Add a padding row before every item except the first
if (it != messages.begin())
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
layout->StartRow(1, kColumnSetId);
layout->AddView(bullet_label);
layout->AddView(permission_label);
}
return list_view;
}
void AppInfoPermissionsPanel::CreateActivePermissionsControl() {
std::vector<base::string16> permission_strings =
GetActivePermissionMessages();
if (permission_strings.empty()) {
views::Label* no_permissions_text = new views::Label(
l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_NO_PERMISSIONS_TEXT));
no_permissions_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
active_permissions_list_ = no_permissions_text;
} else {
active_permissions_heading_ = CreateHeading(l10n_util::GetStringUTF16(
IDS_APPLICATION_INFO_ACTIVE_PERMISSIONS_TEXT));
active_permissions_list_ =
CreateBulletedListView(permission_strings, true, gfx::TRUNCATE);
}
}
void AppInfoPermissionsPanel::CreateRetainedFilesControl() {
const std::vector<base::string16> retained_file_permission_messages =
GetRetainedFilePaths();
if (!retained_file_permission_messages.empty()) {
revoke_file_permissions_button_ = new views::LabelButton(
this,
l10n_util::GetStringUTF16(
IDS_APPLICATION_INFO_REVOKE_RETAINED_FILE_PERMISSIONS_BUTTON_TEXT));
revoke_file_permissions_button_->SetStyle(views::Button::STYLE_BUTTON);
retained_files_heading_ = CreateHeading(l10n_util::GetStringUTF16(
IDS_APPLICATION_INFO_RETAINED_FILE_PERMISSIONS_TEXT));
retained_files_list_ = CreateBulletedListView(
retained_file_permission_messages, false, gfx::ELIDE_MIDDLE);
}
}
void AppInfoPermissionsPanel::LayoutActivePermissionsControl() {
if (active_permissions_list_) {
views::View* vertical_stack = CreateVerticalStack();
if (active_permissions_heading_)
vertical_stack->AddChildView(active_permissions_heading_);
vertical_stack->AddChildView(active_permissions_list_);
AddChildView(vertical_stack);
}
}
void AppInfoPermissionsPanel::LayoutRetainedFilesControl() {
if (retained_files_list_) {
DCHECK(retained_files_heading_);
DCHECK(revoke_file_permissions_button_);
// Add a sub-view so the revoke button is right-aligned.
views::View* right_aligned_button = new views::View();
views::BoxLayout* right_aligned_horizontal_layout =
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
right_aligned_horizontal_layout->set_main_axis_alignment(
views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
right_aligned_button->SetLayoutManager(right_aligned_horizontal_layout);
right_aligned_button->AddChildView(revoke_file_permissions_button_);
views::View* vertical_stack = CreateVerticalStack();
vertical_stack->AddChildView(retained_files_heading_);
vertical_stack->AddChildView(retained_files_list_);
vertical_stack->AddChildView(right_aligned_button);
AddChildView(vertical_stack);
}
}
void AppInfoPermissionsPanel::ButtonPressed(views::Button* sender,
const ui::Event& event) {
if (sender == revoke_file_permissions_button_) {
RevokeFilePermissions();
} else {
NOTREACHED();
}
}
const std::vector<base::string16>
AppInfoPermissionsPanel::GetActivePermissionMessages() const {
return app_->permissions_data()->GetPermissionMessageStrings();
}
const std::vector<base::string16>
AppInfoPermissionsPanel::GetRetainedFilePaths() const {
std::vector<base::string16> retained_file_paths;
if (app_->permissions_data()->HasAPIPermission(
extensions::APIPermission::kFileSystem)) {
std::vector<apps::SavedFileEntry> retained_file_entries =
apps::SavedFilesService::Get(profile_)->GetAllFileEntries(app_->id());
for (std::vector<apps::SavedFileEntry>::const_iterator it =
retained_file_entries.begin();
it != retained_file_entries.end();
++it) {
retained_file_paths.push_back(it->path.LossyDisplayName());
}
}
return retained_file_paths;
}
void AppInfoPermissionsPanel::RevokeFilePermissions() {
apps::SavedFilesService::Get(profile_)->ClearQueue(app_);
// TODO(benwells): Fix this to call something like
// AppLoadService::RestartApplicationIfRunning.
if (apps::AppRestoreService::Get(profile_)->IsAppRestorable(app_->id()))
apps::AppLoadService::Get(profile_)->RestartApplication(app_->id());
GetWidget()->Close();
}