From 37cd64d34bc3dbf2385a3c312c92bb3c7c65664a Mon Sep 17 00:00:00 2001 From: "tessamac@google.com" Date: Mon, 25 Oct 2010 18:17:58 +0000 Subject: Add optional homepage_url to manifest and use it in place of Gallery URL in UI. BUG=28907 TEST=Added homepage_url to manifest, check that it replaces gallery URL link. Review URL: http://codereview.chromium.org/3767013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63749 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/common/extensions/docs/manifest.html | 100 +++++++++++---------- chrome/common/extensions/docs/static/manifest.html | 92 ++++++++++--------- chrome/common/extensions/extension.cc | 25 +++++- chrome/common/extensions/extension.h | 9 +- chrome/common/extensions/extension_constants.cc | 3 + chrome/common/extensions/extension_constants.h | 2 + .../extensions/extension_manifests_unittest.cc | 23 +++++ 7 files changed, 162 insertions(+), 92 deletions(-) (limited to 'chrome/common/extensions') diff --git a/chrome/common/extensions/docs/manifest.html b/chrome/common/extensions/docs/manifest.html index d8bd4f4..9f72560 100644 --- a/chrome/common/extensions/docs/manifest.html +++ b/chrome/common/extensions/docs/manifest.html @@ -245,11 +245,15 @@ Field details
  1. + default_locale +
  2. description
  3. + homepage_url +
  4. icons
  5. - default_locale + incognito
  6. key
  7. @@ -260,8 +264,6 @@ permissions
  8. version -
  9. - incognito
@@ -350,13 +352,14 @@ are name and version. "background_page": "aFile.html", "chrome_url_overrides": {...}, "content_scripts": [...], + "homepage_url": "http://path/to/homepage", + "incognito": "split or spanning", "key": "publicKey", "minimum_chrome_version": "versionString", "options_page": "aFile.html", "permissions": [...], "plugins": [...], "update_url": "http://path/to/updateInfo.xml" - "incognito": "split or spanning", } @@ -370,6 +373,19 @@ with links to where they're described in detail, see the Field summary.

+

default_locale

+ +

+Specifies the subdirectory of _locales +that contains the default strings for this extension. +This field is required in extensions +that have a _locales directory; +it must be absent in extensions +that have no _locales directory. +For details, see +Internationalization. +

+

description

@@ -384,6 +400,15 @@ You can specify locale-specific strings for this field; see Internationalization for details.

+

homepage_url

+ +

+The URL of the homepage for this extension. The extensions management page (chrome://extensions) +will contain a link to this URL. This field is particularly useful if you +host the extension on your own site. If you distribute your +extension using the gallery, +the homepage URL defaults to the extension's own gallery page. +

icons

@@ -428,8 +453,6 @@ extension developers are using the documented sizes. If you use other sizes, your icon may look bad in future versions of the browser.

- -

If you submit your extension to the gallery, @@ -441,17 +464,34 @@ see the gallery help.

-

default_locale

+

incognito

-Specifies the subdirectory of _locales -that contains the default strings for this extension. -This field is required in extensions -that have a _locales directory; -it must be absent in extensions -that have no _locales directory. -For details, see -Internationalization. +Either split or spanning, to specify how this extension will +behave if allowed to run in incognito. +

+ +

+spanning is the default for extensions, and means that the extension +will run in a single shared process. Any events or messages from an incognito +tab will be sent to the shared process, with an incognito flag +indicating where it came from. +

+ +

+split is the default for apps, and it means that all app pages in +an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process. +This incognito process runs along side the regular process, but has a separate +memory-only cookie store. Each process sees events and messages only from its +own context (e.g. the incognito process will only see incognito tab updates). +The processes are unable to communicate with each other. +

+ +

+As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use +split incognito behavior. If your extension or app needs to be logged +into a remote server or persist settings locally, use spanning +incognito behavior.

key

@@ -680,36 +720,6 @@ For more information, see Autoupdating.

-

incognito

- -

-Either split or spanning, to specify how this extension will -behave if allowed to run in incognito. -

- -

-spanning is the default for extensions, and means that the extension -will run in a single shared process. Any events or messages from an incognito -tab will be sent to the shared process, with an incognito flag -indicating where it came from. -

- -

-split is the default for apps, and it means that all app pages in -an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process. -This incognito process runs along side the regular process, but has a separate -memory-only cookie store. Each process sees events and messages only from its -own context (e.g. the incognito process will only see incognito tab updates). -The processes are unable to communicate with each other. -

- -

-As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use -split incognito behavior. If your extension or app needs to be logged -into a remote server or persist settings locally, use spanning -incognito behavior. -

- diff --git a/chrome/common/extensions/docs/static/manifest.html b/chrome/common/extensions/docs/static/manifest.html index 5e1758c..3b0af0d 100644 --- a/chrome/common/extensions/docs/static/manifest.html +++ b/chrome/common/extensions/docs/static/manifest.html @@ -37,13 +37,14 @@ are name and version. "background_page": "aFile.html", "chrome_url_overrides": {...}, "content_scripts": [...], + "homepage_url": "http://path/to/homepage", + "incognito": "split or spanning", "key": "publicKey", "minimum_chrome_version": "versionString", "options_page": "aFile.html", "permissions": [...], "plugins": [...], "update_url": "http://path/to/updateInfo.xml" - "incognito": "split or spanning", } @@ -57,6 +58,19 @@ with links to where they're described in detail, see the Field summary.

+

default_locale

+ +

+Specifies the subdirectory of _locales +that contains the default strings for this extension. +This field is required in extensions +that have a _locales directory; +it must be absent in extensions +that have no _locales directory. +For details, see +Internationalization. +

+

description

@@ -71,6 +85,15 @@ You can specify locale-specific strings for this field; see Internationalization for details.

+

homepage_url

+ +

+The URL of the homepage for this extension. The extensions management page (chrome://extensions) +will contain a link to this URL. This field is particularly useful if you +host the extension on your own site. If you distribute your +extension using the gallery, +the homepage URL defaults to the extension's own gallery page. +

icons

@@ -116,8 +139,6 @@ extension developers are using the documented sizes. If you use other sizes, your icon may look bad in future versions of the browser.

- -

If you submit your extension to the gallery, @@ -129,17 +150,34 @@ see the gallery help.

-

default_locale

+

incognito

-Specifies the subdirectory of _locales -that contains the default strings for this extension. -This field is required in extensions -that have a _locales directory; -it must be absent in extensions -that have no _locales directory. -For details, see -Internationalization. +Either split or spanning, to specify how this extension will +behave if allowed to run in incognito. +

+ +

+spanning is the default for extensions, and means that the extension +will run in a single shared process. Any events or messages from an incognito +tab will be sent to the shared process, with an incognito flag +indicating where it came from. +

+ +

+split is the default for apps, and it means that all app pages in +an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process. +This incognito process runs along side the regular process, but has a separate +memory-only cookie store. Each process sees events and messages only from its +own context (e.g. the incognito process will only see incognito tab updates). +The processes are unable to communicate with each other. +

+ +

+As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use +split incognito behavior. If your extension or app needs to be logged +into a remote server or persist settings locally, use spanning +incognito behavior.

key

@@ -369,34 +407,4 @@ For more information, see Autoupdating.

-

incognito

- -

-Either split or spanning, to specify how this extension will -behave if allowed to run in incognito. -

- -

-spanning is the default for extensions, and means that the extension -will run in a single shared process. Any events or messages from an incognito -tab will be sent to the shared process, with an incognito flag -indicating where it came from. -

- -

-split is the default for apps, and it means that all app pages in -an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process. -This incognito process runs along side the regular process, but has a separate -memory-only cookie store. Each process sees events and messages only from its -own context (e.g. the incognito process will only see incognito tab updates). -The processes are unable to communicate with each other. -

- -

-As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use -split incognito behavior. If your extension or app needs to be logged -into a remote server or persist settings locally, use spanning -incognito behavior. -

- diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index e3254d8..de50d07 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -1263,6 +1263,22 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, } } + // Initialize homepage url (if present). + if (source.HasKey(keys::kHomepageURL)) { + std::string tmp; + if (!source.GetString(keys::kHomepageURL, &tmp)) { + *error = ExtensionErrorUtils::FormatErrorMessage( + errors::kInvalidHomepageURL, ""); + return false; + } + mutable_static_data_->homepage_url = GURL(tmp); + if (!mutable_static_data_->homepage_url.is_valid()) { + *error = ExtensionErrorUtils::FormatErrorMessage( + errors::kInvalidHomepageURL, tmp); + return false; + } + } + // Initialize update url (if present). if (source.HasKey(keys::kUpdateURL)) { std::string tmp; @@ -1854,15 +1870,18 @@ std::string Extension::ChromeStoreLaunchURL() { return gallery_prefix; } -GURL Extension::GalleryUrl() const { - if (!update_url().DomainIs("google.com")) +GURL Extension::GetHomepageURL() const { + if (static_data_->homepage_url.is_valid()) + return static_data_->homepage_url; + + if (update_url()!= GURL(extension_urls::kGalleryUpdateHttpsUrl) && + update_url()!= GURL(extension_urls::kGalleryUpdateHttpUrl)) return GURL(); // TODO(erikkay): This may not be entirely correct with the webstore. // I think it will have a mixture of /extensions/detail and /webstore/detail // URLs. Perhaps they'll handle this nicely with redirects? GURL url(ChromeStoreLaunchURL() + std::string("/detail/") + id()); - return url; } diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index c90928e..4aa662d 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -217,6 +217,10 @@ class Extension { // The sites this extension has permission to talk to (using XHR, etc). URLPatternList host_permissions; + // The homepage for this extension. Useful if it is not hosted by Google and + // therefore does not have a Gallery URL. + GURL homepage_url; + // URL for fetching an update manifest GURL update_url; @@ -554,9 +558,10 @@ class Extension { return static_data_->icons; } - // Returns the Google Gallery URL for this extension, if one exists. For + // Returns the Homepage URL for this extension. If homepage_url was not + // specified in the manifest, this returns the Google Gallery URL. For // third-party extensions, this returns a blank GURL. - GURL GalleryUrl() const; + GURL GetHomepageURL() const; // Theme-related. DictionaryValue* GetThemeImages() const { diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index 983fda4a..5e418b5 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc @@ -19,6 +19,7 @@ const char* kDefaultLocale = "default_locale"; const char* kDescription = "description"; const char* kDevToolsPage = "devtools_page"; const char* kExcludeGlobs = "exclude_globs"; +const char* kHomepageURL = "homepage_url"; const char* kIcons = "icons"; const char* kIncognito = "incognito"; const char* kIncludeGlobs = "include_globs"; @@ -124,6 +125,8 @@ const char* kInvalidGlob = "Invalid value for 'content_scripts[*].*[*]'."; const char* kInvalidGlobList = "Invalid value for 'content_scripts[*].*'."; +const char* kInvalidHomepageURL = + "Invalid value for homepage url: '[*]'."; const char* kInvalidIconPath = "Invalid value for 'icons[\"*\"]'."; const char* kInvalidIcons = diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index e76ce24..332f386 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -24,6 +24,7 @@ namespace extension_manifest_keys { extern const char* kDescription; extern const char* kDevToolsPage; extern const char* kExcludeGlobs; + extern const char* kHomepageURL; extern const char* kIcons; extern const char* kIncognito; extern const char* kIncludeGlobs; @@ -108,6 +109,7 @@ namespace extension_manifest_errors { extern const char* kInvalidDevToolsPage; extern const char* kInvalidGlob; extern const char* kInvalidGlobList; + extern const char* kInvalidHomepageURL; extern const char* kInvalidIconPath; extern const char* kInvalidIcons; extern const char* kInvalidIncognitoBehavior; diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc index ac56f70..66d6b35 100644 --- a/chrome/common/extensions/extension_manifests_unittest.cc +++ b/chrome/common/extensions/extension_manifests_unittest.cc @@ -338,3 +338,26 @@ TEST_F(ExtensionManifestTest, DisallowMultipleUISurfaces) { LoadAndExpectError("multiple_ui_surfaces_2.json", errors::kOneUISurfaceOnly); LoadAndExpectError("multiple_ui_surfaces_3.json", errors::kOneUISurfaceOnly); } + +TEST_F(ExtensionManifestTest, ParseHomepageURLs) { + LoadAndExpectSuccess("homepage_valid.json"); + LoadAndExpectError("homepage_empty.json", + extension_manifest_errors::kInvalidHomepageURL); + LoadAndExpectError("homepage_invalid.json", + extension_manifest_errors::kInvalidHomepageURL); +} + +TEST_F(ExtensionManifestTest, GetHomepageURL) { + scoped_ptr extension(LoadAndExpectSuccess("homepage_valid.json")); + EXPECT_EQ(GURL("http://foo.com#bar"), extension->GetHomepageURL()); + + // The Google Gallery URL ends with the id, which depends on the path, which + // can be different in testing, so we just check the part before id. + extension.reset(LoadAndExpectSuccess("homepage_google_hosted.json")); + EXPECT_TRUE(StartsWithASCII(extension->GetHomepageURL().spec(), + "https://chrome.google.com/extensions/detail/", + false)); + + extension.reset(LoadAndExpectSuccess("homepage_externally_hosted.json")); + EXPECT_EQ(GURL(), extension->GetHomepageURL()); +} -- cgit v1.1