Commit c58f78fe authored by sashab@chromium.org's avatar sashab@chromium.org

Extend App Info dialog to include app shortcut and list of permissions

Added a list of permissions to the app info dialog, as well as the app's
shortcut icon and some basic app information (name, version and description).

Context menu option to open the dialog is still behind the flag
--enable-app-list-app-info.

BUG=266739

Review URL: https://codereview.chromium.org/146583010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251954 0039d316-1c4b-4281-b951-d872f2087c98
parent 5b53c034
...@@ -4,10 +4,18 @@ ...@@ -4,10 +4,18 @@
#include "chrome/browser/ui/views/apps/app_info_dialog_views.h" #include "chrome/browser/ui/views/apps/app_info_dialog_views.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/image_loader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/apps/app_info_dialog.h" #include "chrome/browser/ui/apps/app_info_dialog.h"
#include "chrome/browser/ui/views/constrained_window_views.h" #include "chrome/browser/ui/views/constrained_window_views.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/permissions/permission_message_provider.h"
#include "extensions/common/permissions/permission_set.h"
#include "grit/generated_resources.h" #include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
...@@ -15,6 +23,9 @@ ...@@ -15,6 +23,9 @@
#include "ui/views/layout/layout_constants.h" #include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
// Size of extension icon in top left of dialog.
const int kIconSize = 64;
void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window, void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window,
Profile* profile, Profile* profile,
const extensions::Extension* app, const extensions::Extension* app,
...@@ -23,6 +34,67 @@ void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window, ...@@ -23,6 +34,67 @@ void ShowChromeAppInfoDialog(gfx::NativeWindow parent_window,
parent_window)->Show(); parent_window)->Show();
} }
PermissionsScrollView::PermissionsScrollView(int min_height,
int max_height,
const extensions::Extension* app)
: message_center::BoundedScrollView(min_height, max_height) {
inner_scrollable_view = new views::View();
this->SetContents(inner_scrollable_view);
// Get the permission messages for the app
std::vector<base::string16> permission_messages =
extensions::PermissionMessageProvider::Get()->GetWarningMessages(
app->GetActivePermissions(), app->GetType());
// Create the layout
views::GridLayout* layout =
views::GridLayout::CreatePanel(inner_scrollable_view);
inner_scrollable_view->SetLayoutManager(layout);
// Create 2 columns: one for the bullet, one for the bullet text
static const int kPermissionBulletsColumnSetId = 1;
views::ColumnSet* permission_bullets_column_set =
layout->AddColumnSet(kPermissionBulletsColumnSetId);
permission_bullets_column_set->AddPaddingColumn(0, 10);
permission_bullets_column_set->AddColumn(views::GridLayout::LEADING,
views::GridLayout::LEADING,
0,
views::GridLayout::USE_PREF,
0, // no fixed width
0);
permission_bullets_column_set->AddPaddingColumn(0, 5);
permission_bullets_column_set->AddColumn(views::GridLayout::LEADING,
views::GridLayout::LEADING,
0,
views::GridLayout::USE_PREF,
0, // no fixed width
0);
// Add permissions to scrollable view
for (std::vector<base::string16>::const_iterator it =
permission_messages.begin();
it != permission_messages.end();
++it) {
views::Label* permission_label = new views::Label(*it);
permission_label->SetMultiLine(true);
permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
permission_label->SizeToFit(250);
layout->StartRow(0, kPermissionBulletsColumnSetId);
// Extract only the bullet from the IDS_EXTENSION_PERMISSION_LINE text.
layout->AddView(new views::Label(l10n_util::GetStringFUTF16(
IDS_EXTENSION_PERMISSION_LINE, base::string16())));
// Place the text second, so multi-lined permissions line up below the
// bullet.
layout->AddView(permission_label);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
}
}
PermissionsScrollView::~PermissionsScrollView() {}
AppInfoView::AppInfoView(Profile* profile, AppInfoView::AppInfoView(Profile* profile,
const extensions::Extension* app, const extensions::Extension* app,
const base::Closure& close_callback) const base::Closure& close_callback)
...@@ -30,7 +102,8 @@ AppInfoView::AppInfoView(Profile* profile, ...@@ -30,7 +102,8 @@ AppInfoView::AppInfoView(Profile* profile,
app_name_label(NULL), app_name_label(NULL),
app_description_label(NULL), app_description_label(NULL),
app_(app), app_(app),
close_callback_(close_callback) { close_callback_(close_callback),
weak_ptr_factory_(this) {
// Create controls // Create controls
app_name_label = new views::Label(base::UTF8ToUTF16(app_->name())); app_name_label = new views::Label(base::UTF8ToUTF16(app_->name()));
app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
...@@ -39,25 +112,90 @@ AppInfoView::AppInfoView(Profile* profile, ...@@ -39,25 +112,90 @@ AppInfoView::AppInfoView(Profile* profile,
new views::Label(base::UTF8ToUTF16(app_->description())); new views::Label(base::UTF8ToUTF16(app_->description()));
app_description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); app_description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
// Layout controls app_version_label =
new views::Label(base::UTF8ToUTF16(app_->VersionString()));
app_version_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
app_icon = new views::ImageView();
app_icon->SetImageSize(gfx::Size(kIconSize, kIconSize));
permission_list_heading = new views::Label(
l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_CAN_ACCESS));
permission_list_heading->SetHorizontalAlignment(gfx::ALIGN_LEFT);
permissions_scroll_view = new PermissionsScrollView(0, 100, app);
// Load the app icon asynchronously. For the response, check OnImageLoaded.
extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
app,
extension_misc::EXTENSION_ICON_LARGE,
ExtensionIconSet::MATCH_BIGGER);
int pixel_size =
static_cast<int>(kIconSize * gfx::ImageSkia::GetMaxSupportedScale());
extensions::ImageLoader::Get(profile)
->LoadImageAsync(app,
image,
gfx::Size(pixel_size, pixel_size),
base::Bind(&AppInfoView::OnAppImageLoaded, AsWeakPtr()));
// Create the layout
views::GridLayout* layout = views::GridLayout::CreatePanel(this); views::GridLayout* layout = views::GridLayout::CreatePanel(this);
SetLayoutManager(layout); SetLayoutManager(layout);
// Header column set with app icon and information
static const int kHeaderColumnSetId = 0; static const int kHeaderColumnSetId = 0;
views::ColumnSet* column_set = layout->AddColumnSet(kHeaderColumnSetId); views::ColumnSet* header_column_set =
column_set->AddColumn(views::GridLayout::FILL, layout->AddColumnSet(kHeaderColumnSetId);
views::GridLayout::CENTER, header_column_set->AddColumn(views::GridLayout::FILL,
100.0f, views::GridLayout::CENTER,
views::GridLayout::FIXED, 0,
0, views::GridLayout::FIXED,
0); kIconSize,
0);
header_column_set->AddPaddingColumn(0,
views::kRelatedControlHorizontalSpacing);
header_column_set->AddColumn(views::GridLayout::FILL,
views::GridLayout::CENTER,
100.0f,
views::GridLayout::FIXED,
0,
0);
// Column set with scrollable permissions
static const int kPermissionsColumnSetId = 1;
views::ColumnSet* permissions_column_set =
layout->AddColumnSet(kPermissionsColumnSetId);
permissions_column_set->AddColumn(views::GridLayout::FILL,
views::GridLayout::CENTER,
100.0f,
views::GridLayout::FIXED,
0,
0);
// The app icon takes up 3 rows
layout->StartRow(0, kHeaderColumnSetId); layout->StartRow(0, kHeaderColumnSetId);
layout->AddView(app_icon, 1, 3);
// The app information fills up the right side of the icon
layout->AddView(app_name_label); layout->AddView(app_name_label);
layout->AddPaddingRow(0, views::kPanelSubVerticalSpacing);
layout->StartRow(0, kHeaderColumnSetId); layout->StartRow(0, kHeaderColumnSetId);
layout->SkipColumns(1);
layout->AddView(app_version_label);
layout->StartRow(0, kHeaderColumnSetId);
layout->SkipColumns(1);
layout->AddView(app_description_label); layout->AddView(app_description_label);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
layout->StartRow(0, kPermissionsColumnSetId);
layout->AddView(permission_list_heading);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
layout->StartRow(0, kPermissionsColumnSetId);
layout->AddView(permissions_scroll_view);
} }
AppInfoView::~AppInfoView() {} AppInfoView::~AppInfoView() {}
...@@ -83,9 +221,7 @@ base::string16 AppInfoView::GetDialogButtonLabel(ui::DialogButton button) ...@@ -83,9 +221,7 @@ base::string16 AppInfoView::GetDialogButtonLabel(ui::DialogButton button)
return views::DialogDelegateView::GetDialogButtonLabel(button); return views::DialogDelegateView::GetDialogButtonLabel(button);
} }
int AppInfoView::GetDialogButtons() const { int AppInfoView::GetDialogButtons() const { return ui::DIALOG_BUTTON_CANCEL; }
return ui::DIALOG_BUTTON_CANCEL;
}
bool AppInfoView::IsDialogButtonEnabled(ui::DialogButton button) const { bool AppInfoView::IsDialogButtonEnabled(ui::DialogButton button) const {
return true; return true;
...@@ -98,3 +234,14 @@ ui::ModalType AppInfoView::GetModalType() const { ...@@ -98,3 +234,14 @@ ui::ModalType AppInfoView::GetModalType() const {
base::string16 AppInfoView::GetWindowTitle() const { base::string16 AppInfoView::GetWindowTitle() const {
return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_TITLE); return l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_TITLE);
} }
void AppInfoView::OnAppImageLoaded(const gfx::Image& image) {
const SkBitmap* bitmap = image.ToSkBitmap();
if (image.IsEmpty()) {
bitmap = &extensions::IconsInfo::GetDefaultAppIcon()
.GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale())
.sk_bitmap();
}
app_icon->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap));
}
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#define CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_VIEWS_H_ #define CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_VIEWS_H_
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "chrome/browser/shell_integration.h"
#include "ui/message_center/views/bounded_scroll_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/window/dialog_delegate.h" #include "ui/views/window/dialog_delegate.h"
class Profile; class Profile;
...@@ -18,8 +21,22 @@ namespace views { ...@@ -18,8 +21,22 @@ namespace views {
class Label; class Label;
} }
// A scrollable list of permissions for the given app.
class PermissionsScrollView : public message_center::BoundedScrollView {
public:
PermissionsScrollView(int min_height,
int max_height,
const extensions::Extension* app);
private:
virtual ~PermissionsScrollView();
views::View* inner_scrollable_view;
};
// View the information about a particular chrome application. // View the information about a particular chrome application.
class AppInfoView : public views::DialogDelegateView { class AppInfoView : public views::DialogDelegateView,
public base::SupportsWeakPtr<AppInfoView> {
public: public:
AppInfoView(Profile* profile, AppInfoView(Profile* profile,
const extensions::Extension* app, const extensions::Extension* app,
...@@ -42,16 +59,25 @@ class AppInfoView : public views::DialogDelegateView { ...@@ -42,16 +59,25 @@ class AppInfoView : public views::DialogDelegateView {
virtual ui::ModalType GetModalType() const OVERRIDE; virtual ui::ModalType GetModalType() const OVERRIDE;
virtual base::string16 GetWindowTitle() const OVERRIDE; virtual base::string16 GetWindowTitle() const OVERRIDE;
// Called when the app's icon is loaded.
void OnAppImageLoaded(const gfx::Image& image);
// Profile in which the shortcuts will be created. // Profile in which the shortcuts will be created.
Profile* profile_; Profile* profile_;
// UI elements on the dialog. // UI elements on the dialog.
views::Label* app_name_label; views::Label* app_name_label;
views::Label* app_description_label; views::Label* app_description_label;
views::Label* app_version_label;
views::ImageView* app_icon;
views::Label* permission_list_heading;
PermissionsScrollView* permissions_scroll_view;
const extensions::Extension* app_; const extensions::Extension* app_;
base::Closure close_callback_; base::Closure close_callback_;
base::WeakPtrFactory<AppInfoView> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AppInfoView); DISALLOW_COPY_AND_ASSIGN(AppInfoView);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment