Home | History | Annotate | Download | only in app_info_dialog
      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/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"
     25 
     26 AppInfoPermissionsPanel::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 
     50 AppInfoPermissionsPanel::~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.
     57 views::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 
     63   views::View* list_view = new views::View();
     64   views::GridLayout* layout = new views::GridLayout(list_view);
     65   list_view->SetLayoutManager(layout);
     66 
     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,
     72                         0,
     73                         views::GridLayout::USE_PREF,
     74                         0,
     75                         0);
     76   column_set->AddPaddingColumn(0, kSpacingBetweenBulletAndStartOfText);
     77   column_set->AddColumn(views::GridLayout::FILL,
     78                         views::GridLayout::LEADING,
     79                         1,
     80                         views::GridLayout::USE_PREF,
     81                         0,
     82                         0);
     83 
     84   for (std::vector<base::string16>::const_iterator it = messages.begin();
     85        it != messages.end();
     86        ++it) {
     87     views::Label* permission_label = new views::Label(*it);
     88     permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     89 
     90     if (allow_multiline)
     91       permission_label->SetMultiLine(true);
     92     else
     93       permission_label->SetElideBehavior(elide_behavior);
     94 
     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()));
     98 
     99     // Add a padding row before every item except the first
    100     if (it != messages.begin())
    101       layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    102 
    103     layout->StartRow(1, kColumnSetId);
    104     layout->AddView(bullet_label);
    105     layout->AddView(permission_label);
    106   }
    107 
    108   return list_view;
    109 }
    110 
    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;
    119   } else {
    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);
    124   }
    125 }
    126 
    127 void AppInfoPermissionsPanel::CreateRetainedFilesControl() {
    128   const std::vector<base::string16> retained_file_permission_messages =
    129       GetRetainedFilePaths();
    130 
    131   if (!retained_file_permission_messages.empty()) {
    132     revoke_file_permissions_button_ = new views::LabelButton(
    133         this,
    134         l10n_util::GetStringUTF16(
    135             IDS_APPLICATION_INFO_REVOKE_RETAINED_FILE_PERMISSIONS_BUTTON_TEXT));
    136     revoke_file_permissions_button_->SetStyle(views::Button::STYLE_BUTTON);
    137 
    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);
    142   }
    143 }
    144 
    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_);
    151 
    152     AddChildView(vertical_stack);
    153   }
    154 }
    155 
    156 void AppInfoPermissionsPanel::LayoutRetainedFilesControl() {
    157   if (retained_files_list_) {
    158     DCHECK(retained_files_heading_);
    159     DCHECK(revoke_file_permissions_button_);
    160 
    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_);
    169 
    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);
    174 
    175     AddChildView(vertical_stack);
    176   }
    177 }
    178 
    179 void AppInfoPermissionsPanel::ButtonPressed(views::Button* sender,
    180                                             const ui::Event& event) {
    181   if (sender == revoke_file_permissions_button_) {
    182     RevokeFilePermissions();
    183   } else {
    184     NOTREACHED();
    185   }
    186 }
    187 
    188 const std::vector<base::string16>
    189 AppInfoPermissionsPanel::GetActivePermissionMessages() const {
    190   return app_->permissions_data()->GetPermissionMessageStrings();
    191 }
    192 
    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();
    203          ++it) {
    204       retained_file_paths.push_back(it->path.LossyDisplayName());
    205     }
    206   }
    207   return retained_file_paths;
    208 }
    209 
    210 void AppInfoPermissionsPanel::RevokeFilePermissions() {
    211   apps::SavedFilesService::Get(profile_)->ClearQueue(app_);
    212   apps::AppLoadService::Get(profile_)->RestartApplicationIfRunning(app_->id());
    213 
    214   GetWidget()->Close();
    215 }
    216