diff options
20 files changed, 409 insertions, 23 deletions
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index a0dd960..d90bbbd 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -204,10 +204,7 @@ bool CrxInstaller::AllowInstall(const Extension* extension, // For apps with a gallery update URL, require that they be installed // from the gallery. // TODO(erikkay) Apply this rule for paid extensions and themes as well. - if ((extension->update_url() == - GURL(extension_urls::kGalleryUpdateHttpsUrl)) || - (extension->update_url() == - GURL(extension_urls::kGalleryUpdateHttpUrl))) { + if (extension->UpdatesFromGallery()) { *error = l10n_util::GetStringFUTF8( IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS, l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 4f53b48..47531f4 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -36,6 +36,7 @@ #include "chrome/browser/extensions/extension_management_api.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_metrics_module.h" +#include "chrome/browser/extensions/extension_module.h" #include "chrome/browser/extensions/extension_omnibox_api.h" #include "chrome/browser/extensions/extension_page_actions_module.h" #include "chrome/browser/extensions/extension_popup_api.h" @@ -279,6 +280,9 @@ void FactoryRegistry::ResetFunctions() { RegisterFunction<SetEnabledFunction>(); RegisterFunction<UninstallFunction>(); + // Extension module. + RegisterFunction<SetUpdateUrlDataFunction>(); + // WebstorePrivate. RegisterFunction<GetBrowserLoginFunction>(); RegisterFunction<GetStoreLoginFunction>(); diff --git a/chrome/browser/extensions/extension_module.cc b/chrome/browser/extensions/extension_module.cc new file mode 100644 index 0000000..84c3789 --- /dev/null +++ b/chrome/browser/extensions/extension_module.cc @@ -0,0 +1,23 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_module.h" + +#include <string> + +#include "chrome/browser/extensions/extension_prefs.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" + +ExtensionPrefs* SetUpdateUrlDataFunction::extension_prefs() { + return profile()->GetExtensionsService()->extension_prefs(); +} + +bool SetUpdateUrlDataFunction::RunImpl() { + std::string data; + EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &data)); + + extension_prefs()->SetUpdateUrlData(extension_id(), data); + return true; +} diff --git a/chrome/browser/extensions/extension_module.h b/chrome/browser/extensions/extension_module.h new file mode 100644 index 0000000..21227a2 --- /dev/null +++ b/chrome/browser/extensions/extension_module.h @@ -0,0 +1,20 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__ +#pragma once + +#include "chrome/browser/extensions/extension_function.h" + +class ExtensionPrefs; + +class SetUpdateUrlDataFunction : public SyncExtensionFunction { + protected: + ExtensionPrefs* extension_prefs(); + virtual bool RunImpl(); + DECLARE_EXTENSION_FUNCTION_NAME("extension.setUpdateUrlData"); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__ diff --git a/chrome/browser/extensions/extension_module_apitest.cc b/chrome/browser/extensions/extension_module_apitest.cc new file mode 100644 index 0000000..718c422 --- /dev/null +++ b/chrome/browser/extensions/extension_module_apitest.cc @@ -0,0 +1,12 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_apitest.h" + +class ExtensionModuleApiTest : public ExtensionApiTest { +}; + +IN_PROC_BROWSER_TEST_F(ExtensionModuleApiTest, Basics) { + ASSERT_TRUE(RunExtensionTest("extension_module")) << message_; +} diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index bf80550..3c789b0 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -75,6 +75,9 @@ const char kPrefLaunchType[] = "launchType"; // A preference determining the order of which the apps appear on the NTP. const char kPrefAppLaunchIndex[] = "app_launcher_index"; +// "A preference for storing extra data sent in update checks for an extension. +const char kUpdateUrlData[] = "update_url_data"; + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -895,6 +898,28 @@ int ExtensionPrefs::GetNextAppLaunchIndex() { return max_value + 1; } +void ExtensionPrefs::SetUpdateUrlData(const std::string& extension_id, + const std::string& data) { + DictionaryValue* dictionary = GetExtensionPref(extension_id); + if (!dictionary) { + NOTREACHED(); + return; + } + + dictionary->SetString(kUpdateUrlData, data); + SavePrefsAndNotify(); +} + +std::string ExtensionPrefs::GetUpdateUrlData(const std::string& extension_id) { + DictionaryValue* dictionary = GetExtensionPref(extension_id); + if (!dictionary) + return std::string(); + + std::string data; + dictionary->GetString(kUpdateUrlData, &data); + return data; +} + // static void ExtensionPrefs::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(kExtensionsPref); diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index eb16329..298d03c 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -187,6 +187,13 @@ class ExtensionPrefs { // highest current application launch index found. int GetNextAppLaunchIndex(); + // The extension's update URL data. If not empty, the ExtensionUpdater + // will append a ap= parameter to the URL when checking if a new version + // of the extension is available. + void SetUpdateUrlData(const std::string& extension_id, + const std::string& data); + std::string GetUpdateUrlData(const std::string& extension_id); + static void RegisterUserPrefs(PrefService* prefs); // The underlying PrefService. diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc index a3f81ef..573da94 100644 --- a/chrome/browser/extensions/extension_updater.cc +++ b/chrome/browser/extensions/extension_updater.cc @@ -97,7 +97,8 @@ ManifestFetchData::~ManifestFetchData() {} // // (Note that '=' is %3D and '&' is %26 when urlencoded.) bool ManifestFetchData::AddExtension(std::string id, std::string version, - int days) { + int days, + const std::string& update_url_data) { if (extension_ids_.find(id) != extension_ids_.end()) { NOTREACHED() << "Duplicate extension id " << id; return false; @@ -109,6 +110,13 @@ bool ManifestFetchData::AddExtension(std::string id, std::string version, parts.push_back("v=" + version); parts.push_back("uc"); + if (!update_url_data.empty()) { + // Make sure the update_url_data string is escaped before using it so that + // there is no chance of overriding the id or v other parameter value + // we place into the x= value. + parts.push_back("ap=" + EscapeQueryParamValue(update_url_data, true)); + } + if (ShouldPing(days)) { parts.push_back("ping=" + EscapeQueryParamValue("r=" + base::IntToString(days), true)); @@ -177,12 +185,20 @@ void ManifestFetchesBuilder::AddExtension(const Extension& extension) { return; } + // If the extension updates itself from the gallery, ignore any update URL + // data. At the moment there is no extra data that an extension can + // communicate to the the gallery update servers. + std::string update_url_data; + if (!extension.UpdatesFromGallery()) + update_url_data = service_->extension_prefs()-> + GetUpdateUrlData(extension.id()); + AddExtensionData(extension.location(), extension.id(), *extension.version(), (extension.is_theme() ? PendingExtensionInfo::THEME : PendingExtensionInfo::EXTENSION), - extension.update_url()); + extension.update_url(), update_url_data); } void ManifestFetchesBuilder::AddPendingExtension( @@ -195,7 +211,7 @@ void ManifestFetchesBuilder::AddPendingExtension( Version::GetVersionFromString("0.0.0.0")); AddExtensionData(info.install_source, id, *version, - info.expected_crx_type, info.update_url); + info.expected_crx_type, info.update_url, ""); } void ManifestFetchesBuilder::ReportStats() const { @@ -230,7 +246,8 @@ void ManifestFetchesBuilder::AddExtensionData( const std::string& id, const Version& version, PendingExtensionInfo::ExpectedCrxType crx_type, - GURL update_url) { + GURL update_url, + const std::string& update_url_data) { if (!Extension::IsAutoUpdateableLocation(location)) { return; @@ -277,7 +294,7 @@ void ManifestFetchesBuilder::AddExtensionData( CalculatePingDays(service_->extension_prefs()->LastPingDay(id)); while (existing_iter != fetches_.end()) { if (existing_iter->second->AddExtension(id, version.GetString(), - ping_days)) { + ping_days, update_url_data)) { fetch = existing_iter->second; break; } @@ -286,7 +303,8 @@ void ManifestFetchesBuilder::AddExtensionData( if (!fetch) { fetch = new ManifestFetchData(update_url); fetches_.insert(std::pair<GURL, ManifestFetchData*>(update_url, fetch)); - bool added = fetch->AddExtension(id, version.GetString(), ping_days); + bool added = fetch->AddExtension(id, version.GetString(), ping_days, + update_url_data); DCHECK(added); } } @@ -736,7 +754,7 @@ void ExtensionUpdater::CheckNow() { std::string version = prefs_->GetString(kExtensionBlacklistUpdateVersion); int ping_days = CalculatePingDays(service_->extension_prefs()->BlacklistLastPingDay()); - blacklist_fetch->AddExtension(kBlacklistAppID, version, ping_days); + blacklist_fetch->AddExtension(kBlacklistAppID, version, ping_days, ""); StartUpdateCheck(blacklist_fetch); } diff --git a/chrome/browser/extensions/extension_updater.h b/chrome/browser/extensions/extension_updater.h index 1a28a4d..1e99649 100644 --- a/chrome/browser/extensions/extension_updater.h +++ b/chrome/browser/extensions/extension_updater.h @@ -43,7 +43,8 @@ class ManifestFetchData { // Returns true if this extension information was successfully added. If the // return value is false it means the full_url would have become too long, and // this ManifestFetchData object remains unchanged. - bool AddExtension(std::string id, std::string version, int ping_days); + bool AddExtension(std::string id, std::string version, int ping_days, + const std::string& update_url_data); const GURL& base_url() const { return base_url_; } const GURL& full_url() const { return full_url_; } @@ -112,7 +113,8 @@ class ManifestFetchesBuilder { const std::string& id, const Version& version, PendingExtensionInfo::ExpectedCrxType crx_type, - GURL update_url); + GURL update_url, + const std::string& update_url_data); ExtensionUpdateService* service_; // List of data on fetches we're going to do. We limit the number of diff --git a/chrome/browser/extensions/extension_updater_unittest.cc b/chrome/browser/extensions/extension_updater_unittest.cc index 53975d0..bc1a6ff 100644 --- a/chrome/browser/extensions/extension_updater_unittest.cc +++ b/chrome/browser/extensions/extension_updater_unittest.cc @@ -32,11 +32,17 @@ using base::Time; using base::TimeDelta; -static int expected_load_flags = +namespace { + +const char kEmptyUpdateUrlData[] = ""; + +int expected_load_flags = net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE; +} // namespace + // Base class for further specialized test classes. class MockService : public ExtensionUpdateService { public: @@ -402,6 +408,70 @@ class ExtensionUpdaterTest : public testing::Test { EXPECT_TRUE(ContainsKey(params, "ping")); } + static void TestUpdateUrlDataEmpty() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an empty update URL data string does not cause a ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, ""); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataSimple() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an update URL data string causes an appropriate ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, "bar"); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc%26ap%3Dbar", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataCompound() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an update URL data string causes an appropriate ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, "a=1&b=2&c"); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc%26ap%3Da%253D1%2526b%253D2%2526c", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataFromGallery(const char* gallery_url) { + MockService service; + ManifestFetchesBuilder builder(&service); + ExtensionList extensions; + std::string url(gallery_url); + + service.CreateTestExtensions(1, &extensions, &url, Extension::INTERNAL); + builder.AddExtension(*extensions[0]); + std::vector<ManifestFetchData*> fetches = builder.GetFetches(); + EXPECT_EQ(1u, fetches.size()); + scoped_ptr<ManifestFetchData> fetch(fetches[0]); + fetches.clear(); + + // Make sure that extensions that update from the gallery ignore any + // update URL data. + const std::string& update_url = fetch->full_url().spec(); + std::string::size_type x = update_url.find("x="); + EXPECT_NE(std::string::npos, x); + std::string::size_type ap = update_url.find("ap%3D", x); + EXPECT_EQ(std::string::npos, ap); + } + static void TestDetermineUpdates() { // Create a set of test extensions ServiceForManifestTests service; @@ -428,11 +498,13 @@ class ExtensionUpdaterTest : public testing::Test { scoped_ptr<Version> one(Version::GetVersionFromString("1.0")); EXPECT_TRUE(tmp[0]->version()->Equals(*one)); fetch_data.AddExtension(tmp[0]->id(), tmp[0]->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(tmp[0]->id(), "1.1", "http://localhost/e1_1.1.crx", &updates); fetch_data.AddExtension(tmp[1]->id(), tmp[1]->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(tmp[1]->id(), tmp[1]->VersionString(), "http://localhost/e2_2.0.crx", &updates); updateable = updater->DetermineUpdates(fetch_data, updates); @@ -458,7 +530,8 @@ class ExtensionUpdaterTest : public testing::Test { for (PendingExtensionMap::const_iterator it = pending_extensions.begin(); it != pending_extensions.end(); ++it) { fetch_data.AddExtension(it->first, "1.0.0.0", - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(it->first, "1.1", "http://localhost/e1_1.1.crx", &updates); } @@ -495,8 +568,9 @@ class ExtensionUpdaterTest : public testing::Test { // second one should be queued up. ManifestFetchData* fetch1 = new ManifestFetchData(url1); ManifestFetchData* fetch2 = new ManifestFetchData(url2); - fetch1->AddExtension("1111", "1.0", 0); - fetch2->AddExtension("12345", "2.0", ManifestFetchData::kNeverPinged); + fetch1->AddExtension("1111", "1.0", 0, kEmptyUpdateUrlData); + fetch2->AddExtension("12345", "2.0", ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); updater->StartUpdateCheck(fetch1); updater->StartUpdateCheck(fetch2); @@ -814,7 +888,8 @@ class ExtensionUpdaterTest : public testing::Test { ManifestFetchData fetch_data(update_url); const Extension* extension = tmp[0]; fetch_data.AddExtension(extension->id(), extension->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); UpdateManifest::Results results; results.daystart_elapsed_seconds = 750; @@ -844,6 +919,16 @@ TEST(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) { ExtensionUpdaterTest::TestBlacklistUpdateCheckRequests(); } +TEST(ExtensionUpdaterTest, TestUpdateUrlData) { + ExtensionUpdaterTest::TestUpdateUrlDataEmpty(); + ExtensionUpdaterTest::TestUpdateUrlDataSimple(); + ExtensionUpdaterTest::TestUpdateUrlDataCompound(); + ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( + extension_urls::kGalleryUpdateHttpUrl); + ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( + extension_urls::kGalleryUpdateHttpsUrl); +} + TEST(ExtensionUpdaterTest, TestDetermineUpdates) { ExtensionUpdaterTest::TestDetermineUpdates(); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 6710a08..0cdca9a 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1539,6 +1539,8 @@ 'browser/extensions/extension_message_service.h', 'browser/extensions/extension_metrics_module.cc', 'browser/extensions/extension_metrics_module.h', + 'browser/extensions/extension_module.cc', + 'browser/extensions/extension_module.h', 'browser/extensions/extension_omnibox_api.cc', 'browser/extensions/extension_omnibox_api.h', 'browser/extensions/extension_page_actions_module.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 148f254..1782ed1 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1998,6 +1998,7 @@ 'browser/extensions/extension_messages_apitest.cc', 'browser/extensions/extension_messages_browsertest.cc', 'browser/extensions/extension_metrics_apitest.cc', + 'browser/extensions/extension_module_apitest.cc', 'browser/extensions/extension_omnibox_apitest.cc', 'browser/extensions/extension_override_apitest.cc', 'browser/extensions/extension_popup_apitest.cc', diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index 68c9af0..ebc43a0f 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -188,6 +188,14 @@ "description": "Array of global window objects", "items": { "type": "object", "isInstanceOf": "DOMWindow", "properties": {}, "additionalProperties": { "type": "any" } } } + }, + { + "name": "setUpdateUrlData", + "type": "function", + "description": "Sets the value of the ap CGI parameter used in the extension's update URL. This value is ignored for extensions that are hosted in the Chrome Extension Gallery.", + "parameters": [ + {"type": "string", "name": "data", "maxLength": 1024} + ] } ], "events": [ diff --git a/chrome/common/extensions/docs/extension.html b/chrome/common/extensions/docs/extension.html index 3f7dac6..7d301ac 100644 --- a/chrome/common/extensions/docs/extension.html +++ b/chrome/common/extensions/docs/extension.html @@ -284,6 +284,8 @@ <a href="#method-getViews">getViews</a> </li><li> <a href="#method-sendRequest">sendRequest</a> + </li><li> + <a href="#method-setUpdateUrlData">setUpdateUrlData</a> </li> </ol> </li> @@ -2008,6 +2010,127 @@ For details, see </p> </div> <!-- /description --> + </div><div class="apiItem"> + <a name="method-setUpdateUrlData"></a> <!-- method-anchor --> + <h4>setUpdateUrlData</h4> + + <div class="summary"><span style="display: none; ">void</span> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.extension.setUpdateUrlData</span>(<span class="null"><span style="display: none; ">, </span><span>string</span> + <var><span>data</span></var></span>)</div> + + <div class="description"> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Sets the value of the ap CGI parameter used in the extension's update URL. This value is ignored for extensions that are hosted in the Chrome Extension Gallery.</p> + + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>data</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div> + </dl> + + <!-- RETURNS --> + <h4 style="display: none; ">Returns</h4> + <dl> + <div style="display: none; "> + <div> + </div> + </div> + </dl> + + <!-- CALLBACK --> + <div style="display: none; "> + <div> + <h4>Callback function</h4> + <p> + The callback <em>parameter</em> should specify a function + that looks like this: + </p> + <p> + If you specify the <em>callback</em> parameter, it should + specify a function that looks like this: + </p> + + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre> + <dl> + <div> + <div> + </div> + </div> + </dl> + </div> + </div> + + <!-- MIN_VERSION --> + <p style="display: none; "> + This function was added in version <b><span></span></b>. + If you require this function, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </p> + </div> <!-- /description --> + </div> <!-- /apiItem --> </div> <!-- /apiGroup --> diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 8b9c39f..41c260e 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -1854,8 +1854,7 @@ GURL Extension::GetHomepageURL() const { if (homepage_url_.is_valid()) return homepage_url_; - if (update_url()!= GURL(extension_urls::kGalleryUpdateHttpsUrl) && - update_url()!= GURL(extension_urls::kGalleryUpdateHttpUrl)) + if (!UpdatesFromGallery()) return GURL(); // TODO(erikkay): This may not be entirely correct with the webstore. @@ -2193,6 +2192,11 @@ bool Extension::CanExecuteScriptEverywhere() const { return false; } +bool Extension::UpdatesFromGallery() const { + return update_url() == GURL(extension_urls::kGalleryUpdateHttpsUrl) || + update_url() == GURL(extension_urls::kGalleryUpdateHttpUrl); +} + ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest, const std::string& id, const FilePath& path, diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index ce7e628..6c545e73 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -356,6 +356,10 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // on the whitelist of extensions that can script all pages. bool CanExecuteScriptEverywhere() const; + // Returns true if this extension updates itself using the extension + // gallery. + bool UpdatesFromGallery() const; + // Accessors: const FilePath& path() const { return path_; } diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js index c470947..c583ca0 100644 --- a/chrome/renderer/resources/renderer_extension_bindings.js +++ b/chrome/renderer/resources/renderer_extension_bindings.js @@ -113,7 +113,7 @@ var chrome = chrome || {}; // Update the renderer's port bookkeeping, without notifying the browser. CloseChannel(portId, false); if (connectionInvalid) { - var errorMsg = + var errorMsg = "Could not establish connection. Receiving end does not exist."; chrome.extension.lastError = {"message": errorMsg}; console.error("Port error: " + errorMsg); @@ -302,6 +302,7 @@ var chrome = chrome || {}; "extension.lastError", "extension.onConnectExternal", "extension.onRequestExternal", + "extension.setUpdateUrlData", "i18n.getAcceptLanguages" ]; for (var i = 0; i < privileged.length; i++) { diff --git a/chrome/test/data/extensions/api_test/extension_module/manifest.json b/chrome/test/data/extensions/api_test/extension_module/manifest.json new file mode 100644 index 0000000..4b3caa8 --- /dev/null +++ b/chrome/test/data/extensions/api_test/extension_module/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "chrome.extension", + "version": "0.1", + "description": "end-to-end browser test for some chrome.extension API", + "background_page": "test.html" +} diff --git a/chrome/test/data/extensions/api_test/extension_module/test.html b/chrome/test/data/extensions/api_test/extension_module/test.html new file mode 100644 index 0000000..46f4d74 --- /dev/null +++ b/chrome/test/data/extensions/api_test/extension_module/test.html @@ -0,0 +1 @@ +<script src="test.js"></script> diff --git a/chrome/test/data/extensions/api_test/extension_module/test.js b/chrome/test/data/extensions/api_test/extension_module/test.js new file mode 100644 index 0000000..762ba45 --- /dev/null +++ b/chrome/test/data/extensions/api_test/extension_module/test.js @@ -0,0 +1,43 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// extension api test +// browser_tests.exe --gtest_filter=ExtensionModuleApiTest.Basics + +chrome.test.runTests([ + function testUpdateUrlData() { + // Data string must not be too long. + try { + var data = + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 100 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 200 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 300 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 400 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 500 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 600 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 700 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 800 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 900 + '01234567890123456789012345678901234567890123456789' + + '01234567890123456789012345678901234567890123456789' + // 1000 + '01234567890123456789012345678901234567890123456789'; + chrome.extension.setUpdateUrlData(data); + // Should not reach this line since the above call throws. + chrome.test.fail(); + } catch(ex) { + } + + chrome.extension.setUpdateUrlData('a=1&b=2&foo'); + chrome.test.succeed(); + } +]); |