Commit 7b5a3e5e authored by sashab@chromium.org's avatar sashab@chromium.org

Add list of Shared Modules to App Info Dialog

Add a list of Shared Modules to the App Info Dialog, along with an
'About' link next to each one that opens the shared module's options
page. This allows shared modules to display licenses, which meets a
legal requirement explained more in the bug.

BUG=364681

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275767 0039d316-1c4b-4281-b951-d872f2087c98
parent 81f48945
...@@ -2199,6 +2199,12 @@ Even if you have downloaded files from this website before, the website might ha ...@@ -2199,6 +2199,12 @@ Even if you have downloaded files from this website before, the website might ha
Uninstall Uninstall
</message> </message>
</if> </if>
<message name="IDS_APPLICATION_INFO_IMPORTED_MODULES_TITLE_TEXT" desc="Text for the title above the imported modules for the app. Imported modules are like shared libraries that an app has used when it was built (but are not directly accessible by a user).">
This app imports the following modules:
</message>
<message name="IDS_APPLICATION_INFO_IMPORTED_MODULES_ABOUT_LINK_TEXT" desc="Text for the link next to each imported module that goes to the About page for that module. The About page may include things such as open-source and copyright licenses for the app.">
About
</message>
<message name="IDS_APPLICATION_INFO_REQUIRED_PERMISSIONS_TEXT" desc="Heading for the required permissions for the app (the permissions that the user must grant the app upon installation)."> <message name="IDS_APPLICATION_INFO_REQUIRED_PERMISSIONS_TEXT" desc="Heading for the required permissions for the app (the permissions that the user must grant the app upon installation).">
Required Required
</message> </message>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h" #include "extensions/common/extension_icon_set.h"
#include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "grit/generated_resources.h" #include "grit/generated_resources.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -260,6 +261,112 @@ bool AppInfoSummaryPanel::CanShowAppInWebStore() const { ...@@ -260,6 +261,112 @@ bool AppInfoSummaryPanel::CanShowAppInWebStore() const {
return app_->from_webstore(); return app_->from_webstore();
} }
// A small summary panel with a list of the app's imported modules, and a link
// to each of their options pages.
class AppInfoImportedModulesPanel : public views::View,
public views::LinkListener {
public:
AppInfoImportedModulesPanel(Profile* profile,
const extensions::Extension* app);
virtual ~AppInfoImportedModulesPanel();
private:
// Overridden from views::LinkListener:
virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
Profile* profile_;
const extensions::Extension* app_;
std::map<views::Link*, GURL> about_links_;
DISALLOW_COPY_AND_ASSIGN(AppInfoImportedModulesPanel);
};
AppInfoImportedModulesPanel::AppInfoImportedModulesPanel(
Profile* profile,
const extensions::Extension* app)
: profile_(profile), app_(app) {
// Create controls.
views::Label* title =
new views::Label(l10n_util::GetStringUTF16(
IDS_APPLICATION_INFO_IMPORTED_MODULES_TITLE_TEXT),
ui::ResourceBundle::GetSharedInstance().GetFontList(
ui::ResourceBundle::BoldFont));
title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
// Layout elements.
views::GridLayout* layout = new views::GridLayout(this);
SetLayoutManager(layout);
static const int kTitleColumnSetId = 1;
views::ColumnSet* title_column_set = layout->AddColumnSet(kTitleColumnSetId);
title_column_set->AddColumn(views::GridLayout::LEADING,
views::GridLayout::LEADING,
1, // Stretch the title to as wide as needed
views::GridLayout::USE_PREF,
0,
0);
static const int kModulesListColumnSetId = 2;
views::ColumnSet* column_set = layout->AddColumnSet(kModulesListColumnSetId);
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 'about' link
views::GridLayout::USE_PREF,
0,
0);
layout->StartRow(0, kTitleColumnSetId);
layout->AddView(title);
// Find all the shared modules for this app, and display them in a list.
// TODO(sashab): Revisit UI layout once shared module usage becomes more
// common.
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
DCHECK(service);
const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
extensions::SharedModuleInfo::GetImports(app_);
for (size_t i = 0; i < imports.size(); ++i) {
const extensions::Extension* imported_module =
service->GetExtensionById(imports[i].extension_id, true);
DCHECK(imported_module);
views::Label* name_label =
new views::Label(base::UTF8ToUTF16(imported_module->name()));
name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
layout->StartRow(0, kModulesListColumnSetId);
layout->AddView(name_label);
// If this app has an options page, display it as an 'about' link.
GURL options_page =
extensions::ManifestURL::GetOptionsPage(imported_module);
if (options_page != GURL::EmptyGURL()) {
views::Link* about_link = new views::Link(l10n_util::GetStringUTF16(
IDS_APPLICATION_INFO_IMPORTED_MODULES_ABOUT_LINK_TEXT));
about_link->set_listener(this);
about_links_[about_link] = options_page;
layout->AddView(about_link);
}
}
}
AppInfoImportedModulesPanel::~AppInfoImportedModulesPanel() {
}
void AppInfoImportedModulesPanel::LinkClicked(views::Link* source,
int event_flags) {
chrome::NavigateParams params(
profile_, about_links_[source], content::PAGE_TRANSITION_LINK);
chrome::Navigate(&params);
}
} // namespace } // namespace
// A model for a combobox selecting the launch options for a hosted app. // A model for a combobox selecting the launch options for a hosted app.
...@@ -386,6 +493,9 @@ AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window, ...@@ -386,6 +493,9 @@ AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window,
if (launch_options_combobox_) if (launch_options_combobox_)
AddChildView(launch_options_combobox_); AddChildView(launch_options_combobox_);
if (HasImportedModules())
AddChildView(new AppInfoImportedModulesPanel(profile_, app_));
LayoutButtons(); LayoutButtons();
} }
...@@ -534,3 +644,7 @@ bool AppInfoSummaryTab::CanCreateShortcuts() const { ...@@ -534,3 +644,7 @@ bool AppInfoSummaryTab::CanCreateShortcuts() const {
return true; return true;
#endif #endif
} }
bool AppInfoSummaryTab::HasImportedModules() {
return extensions::SharedModuleInfo::ImportsModules(app_);
}
...@@ -85,6 +85,8 @@ class AppInfoSummaryTab ...@@ -85,6 +85,8 @@ class AppInfoSummaryTab
void CreateShortcuts(); void CreateShortcuts();
bool CanCreateShortcuts() const; bool CanCreateShortcuts() const;
bool HasImportedModules();
// UI elements on the dialog. // UI elements on the dialog.
views::View* app_summary_panel_; views::View* app_summary_panel_;
views::Label* app_description_label_; views::Label* app_description_label_;
......
...@@ -299,7 +299,7 @@ ...@@ -299,7 +299,7 @@
"options_page": { "options_page": {
"channel": "stable", "channel": "stable",
"extension_types": [ "extension_types": [
"extension", "legacy_packaged_app", "hosted_app" "extension", "legacy_packaged_app", "hosted_app", "shared_module"
] ]
}, },
"page_action": { "page_action": {
......
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