Commit ded8aeb9 authored by sashab's avatar sashab Committed by Commit bot

Move the Developer Website and Licenses links in the App Info dialog

Move the Developer Website and Licenses links in the App Info dialog to
below the description, if they exist. Change the 'View in Webstore' link
to always display directly under the app name, even if a developer
website is already provided.

BUG=423252

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

Cr-Commit-Position: refs/heads/master@{#302538}
parent 2c646227
......@@ -9,7 +9,6 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/grit/generated_resources.h"
#include "extensions/browser/extension_system.h"
......@@ -19,7 +18,6 @@
#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 "extensions/common/manifest_url_handlers.h"
#include "net/base/url_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
......@@ -38,16 +36,12 @@
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/view.h"
#include "url/gurl.h"
namespace {
// Size of extension icon in top left of dialog.
const int kIconSize = 64;
// The horizontal spacing between the app's links in the header section.
const int kSpacingBetweenAppLinks = 3;
} // namespace
AppInfoHeaderPanel::AppInfoHeaderPanel(Profile* profile,
......@@ -55,8 +49,6 @@ AppInfoHeaderPanel::AppInfoHeaderPanel(Profile* profile,
: AppInfoPanel(profile, app),
app_icon_(NULL),
view_in_store_link_(NULL),
homepage_link_(NULL),
licenses_link_(NULL),
weak_ptr_factory_(this) {
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal,
......@@ -82,14 +74,13 @@ void AppInfoHeaderPanel::CreateControls() {
ui::ResourceBundle::MediumFont));
app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
if (!CanShowAppInWebStore() && !CanShowAppHomePage() &&
!CanDisplayLicenses()) {
// If there's no links, allow the app's name to take up multiple lines.
if (!CanShowAppInWebStore()) {
// If there's no link, allow the app's name to take up multiple lines.
// TODO(sashab): Limit the number of lines to 2.
app_name_label->SetMultiLine(true);
AddChildView(app_name_label);
} else {
// Create a vertical container to store the app's name and links.
// Create a vertical container to store the app's name and link.
views::View* vertical_info_container = new views::View();
views::BoxLayout* vertical_container_layout =
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
......@@ -98,49 +89,21 @@ void AppInfoHeaderPanel::CreateControls() {
vertical_info_container->SetLayoutManager(vertical_container_layout);
vertical_info_container->AddChildView(app_name_label);
// Create a horizontal container to store the app's links.
views::View* horizontal_links_container =
CreateHorizontalStack(kSpacingBetweenAppLinks);
// If the app/extension has a custom home page, display a link to the
// developer's homepage *instead of* a link to the webstore.
if (CanShowAppHomePage()) {
homepage_link_ = new views::Link(
l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_HOMEPAGE_LINK));
homepage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
homepage_link_->set_listener(this);
horizontal_links_container->AddChildView(homepage_link_);
} else if (CanShowAppInWebStore()) {
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);
horizontal_links_container->AddChildView(view_in_store_link_);
}
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);
horizontal_links_container->AddChildView(licenses_link_);
vertical_info_container->AddChildView(view_in_store_link_);
}
vertical_info_container->AddChildView(horizontal_links_container);
AddChildView(vertical_info_container);
}
}
void AppInfoHeaderPanel::LinkClicked(views::Link* source, int event_flags) {
if (source == view_in_store_link_) {
ShowAppInWebStore();
} else if (source == homepage_link_) {
ShowAppHomePage();
} else if (source == licenses_link_) {
DisplayLicenses();
} else {
NOTREACHED();
}
DCHECK_EQ(source, view_in_store_link_);
ShowAppInWebStore();
}
void AppInfoHeaderPanel::LoadAppImageAsync() {
......@@ -182,53 +145,3 @@ void AppInfoHeaderPanel::ShowAppInWebStore() {
bool AppInfoHeaderPanel::CanShowAppInWebStore() const {
return app_->from_webstore();
}
void AppInfoHeaderPanel::ShowAppHomePage() {
DCHECK(CanShowAppHomePage());
OpenLink(extensions::ManifestURL::GetHomepageURL(app_));
Close();
}
bool AppInfoHeaderPanel::CanShowAppHomePage() const {
return extensions::ManifestURL::SpecifiedHomepageURL(app_);
}
void AppInfoHeaderPanel::DisplayLicenses() {
DCHECK(CanDisplayLicenses());
for (const auto& license_url : GetLicenseUrls())
OpenLink(license_url);
Close();
}
bool AppInfoHeaderPanel::CanDisplayLicenses() const {
return !GetLicenseUrls().empty();
}
const std::vector<GURL> AppInfoHeaderPanel::GetLicenseUrls() const {
if (!extensions::SharedModuleInfo::ImportsModules(app_))
return std::vector<GURL>();
std::vector<GURL> license_urls;
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
DCHECK(service);
const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
extensions::SharedModuleInfo::GetImports(app_);
for (const auto& shared_module : imports) {
const extensions::Extension* imported_module =
service->GetExtensionById(shared_module.extension_id, true);
DCHECK(imported_module);
GURL about_page = extensions::ManifestURL::GetAboutPage(imported_module);
if (about_page != GURL::EmptyGURL())
license_urls.push_back(about_page);
}
return license_urls;
}
void AppInfoHeaderPanel::OpenLink(const GURL& url) {
DCHECK(!url.is_empty());
chrome::NavigateParams params(profile_, url, ui::PAGE_TRANSITION_LINK);
chrome::Navigate(&params);
}
......@@ -20,8 +20,6 @@ class Image;
namespace views {
class ImageView;
class Link;
class View;
}
// A small summary panel with the app's name, icon, version, and various links
......@@ -49,25 +47,9 @@ class AppInfoHeaderPanel : public AppInfoPanel,
void ShowAppInWebStore();
bool CanShowAppInWebStore() const;
// Opens the app's homepage URL as specified in the manifest. Must only be
// called if CanShowAppHomePage() returns true.
void ShowAppHomePage();
bool CanShowAppHomePage() const;
// Displays the licenses for the app. Must only be called if
// CanDisplayLicenses() returns true.
void DisplayLicenses();
bool CanDisplayLicenses() const;
const std::vector<GURL> GetLicenseUrls() const;
// Opens the given URL in a new browser tab.
void OpenLink(const GURL& url);
// UI elements on the dialog. Elements are NULL if they are not displayed.
views::ImageView* app_icon_;
views::Link* view_in_store_link_;
views::Link* homepage_link_;
views::Link* licenses_link_;
base::WeakPtrFactory<AppInfoHeaderPanel> weak_ptr_factory_;
......
......@@ -4,11 +4,13 @@
#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"
namespace {
......@@ -27,6 +29,12 @@ void AppInfoPanel::Close() {
GetWidget()->Close();
}
void AppInfoPanel::OpenLink(const GURL& url) {
DCHECK(!url.is_empty());
chrome::NavigateParams params(profile_, url, ui::PAGE_TRANSITION_LINK);
chrome::Navigate(&params);
}
views::Label* AppInfoPanel::CreateHeading(const base::string16& text) const {
views::Label* label = new views::Label(text);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
......
......@@ -28,6 +28,9 @@ class AppInfoPanel : public views::View {
// Closes the dialog.
void Close();
// Opens the given URL in a new browser tab.
void OpenLink(const GURL& url);
// Create a heading label with the given text.
views::Label* CreateHeading(const base::string16& text) const;
......
......@@ -22,11 +22,14 @@
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/manifest_url_handlers.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/text/bytes_formatting.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/link.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/view.h"
......@@ -128,6 +131,8 @@ AppInfoSummaryPanel::AppInfoSummaryPanel(Profile* profile,
const extensions::Extension* app)
: AppInfoPanel(profile, app),
size_value_(NULL),
homepage_link_(NULL),
licenses_link_(NULL),
launch_options_combobox_(NULL),
weak_ptr_factory_(this) {
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
......@@ -143,24 +148,48 @@ AppInfoSummaryPanel::~AppInfoSummaryPanel() {
RemoveAllChildViews(true);
}
void AppInfoSummaryPanel::AddDescriptionControl(views::View* vertical_stack) {
if (app_->description().empty())
return;
void AppInfoSummaryPanel::AddDescriptionAndLinksControl(
views::View* vertical_stack) {
views::View* description_and_labels_stack = new views::View();
description_and_labels_stack->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical,
0,
0,
views::kRelatedControlSmallVerticalSpacing));
if (!app_->description().empty()) {
// TODO(sashab): Clip the app's description to 4 lines, and use Label's
// built-in elide behavior to add ellipses at the end: crbug.com/358053
const size_t max_length = 400;
base::string16 text = base::UTF8ToUTF16(app_->description());
if (text.length() > max_length) {
text = text.substr(0, max_length);
text += base::ASCIIToUTF16(" ... ");
}
views::Label* description_label = new views::Label(text);
description_label->SetMultiLine(true);
description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
description_and_labels_stack->AddChildView(description_label);
}
// TODO(sashab): Clip the app's description to 4 lines, and use Label's
// built-in elide behavior to add ellipses at the end: crbug.com/358053
const size_t max_length = 400;
base::string16 text = base::UTF8ToUTF16(app_->description());
if (text.length() > max_length) {
text = text.substr(0, max_length);
text += base::ASCIIToUTF16(" ... ");
if (CanShowAppHomePage()) {
homepage_link_ = new views::Link(
l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_HOMEPAGE_LINK));
homepage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
homepage_link_->set_listener(this);
description_and_labels_stack->AddChildView(homepage_link_);
}
views::Label* description_label = new views::Label(text);
description_label->SetMultiLine(true);
description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
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);
description_and_labels_stack->AddChildView(licenses_link_);
}
vertical_stack->AddChildView(description_label);
vertical_stack->AddChildView(description_and_labels_stack);
}
void AppInfoSummaryPanel::AddDetailsControl(views::View* vertical_stack) {
......@@ -222,7 +251,7 @@ void AppInfoSummaryPanel::AddSubviews() {
CreateVerticalStack(views::kUnrelatedControlVerticalSpacing);
AddChildView(vertical_stack);
AddDescriptionControl(vertical_stack);
AddDescriptionAndLinksControl(vertical_stack);
AddDetailsControl(vertical_stack);
AddLaunchOptionControl(vertical_stack);
}
......@@ -236,6 +265,16 @@ void AppInfoSummaryPanel::OnPerformAction(views::Combobox* combobox) {
}
}
void AppInfoSummaryPanel::LinkClicked(views::Link* source, int event_flags) {
if (source == homepage_link_) {
ShowAppHomePage();
} else if (source == licenses_link_) {
DisplayLicenses();
} else {
NOTREACHED();
}
}
void AppInfoSummaryPanel::StartCalculatingAppSize() {
base::PostTaskAndReplyWithResult(
content::BrowserThread::GetBlockingPool(),
......@@ -274,3 +313,46 @@ bool AppInfoSummaryPanel::CanSetLaunchType() const {
return !app_->is_platform_app() && !app_->is_extension() &&
app_->id() != extension_misc::kChromeAppId;
}
void AppInfoSummaryPanel::ShowAppHomePage() {
DCHECK(CanShowAppHomePage());
OpenLink(extensions::ManifestURL::GetHomepageURL(app_));
Close();
}
bool AppInfoSummaryPanel::CanShowAppHomePage() const {
return extensions::ManifestURL::SpecifiedHomepageURL(app_);
}
void AppInfoSummaryPanel::DisplayLicenses() {
DCHECK(CanDisplayLicenses());
for (const auto& license_url : GetLicenseUrls())
OpenLink(license_url);
Close();
}
bool AppInfoSummaryPanel::CanDisplayLicenses() const {
return !GetLicenseUrls().empty();
}
const std::vector<GURL> AppInfoSummaryPanel::GetLicenseUrls() const {
if (!extensions::SharedModuleInfo::ImportsModules(app_))
return std::vector<GURL>();
std::vector<GURL> license_urls;
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
DCHECK(service);
const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
extensions::SharedModuleInfo::GetImports(app_);
for (const auto& shared_module : imports) {
const extensions::Extension* imported_module =
service->GetExtensionById(shared_module.extension_id, true);
DCHECK(imported_module);
GURL about_page = extensions::ManifestURL::GetAboutPage(imported_module);
if (about_page != GURL::EmptyGURL())
license_urls.push_back(about_page);
}
return license_urls;
}
......@@ -10,6 +10,7 @@
#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h"
#include "chrome/common/extensions/extension_constants.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/link_listener.h"
class LaunchOptionsComboboxModel;
class Profile;
......@@ -21,12 +22,15 @@ class Extension;
namespace views {
class Combobox;
class Label;
class Link;
class View;
}
// The summary panel of the app info dialog, which provides basic information
// and controls related to the app.
class AppInfoSummaryPanel : public AppInfoPanel,
public views::ComboboxListener,
public views::LinkListener,
public base::SupportsWeakPtr<AppInfoSummaryPanel> {
public:
AppInfoSummaryPanel(Profile* profile, const extensions::Extension* app);
......@@ -35,7 +39,7 @@ class AppInfoSummaryPanel : public AppInfoPanel,
private:
// Internal initialisation methods.
void AddDescriptionControl(views::View* vertical_stack);
void AddDescriptionAndLinksControl(views::View* vertical_stack);
void AddDetailsControl(views::View* vertical_stack);
void AddLaunchOptionControl(views::View* vertical_stack);
void AddSubviews();
......@@ -43,6 +47,9 @@ class AppInfoSummaryPanel : public AppInfoPanel,
// Overridden from views::ComboboxListener:
void OnPerformAction(views::Combobox* combobox) override;
// Overridden from views::LinkListener:
virtual void LinkClicked(views::Link* source, int event_flags) override;
// Called asynchronously to calculate and update the size of the app displayed
// in the dialog.
void StartCalculatingAppSize();
......@@ -56,8 +63,21 @@ class AppInfoSummaryPanel : public AppInfoPanel,
void SetLaunchType(extensions::LaunchType) const;
bool CanSetLaunchType() const;
// Opens the app's homepage URL as specified in the manifest. Must only be
// called if CanShowAppHomePage() returns true.
void ShowAppHomePage();
bool CanShowAppHomePage() const;
// Displays the licenses for the app. Must only be called if
// CanDisplayLicenses() returns true.
void DisplayLicenses();
bool CanDisplayLicenses() const;
const std::vector<GURL> GetLicenseUrls() const;
// UI elements on the dialog.
views::Label* size_value_;
views::Link* homepage_link_;
views::Link* licenses_link_;
scoped_ptr<LaunchOptionsComboboxModel> launch_options_combobox_model_;
views::Combobox* launch_options_combobox_;
......
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