| Index: chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
|
| diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..584d51e631c5f9dfefb0ddecef2ddfc9d948689d
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
|
| @@ -0,0 +1,323 @@
|
| +// 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_summary_panel.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/extensions/extension_service.h"
|
| +#include "chrome/browser/extensions/extension_uninstall_dialog.h"
|
| +#include "chrome/browser/extensions/extension_util.h"
|
| +#include "chrome/browser/extensions/image_loader.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/browser_navigator.h"
|
| +#include "chrome/common/extensions/extension_constants.h"
|
| +#include "chrome/common/extensions/manifest_url_handler.h"
|
| +#include "extensions/browser/extension_system.h"
|
| +#include "extensions/browser/management_policy.h"
|
| +#include "extensions/common/constants.h"
|
| +#include "extensions/common/extension.h"
|
| +#include "extensions/common/extension_icon_set.h"
|
| +#include "extensions/common/extension_resource.h"
|
| +#include "extensions/common/manifest_handlers/icons_handler.h"
|
| +#include "extensions/common/manifest_handlers/shared_module_info.h"
|
| +#include "grit/generated_resources.h"
|
| +#include "net/base/url_util.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/geometry/size.h"
|
| +#include "ui/gfx/image/image.h"
|
| +#include "ui/gfx/image/image_skia.h"
|
| +#include "ui/gfx/image/image_skia_rep.h"
|
| +#include "ui/gfx/native_widget_types.h"
|
| +#include "ui/gfx/text_constants.h"
|
| +#include "ui/views/controls/image_view.h"
|
| +#include "ui/views/controls/label.h"
|
| +#include "ui/views/controls/link.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/widget/widget.h"
|
| +#include "url/gurl.h"
|
| +
|
| +// Size of extension icon in top left of dialog.
|
| +const int kIconSize = 64;
|
| +
|
| +AppInfoSummaryPanel::AppInfoSummaryPanel(gfx::NativeWindow parent_window,
|
| + Profile* profile,
|
| + const extensions::Extension* app,
|
| + const base::Closure& close_callback)
|
| + : app_icon_(NULL),
|
| + app_name_label_(NULL),
|
| + app_version_label_(NULL),
|
| + view_in_store_link_(NULL),
|
| + remove_link_(NULL),
|
| + licenses_link_(NULL),
|
| + parent_window_(parent_window),
|
| + profile_(profile),
|
| + app_(app),
|
| + close_callback_(close_callback),
|
| + weak_ptr_factory_(this) {
|
| + CreateControls();
|
| +
|
| + SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kHorizontal,
|
| + views::kButtonHEdgeMargin,
|
| + views::kButtonVEdgeMargin,
|
| + views::kRelatedControlHorizontalSpacing));
|
| +
|
| + LayoutControls();
|
| +}
|
| +
|
| +AppInfoSummaryPanel::~AppInfoSummaryPanel() {
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::CreateControls() {
|
| + app_name_label_ =
|
| + new views::Label(base::UTF8ToUTF16(app_->name()),
|
| + ui::ResourceBundle::GetSharedInstance().GetFontList(
|
| + ui::ResourceBundle::BoldFont));
|
| + app_name_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| +
|
| + // The version number doesn't make sense for bookmarked apps.
|
| + if (!app_->from_bookmark()) {
|
| + 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));
|
| + LoadAppImageAsync();
|
| +
|
| + if (CanShowAppInWebStore()) {
|
| + view_in_store_link_ = new views::Link(
|
| + l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK));
|
| + view_in_store_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + view_in_store_link_->set_listener(this);
|
| + }
|
| +
|
| + if (CanUninstallApp()) {
|
| + remove_link_ = new views::Link(
|
| + l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT));
|
| + remove_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + remove_link_->set_listener(this);
|
| + }
|
| +
|
| + if (CanDisplayLicenses()) {
|
| + licenses_link_ = new views::Link(
|
| + l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LICENSES_BUTTON_TEXT));
|
| + licenses_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + licenses_link_->set_listener(this);
|
| + }
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::LayoutAppNameAndVersionInto(
|
| + views::View* parent_view) {
|
| + views::View* view = new views::View();
|
| + // We need a horizontal BoxLayout here to ensure that the GridLayout does
|
| + // not stretch beyond the size of its content.
|
| + view->SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
|
| +
|
| + views::View* container_view = new views::View();
|
| + view->AddChildView(container_view);
|
| + views::GridLayout* layout = new views::GridLayout(container_view);
|
| + container_view->SetLayoutManager(layout);
|
| +
|
| + static const int kColumnId = 1;
|
| + views::ColumnSet* column_set = layout->AddColumnSet(kColumnId);
|
| + column_set->AddColumn(views::GridLayout::LEADING,
|
| + views::GridLayout::LEADING,
|
| + 1, // Stretch the title to as wide as needed
|
| + views::GridLayout::USE_PREF,
|
| + 0,
|
| + 0);
|
| + column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
|
| + column_set->AddColumn(views::GridLayout::LEADING,
|
| + views::GridLayout::LEADING,
|
| + 0, // Do not stretch the version
|
| + views::GridLayout::USE_PREF,
|
| + 0,
|
| + 0);
|
| +
|
| + layout->StartRow(1, kColumnId);
|
| + layout->AddView(app_name_label_);
|
| + if (app_version_label_)
|
| + layout->AddView(app_version_label_);
|
| +
|
| + parent_view->AddChildView(view);
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::LayoutControls() {
|
| + AddChildView(app_icon_);
|
| +
|
| + if (!app_version_label_ && !view_in_store_link_) {
|
| + // If there's no link to the webstore _and_ no version, allow the app's name
|
| + // to take up multiple lines.
|
| + app_name_label_->SetMultiLine(true);
|
| + AddChildView(app_name_label_);
|
| + } else {
|
| + // Create a vertical container to store the app's name and info.
|
| + views::View* vertical_info_container = new views::View();
|
| + views::BoxLayout* vertical_container_layout =
|
| + new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
|
| + vertical_container_layout->set_main_axis_alignment(
|
| + views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
|
| + vertical_info_container->SetLayoutManager(vertical_container_layout);
|
| +
|
| + // Create a horizontal container to store the app's links.
|
| + views::View* horizontal_links_container = new views::View();
|
| + horizontal_links_container->SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 3));
|
| +
|
| + if (view_in_store_link_)
|
| + horizontal_links_container->AddChildView(view_in_store_link_);
|
| + if (remove_link_)
|
| + horizontal_links_container->AddChildView(remove_link_);
|
| + if (licenses_link_)
|
| + horizontal_links_container->AddChildView(licenses_link_);
|
| +
|
| + // First line: title and (possibly) version. Second line: links (if any).
|
| + if (app_version_label_) {
|
| + LayoutAppNameAndVersionInto(vertical_info_container);
|
| + } else {
|
| + vertical_info_container->AddChildView(app_name_label_);
|
| + }
|
| +
|
| + if (vertical_info_container->child_count() > 0)
|
| + vertical_info_container->AddChildView(horizontal_links_container);
|
| +
|
| + AddChildView(vertical_info_container);
|
| + }
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::LinkClicked(views::Link* source, int event_flags) {
|
| + if (source == view_in_store_link_) {
|
| + ShowAppInWebStore();
|
| + } else if (source == remove_link_) {
|
| + UninstallApp();
|
| + } else if (source == licenses_link_) {
|
| + DisplayLicenses();
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::ExtensionUninstallAccepted() {
|
| + ExtensionService* service =
|
| + extensions::ExtensionSystem::Get(profile_)->extension_service();
|
| + service->UninstallExtension(app_->id(), false, NULL);
|
| +
|
| + // Close the App Info dialog as well (which will free the dialog too).
|
| + GetWidget()->Close();
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::ExtensionUninstallCanceled() {
|
| + extension_uninstall_dialog_.reset();
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::LoadAppImageAsync() {
|
| + 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(&AppInfoSummaryPanel::OnAppImageLoaded, AsWeakPtr()));
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::OnAppImageLoaded(const gfx::Image& image) {
|
| + const SkBitmap* bitmap;
|
| + if (image.IsEmpty()) {
|
| + bitmap = &extensions::util::GetDefaultAppIcon()
|
| + .GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale())
|
| + .sk_bitmap();
|
| + } else {
|
| + bitmap = image.ToSkBitmap();
|
| + }
|
| +
|
| + app_icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap));
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::ShowAppInWebStore() const {
|
| + DCHECK(CanShowAppInWebStore());
|
| + const GURL url = extensions::ManifestURL::GetDetailsURL(app_);
|
| + DCHECK_NE(url, GURL::EmptyGURL());
|
| + chrome::NavigateParams params(
|
| + profile_,
|
| + net::AppendQueryParameter(url,
|
| + extension_urls::kWebstoreSourceField,
|
| + extension_urls::kLaunchSourceAppListInfoDialog),
|
| + content::PAGE_TRANSITION_LINK);
|
| + chrome::Navigate(¶ms);
|
| +}
|
| +
|
| +bool AppInfoSummaryPanel::CanShowAppInWebStore() const {
|
| + return app_->from_webstore();
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::UninstallApp() {
|
| + DCHECK(CanUninstallApp());
|
| + extension_uninstall_dialog_.reset(
|
| + extensions::ExtensionUninstallDialog::Create(profile_, NULL, this));
|
| + extension_uninstall_dialog_->ConfirmUninstall(app_);
|
| +}
|
| +
|
| +bool AppInfoSummaryPanel::CanUninstallApp() const {
|
| + return extensions::ExtensionSystem::Get(profile_)
|
| + ->management_policy()
|
| + ->UserMayModifySettings(app_, NULL);
|
| +}
|
| +
|
| +void AppInfoSummaryPanel::DisplayLicenses() {
|
| + // Find the first shared module for this app, and display it's options page
|
| + // as an 'about' link.
|
| + // TODO(sashab): Revisit UI layout once shared module usage becomes more
|
| + // common.
|
| + DCHECK(CanDisplayLicenses());
|
| + ExtensionService* service =
|
| + extensions::ExtensionSystem::Get(profile_)->extension_service();
|
| + DCHECK(service);
|
| + const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
|
| + extensions::SharedModuleInfo::GetImports(app_);
|
| + const extensions::Extension* imported_module =
|
| + service->GetExtensionById(imports[0].extension_id, true);
|
| + DCHECK(imported_module);
|
| +
|
| + GURL about_page = extensions::ManifestURL::GetOptionsPage(imported_module);
|
| + DCHECK(about_page != GURL::EmptyGURL());
|
| +
|
| + chrome::NavigateParams params(
|
| + profile_, about_page, content::PAGE_TRANSITION_LINK);
|
| + chrome::Navigate(¶ms);
|
| +}
|
| +
|
| +bool AppInfoSummaryPanel::CanDisplayLicenses() {
|
| + if (!extensions::SharedModuleInfo::ImportsModules(app_))
|
| + return false;
|
| +
|
| + ExtensionService* service =
|
| + extensions::ExtensionSystem::Get(profile_)->extension_service();
|
| + DCHECK(service);
|
| +
|
| + const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
|
| + extensions::SharedModuleInfo::GetImports(app_);
|
| + const extensions::Extension* imported_module =
|
| + service->GetExtensionById(imports[0].extension_id, true);
|
| + DCHECK(imported_module);
|
| +
|
| + GURL about_page = extensions::ManifestURL::GetOptionsPage(imported_module);
|
| + if (about_page == GURL::EmptyGURL())
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
|
|