diff options
author | tessamac@google.com <tessamac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-25 18:17:58 +0000 |
---|---|---|
committer | tessamac@google.com <tessamac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-25 18:17:58 +0000 |
commit | 37cd64d34bc3dbf2385a3c312c92bb3c7c65664a (patch) | |
tree | 8edbd5db58ecfc090a4f2c41f26e01fb88536bc0 /chrome/common/extensions | |
parent | 0b1ed04aa570de0073ffd6789513c514882d36b4 (diff) | |
download | chromium_src-37cd64d34bc3dbf2385a3c312c92bb3c7c65664a.zip chromium_src-37cd64d34bc3dbf2385a3c312c92bb3c7c65664a.tar.gz chromium_src-37cd64d34bc3dbf2385a3c312c92bb3c7c65664a.tar.bz2 |
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
Diffstat (limited to 'chrome/common/extensions')
-rw-r--r-- | chrome/common/extensions/docs/manifest.html | 100 | ||||
-rw-r--r-- | chrome/common/extensions/docs/static/manifest.html | 92 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 25 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 9 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.cc | 3 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.h | 2 | ||||
-rw-r--r-- | chrome/common/extensions/extension_manifests_unittest.cc | 23 |
7 files changed, 162 insertions, 92 deletions
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 @@ <a href="#H2-1">Field details</a> <ol> <li> + <a href="#default_locale">default_locale</a> + </li><li> <a href="#description">description</a> </li><li> + <a href="#homepage_url">homepage_url</a> + </li><li> <a href="#icons">icons</a> </li><li> - <a href="#default_locale">default_locale</a> + <a href="#incognito">incognito</a> </li><li> <a href="#key">key</a> </li><li> @@ -260,8 +264,6 @@ <a href="#permissions">permissions</a> </li><li> <a href="#version">version</a> - </li><li> - <a href="#incognito">incognito</a> </li> </ol> </li> @@ -350,13 +352,14 @@ are <b>name</b> and <b>version</b>. "<a href="background_pages.html">background_page</a>": "<em>aFile</em>.html", "<a href="override.html">chrome_url_overrides</a>": {...}, "<a href="content_scripts.html">content_scripts</a>": [...], + "<a href="#homepage_url">homepage_url</a>": "http://path/to/homepage", + "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>", "<a href="#key">key</a>": "<em>publicKey</em>", "<a href="#minimum_chrome_version">minimum_chrome_version</a>": "<em>versionString</em>", "<a href="options.html">options_page</a>": "<em>aFile</em>.html", "<a href="#permissions">permissions</a>": [...], "<a href="npapi.html">plugins</a>": [...], "<a href="autoupdate.html">update_url</a>": "http://<em>path/to/updateInfo</em>.xml" - "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>", } </pre> @@ -370,6 +373,19 @@ with links to where they're described in detail, see the <a href="#overview">Field summary</a>. </p> +<h3 id="default_locale">default_locale</h3> + +<p> +Specifies the subdirectory of <code>_locales</code> +that contains the default strings for this extension. +This field is <b>required</b> in extensions +that have a <code>_locales</code> directory; +it <b>must be absent</b> in extensions +that have no <code>_locales</code> directory. +For details, see +<a href="i18n.html">Internationalization</a>. +</p> + <h3 id="description">description</h3> <p> @@ -384,6 +400,15 @@ You can specify locale-specific strings for this field; see <a href="i18n.html">Internationalization</a> for details. </p> +<h3 id="homepage_url">homepage_url</h3> + +<p> +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 +<a href="hosting.html">host the extension on your own site</a>. If you distribute your +extension using the <a href="http://chrome.google.com/extensions">gallery</a>, +the homepage URL defaults to the extension's own gallery page. +</p> <h3 id="icons">icons</h3> @@ -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. </p> - - <p> If you submit your extension to the <a href="https://chrome.google.com/extensions">gallery</a>, @@ -441,17 +464,34 @@ see the <a href="http://www.google.com/support/chrome/bin/answer.py?answer=113909">gallery help</a>. </p> -<h3 id="default_locale">default_locale</h3> +<h3 id="incognito">incognito</h3> <p> -Specifies the subdirectory of <code>_locales</code> -that contains the default strings for this extension. -This field is <b>required</b> in extensions -that have a <code>_locales</code> directory; -it <b>must be absent</b> in extensions -that have no <code>_locales</code> directory. -For details, see -<a href="i18n.html">Internationalization</a>. +Either <em>split</em> or <em>spanning</em>, to specify how this extension will +behave if allowed to run in incognito. +</p> + +<p> +<em>spanning</em> 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 <em>incognito</em> flag +indicating where it came from. +</p> + +<p> +<em>split</em> 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. +</p> + +<p> +As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use +<em>split</em> incognito behavior. If your extension or app needs to be logged +into a remote server or persist settings locally, use <em>spanning</em> +incognito behavior. </p> <h3 id="key">key</h3> @@ -680,36 +720,6 @@ For more information, see <a href="autoupdate.html">Autoupdating</a>. </p> -<h3 id="incognito">incognito</h3> - -<p> -Either <em>split</em> or <em>spanning</em>, to specify how this extension will -behave if allowed to run in incognito. -</p> - -<p> -<em>spanning</em> 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 <em>incognito</em> flag -indicating where it came from. -</p> - -<p> -<em>split</em> 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. -</p> - -<p> -As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use -<em>split</em> incognito behavior. If your extension or app needs to be logged -into a remote server or persist settings locally, use <em>spanning</em> -incognito behavior. -</p> - <!-- [PENDING: Possibly: point to the gallery and make a big deal of the fact that autoupdating is free if you use the gallery.] --> </div> 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 <b>name</b> and <b>version</b>. "<a href="background_pages.html">background_page</a>": "<em>aFile</em>.html", "<a href="override.html">chrome_url_overrides</a>": {...}, "<a href="content_scripts.html">content_scripts</a>": [...], + "<a href="#homepage_url">homepage_url</a>": "http://path/to/homepage", + "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>", "<a href="#key">key</a>": "<em>publicKey</em>", "<a href="#minimum_chrome_version">minimum_chrome_version</a>": "<em>versionString</em>", "<a href="options.html">options_page</a>": "<em>aFile</em>.html", "<a href="#permissions">permissions</a>": [...], "<a href="npapi.html">plugins</a>": [...], "<a href="autoupdate.html">update_url</a>": "http://<em>path/to/updateInfo</em>.xml" - "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>", } </pre> @@ -57,6 +58,19 @@ with links to where they're described in detail, see the <a href="#overview">Field summary</a>. </p> +<h3 id="default_locale">default_locale</h3> + +<p> +Specifies the subdirectory of <code>_locales</code> +that contains the default strings for this extension. +This field is <b>required</b> in extensions +that have a <code>_locales</code> directory; +it <b>must be absent</b> in extensions +that have no <code>_locales</code> directory. +For details, see +<a href="i18n.html">Internationalization</a>. +</p> + <h3 id="description">description</h3> <p> @@ -71,6 +85,15 @@ You can specify locale-specific strings for this field; see <a href="i18n.html">Internationalization</a> for details. </p> +<h3 id="homepage_url">homepage_url</h3> + +<p> +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 +<a href="hosting.html">host the extension on your own site</a>. If you distribute your +extension using the <a href="http://chrome.google.com/extensions">gallery</a>, +the homepage URL defaults to the extension's own gallery page. +</p> <h3 id="icons">icons</h3> @@ -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. </p> - - <p> If you submit your extension to the <a href="https://chrome.google.com/extensions">gallery</a>, @@ -129,17 +150,34 @@ see the <a href="http://www.google.com/support/chrome/bin/answer.py?answer=113909">gallery help</a>. </p> -<h3 id="default_locale">default_locale</h3> +<h3 id="incognito">incognito</h3> <p> -Specifies the subdirectory of <code>_locales</code> -that contains the default strings for this extension. -This field is <b>required</b> in extensions -that have a <code>_locales</code> directory; -it <b>must be absent</b> in extensions -that have no <code>_locales</code> directory. -For details, see -<a href="i18n.html">Internationalization</a>. +Either <em>split</em> or <em>spanning</em>, to specify how this extension will +behave if allowed to run in incognito. +</p> + +<p> +<em>spanning</em> 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 <em>incognito</em> flag +indicating where it came from. +</p> + +<p> +<em>split</em> 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. +</p> + +<p> +As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use +<em>split</em> incognito behavior. If your extension or app needs to be logged +into a remote server or persist settings locally, use <em>spanning</em> +incognito behavior. </p> <h3 id="key">key</h3> @@ -369,34 +407,4 @@ For more information, see <a href="autoupdate.html">Autoupdating</a>. </p> -<h3 id="incognito">incognito</h3> - -<p> -Either <em>split</em> or <em>spanning</em>, to specify how this extension will -behave if allowed to run in incognito. -</p> - -<p> -<em>spanning</em> 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 <em>incognito</em> flag -indicating where it came from. -</p> - -<p> -<em>split</em> 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. -</p> - -<p> -As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use -<em>split</em> incognito behavior. If your extension or app needs to be logged -into a remote server or persist settings locally, use <em>spanning</em> -incognito behavior. -</p> - <!-- [PENDING: Possibly: point to the gallery and make a big deal of the fact that autoupdating is free if you use the gallery.] --> 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> 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()); +} |