Commit 11a86d52 authored by Dave Schuyler's avatar Dave Schuyler Committed by Commit Bot

[MD extensions] View-in-store feature for Details page

This CL adds a View in store link row that links to the extension home
page as well as a link row for the Chrome Web Store page for the extension.

Bug: 794286
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I06a8c078f0659adc3c69e6139133ec9cf6a81d9a
Reviewed-on: https://chromium-review.googlesource.com/826473
Commit-Queue: Dave Schuyler <dschuyler@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524325}
parent 8c25dd76
...@@ -411,6 +411,13 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper( ...@@ -411,6 +411,13 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec(); info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec();
info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension); info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension);
// Developer and web store URLs.
// TODO(dschuyler) after MD extensions releases (expected in m64), look into
// removing the |home_page.url| and |home_page.specified| above.
info->manifest_home_page_url =
ManifestURL::GetManifestHomePageURL(&extension).spec();
info->web_store_url = ManifestURL::GetWebStoreURL(&extension).spec();
info->id = extension.id(); info->id = extension.id();
// Incognito access. // Incognito access.
......
...@@ -163,7 +163,7 @@ ...@@ -163,7 +163,7 @@
margin: 0; margin: 0;
} }
#remove-extension { button[is='cr-link-row'] {
width: 100%; width: 100%;
} }
...@@ -364,6 +364,14 @@ ...@@ -364,6 +364,14 @@
<button class="icon-external" is="paper-icon-button-light" <button class="icon-external" is="paper-icon-button-light"
aria-labelledby="optionLabel" actionable></button> aria-labelledby="optionLabel" actionable></button>
</div> </div>
<button class="hr" hidden="[[!data.manifestHomePageUrl.length]]"
is="cr-link-row" icon-class="icon-external" id="developerWebsite"
label="$i18n{developerWebsite}" on-tap="onDeveloperWebSiteTap_">
</button>
<button class="hr" hidden="[[!data.webStoreUrl.length]]"
is="cr-link-row" icon-class="icon-external" id="viewInStore"
label="$i18n{viewInStore}" on-tap="onViewInStoreTap_">
</button>
<div class="section block"> <div class="section block">
<div class="section-title">$i18n{itemSource}</div> <div class="section-title">$i18n{itemSource}</div>
<div id="source" class="section-content"> <div id="source" class="section-content">
......
...@@ -113,18 +113,6 @@ cr.define('extensions', function() { ...@@ -113,18 +113,6 @@ cr.define('extensions', function() {
return extensions.computeInspectableViewLabel(view); return extensions.computeInspectableViewLabel(view);
}, },
/**
* @return {boolean}
* @private
*/
shouldShowHomepageButton_: function() {
// Note: we ignore |data.homePage.specified| - we use an extension's
// webstore entry as a homepage if the extension didn't explicitly specify
// a homepage. (|url| can still be unset in the case of unpacked
// extensions.)
return this.data.homePage.url.length > 0;
},
/** /**
* @return {boolean} * @return {boolean}
* @private * @private
...@@ -202,19 +190,28 @@ cr.define('extensions', function() { ...@@ -202,19 +190,28 @@ cr.define('extensions', function() {
}, },
/** @private */ /** @private */
onIconClick_: function(e) { onDeveloperWebSiteTap_: function() {
e.preventDefault(); this.delegate.openUrl(this.data.manifestHomePageUrl);
},
/** @private */
onViewInStoreTap_: function() {
this.delegate.openUrl(this.data.webStoreUrl);
}, },
/** /**
* @param {!chrome.developerPrivate.DependentExtension} item * @param {!chrome.developerPrivate.DependentExtension} item
* @return {string}
* @private * @private
*/ */
computeDependentEntry_: function(item) { computeDependentEntry_: function(item) {
return loadTimeData.getStringF('itemDependentEntry', item.name, item.id); return loadTimeData.getStringF('itemDependentEntry', item.name, item.id);
}, },
/** @private */ /**
* @return {string}
* @private
*/
computeSourceString_: function() { computeSourceString_: function() {
return this.data.locationText || return this.data.locationText ||
extensions.getItemSourceString(extensions.getItemSource(this.data)); extensions.getItemSourceString(extensions.getItemSource(this.data));
......
...@@ -44,6 +44,11 @@ cr.define('extensions', function() { ...@@ -44,6 +44,11 @@ cr.define('extensions', function() {
*/ */
inspectItemView(id, view) {} inspectItemView(id, view) {}
/**
* @param {string} url
*/
openUrl(url) {}
/** /**
* @param {string} id * @param {string} id
* @return {!Promise} * @return {!Promise}
......
...@@ -174,6 +174,14 @@ cr.define('extensions', function() { ...@@ -174,6 +174,14 @@ cr.define('extensions', function() {
}); });
} }
/**
* @param {string} url
* @override
*/
openUrl(url) {
window.open(url);
}
/** @override */ /** @override */
reloadItem(id) { reloadItem(id) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
......
...@@ -144,6 +144,13 @@ content::WebUIDataSource* CreateMdExtensionsSource(bool in_dev_mode) { ...@@ -144,6 +144,13 @@ content::WebUIDataSource* CreateMdExtensionsSource(bool in_dev_mode) {
source->AddLocalizedString("noExtensionsOrApps", source->AddLocalizedString("noExtensionsOrApps",
IDS_MD_EXTENSIONS_NO_INSTALLED_ITEMS); IDS_MD_EXTENSIONS_NO_INSTALLED_ITEMS);
source->AddLocalizedString("noDescription", IDS_MD_EXTENSIONS_NO_DESCRIPTION); source->AddLocalizedString("noDescription", IDS_MD_EXTENSIONS_NO_DESCRIPTION);
// TODO(dschuyler): define "viewInStore" as IDS_MD_EXTENSIONS_VIEW_IN_STORE.
source->AddLocalizedString("viewInStore",
IDS_APPLICATION_INFO_WEB_STORE_LINK);
// TODO(dschuyler): define "developerWebsite" as
// IDS_MD_EXTENSIONS_DEVELOPER_WEBSITE.
source->AddLocalizedString("developerWebsite",
IDS_APPLICATION_INFO_HOMEPAGE_LINK);
source->AddLocalizedString("noSearchResults", IDS_SEARCH_NO_RESULTS); source->AddLocalizedString("noSearchResults", IDS_SEARCH_NO_RESULTS);
source->AddLocalizedString("searchResults", IDS_SEARCH_RESULTS); source->AddLocalizedString("searchResults", IDS_SEARCH_RESULTS);
source->AddLocalizedString("dropToInstall", source->AddLocalizedString("dropToInstall",
......
...@@ -207,6 +207,7 @@ namespace developerPrivate { ...@@ -207,6 +207,7 @@ namespace developerPrivate {
Location location; Location location;
DOMString? locationText; DOMString? locationText;
ManifestError[] manifestErrors; ManifestError[] manifestErrors;
DOMString manifestHomePageUrl;
boolean mustRemainInstalled; boolean mustRemainInstalled;
DOMString name; DOMString name;
boolean offlineEnabled; boolean offlineEnabled;
...@@ -223,6 +224,7 @@ namespace developerPrivate { ...@@ -223,6 +224,7 @@ namespace developerPrivate {
boolean userMayModify; boolean userMayModify;
DOMString version; DOMString version;
ExtensionView[] views; ExtensionView[] views;
DOMString webStoreUrl;
}; };
dictionary ProfileInfo { dictionary ProfileInfo {
...@@ -598,7 +600,7 @@ namespace developerPrivate { ...@@ -598,7 +600,7 @@ namespace developerPrivate {
static void openDevTools(OpenDevToolsProperties properties, static void openDevTools(OpenDevToolsProperties properties,
optional VoidCallback callback); optional VoidCallback callback);
// Delete reported extension erors. // Delete reported extension errors.
// |properties| : The properties specifying the errors to remove. // |properties| : The properties specifying the errors to remove.
static void deleteExtensionErrors( static void deleteExtensionErrors(
DeleteExtensionErrorsProperties properties, DeleteExtensionErrorsProperties properties,
......
...@@ -106,8 +106,19 @@ cr.define('extension_detail_view_tests', function() { ...@@ -106,8 +106,19 @@ cr.define('extension_detail_view_tests', function() {
item.set('data.optionsPage', {openInTab: true, url: optionsUrl}); item.set('data.optionsPage', {openInTab: true, url: optionsUrl});
expectTrue(testIsVisible('#extensions-options')); expectTrue(testIsVisible('#extensions-options'));
// TODO(devlin): Add checks for homepage once it's added back to the item.set('data.manifestHomePageUrl', 'http://example.com');
// mocks. Polymer.dom.flush();
expectTrue(testIsVisible('#developerWebsite'));
item.set('data.manifestHomePageUrl', '');
Polymer.dom.flush();
expectFalse(testIsVisible('#developerWebsite'));
item.set('data.webStoreUrl', 'http://example.com');
Polymer.dom.flush();
expectTrue(testIsVisible('#viewInStore'));
item.set('data.webStoreUrl', '');
Polymer.dom.flush();
expectFalse(testIsVisible('#viewInStore'));
expectFalse(testIsVisible('#id-section')); expectFalse(testIsVisible('#id-section'));
expectFalse(testIsVisible('#inspectable-views')); expectFalse(testIsVisible('#inspectable-views'));
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "extensions/common/manifest_url_handlers.h" #include "extensions/common/manifest_url_handlers.h"
#include <memory> #include <memory>
#include <utility>
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
...@@ -38,6 +39,22 @@ const GURL ManifestURL::GetHomepageURL(const Extension* extension) { ...@@ -38,6 +39,22 @@ const GURL ManifestURL::GetHomepageURL(const Extension* extension) {
const GURL& homepage_url = Get(extension, keys::kHomepageURL); const GURL& homepage_url = Get(extension, keys::kHomepageURL);
if (homepage_url.is_valid()) if (homepage_url.is_valid())
return homepage_url; return homepage_url;
return GetWebStoreURL(extension);
}
// static
bool ManifestURL::SpecifiedHomepageURL(const Extension* extension) {
return Get(extension, keys::kHomepageURL).is_valid();
}
// static
const GURL ManifestURL::GetManifestHomePageURL(const Extension* extension) {
const GURL& homepage_url = Get(extension, keys::kHomepageURL);
return homepage_url.is_valid() ? homepage_url : GURL::EmptyGURL();
}
// static
const GURL ManifestURL::GetWebStoreURL(const Extension* extension) {
bool use_webstore_url = UpdatesFromGallery(extension) && bool use_webstore_url = UpdatesFromGallery(extension) &&
!SharedModuleInfo::IsSharedModule(extension); !SharedModuleInfo::IsSharedModule(extension);
return use_webstore_url return use_webstore_url
...@@ -46,11 +63,6 @@ const GURL ManifestURL::GetHomepageURL(const Extension* extension) { ...@@ -46,11 +63,6 @@ const GURL ManifestURL::GetHomepageURL(const Extension* extension) {
: GURL::EmptyGURL(); : GURL::EmptyGURL();
} }
// static
bool ManifestURL::SpecifiedHomepageURL(const Extension* extension) {
return Get(extension, keys::kHomepageURL).is_valid();
}
// static // static
const GURL& ManifestURL::GetUpdateURL(const Extension* extension) { const GURL& ManifestURL::GetUpdateURL(const Extension* extension) {
return Get(extension, keys::kUpdateURL); return Get(extension, keys::kUpdateURL);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define EXTENSIONS_COMMON_MANIFEST_URL_HANDLERS_H_ #define EXTENSIONS_COMMON_MANIFEST_URL_HANDLERS_H_
#include <string> #include <string>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
...@@ -29,12 +30,23 @@ struct ManifestURL : public Extension::ManifestData { ...@@ -29,12 +30,23 @@ struct ManifestURL : public Extension::ManifestData {
// If homepage_url was not specified in the manifest, // If homepage_url was not specified in the manifest,
// this returns the Google Gallery URL. For third-party extensions, // this returns the Google Gallery URL. For third-party extensions,
// this returns a blank GURL. // this returns a blank GURL.
// See also: GetManifestHomePageURL(), SpecifiedHomepageURL()
static const GURL GetHomepageURL(const Extension* extension); static const GURL GetHomepageURL(const Extension* extension);
// Returns true if the extension specified a valid home page url in the // Returns true if the extension specified a valid home page url in the
// manifest. // manifest.
static bool SpecifiedHomepageURL(const Extension* extension); static bool SpecifiedHomepageURL(const Extension* extension);
// Returns the homepage specified by the extension in its manifest, if it
// specifies a homepage. Otherwise, returns an empty url.
// See also: GetHomepageURL()
static const GURL GetManifestHomePageURL(const Extension* extension);
// Returns the Chrome Web Store URL for this extension if it is hosted in the
// webstore; otherwise returns an empty url.
// See also: GetHomepageURL()
static const GURL GetWebStoreURL(const Extension* extension);
// Returns the Update URL for this extension. // Returns the Update URL for this extension.
static const GURL& GetUpdateURL(const Extension* extension); static const GURL& GetUpdateURL(const Extension* extension);
......
...@@ -303,6 +303,7 @@ chrome.developerPrivate.Permission; ...@@ -303,6 +303,7 @@ chrome.developerPrivate.Permission;
* location: !chrome.developerPrivate.Location, * location: !chrome.developerPrivate.Location,
* locationText: (string|undefined), * locationText: (string|undefined),
* manifestErrors: !Array<!chrome.developerPrivate.ManifestError>, * manifestErrors: !Array<!chrome.developerPrivate.ManifestError>,
* manifestHomePageUrl: string,
* mustRemainInstalled: boolean, * mustRemainInstalled: boolean,
* name: string, * name: string,
* offlineEnabled: boolean, * offlineEnabled: boolean,
...@@ -318,7 +319,8 @@ chrome.developerPrivate.Permission; ...@@ -318,7 +319,8 @@ chrome.developerPrivate.Permission;
* updateUrl: string, * updateUrl: string,
* userMayModify: boolean, * userMayModify: boolean,
* version: string, * version: string,
* views: !Array<!chrome.developerPrivate.ExtensionView> * views: !Array<!chrome.developerPrivate.ExtensionView>,
* webStoreUrl: string
* }} * }}
* @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionInfo * @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionInfo
*/ */
...@@ -734,7 +736,7 @@ chrome.developerPrivate.requestFileSource = function(properties, callback) {}; ...@@ -734,7 +736,7 @@ chrome.developerPrivate.requestFileSource = function(properties, callback) {};
chrome.developerPrivate.openDevTools = function(properties, callback) {}; chrome.developerPrivate.openDevTools = function(properties, callback) {};
/** /**
* Delete reported extension erors. * Delete reported extension errors.
* @param {!chrome.developerPrivate.DeleteExtensionErrorsProperties} properties * @param {!chrome.developerPrivate.DeleteExtensionErrorsProperties} properties
* The properties specifying the errors to remove. * The properties specifying the errors to remove.
* @param {function():void=} callback * @param {function():void=} callback
......
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