summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions
diff options
context:
space:
mode:
authortessamac@google.com <tessamac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-25 18:17:58 +0000
committertessamac@google.com <tessamac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-25 18:17:58 +0000
commit37cd64d34bc3dbf2385a3c312c92bb3c7c65664a (patch)
tree8edbd5db58ecfc090a4f2c41f26e01fb88536bc0 /chrome/common/extensions
parent0b1ed04aa570de0073ffd6789513c514882d36b4 (diff)
downloadchromium_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.html100
-rw-r--r--chrome/common/extensions/docs/static/manifest.html92
-rw-r--r--chrome/common/extensions/extension.cc25
-rw-r--r--chrome/common/extensions/extension.h9
-rw-r--r--chrome/common/extensions/extension_constants.cc3
-rw-r--r--chrome/common/extensions/extension_constants.h2
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc23
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());
+}