diff options
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/crx_installer.cc | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_module.cc | 23 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_module.h | 20 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_module_apitest.cc | 12 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.cc | 25 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.h | 7 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_updater.cc | 32 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_updater.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_updater_unittest.cc | 99 |
10 files changed, 213 insertions, 20 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(); } |