#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/extensions/updater/manifest_fetch_data.h"
#include "chrome/browser/extensions/updater/request_queue_impl.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/omaha_query_params/omaha_query_params.h"
+#include "chrome/browser/google/google_brand.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
+#include "components/omaha_query_params/omaha_query_params.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/id_util.h"
#include "extensions/common/manifest_constants.h"
+#include "google_apis/gaia/fake_identity_provider.h"
+#include "google_apis/gaia/fake_oauth2_token_service.h"
#include "libxml/globals.h"
#include "net/base/backoff_entry.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
+#include "net/http/http_request_headers.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/third_party/mozilla/url_parse.h"
#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#endif
const char kEmptyUpdateUrlData[] = "";
+const char kAuthUserQueryKey[] = "authuser";
+
int kExpectedLoadFlags =
net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE;
-int kExpectedLoadFlagsForProtectedDownload = net::LOAD_DISABLE_CACHE;
+int kExpectedLoadFlagsForDownloadWithCookies = net::LOAD_DISABLE_CACHE;
+
+// Fake authentication constants
+const char kFakeAccountId[] = "bobloblaw@lawblog.example.com";
+const char kFakeOAuth2Token[] = "ce n'est pas un jeton";
const ManifestFetchData::PingData kNeverPingedData(
ManifestFetchData::kNeverPinged, ManifestFetchData::kNeverPinged, true);
};
const int kNotificationsObserved[] = {
- chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED,
- chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND,
+ extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED,
+ extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
};
// A class that observes the notifications sent by the ExtensionUpdater and
for (size_t i = 0; i < arraysize(kNotificationsObserved); ++i) {
if (kNotificationsObserved[i] == type) {
count_[i]++;
- if (type == chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND) {
+ if (type == extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND) {
updated_.insert(
content::Details<UpdateDetails>(details)->id);
}
DISALLOW_COPY_AND_ASSIGN(NotificationsObserver);
};
+// Extracts the integer value of the |authuser| query parameter. Returns 0 if
+// the parameter is not set.
+int GetAuthUserQueryValue(const GURL& url) {
+ std::string query_string = url.query();
+ url::Component query(0, query_string.length());
+ url::Component key, value;
+ while (
+ url::ExtractQueryKeyValue(query_string.c_str(), &query, &key, &value)) {
+ std::string key_string = query_string.substr(key.begin, key.len);
+ if (key_string == kAuthUserQueryKey) {
+ int user_index = 0;
+ base::StringToInt(query_string.substr(value.begin, value.len),
+ &user_index);
+ return user_index;
+ }
+ }
+ return 0;
+}
+
} // namespace
// Base class for further specialized test classes.
class MockService : public TestExtensionService {
public:
explicit MockService(TestExtensionPrefs* prefs)
- : prefs_(prefs), pending_extension_manager_(*this, &profile_) {}
+ : prefs_(prefs),
+ pending_extension_manager_(&profile_),
+ downloader_delegate_override_(NULL) {
+ }
virtual ~MockService() {}
PrefService* pref_service() { return prefs_->pref_service(); }
+ FakeOAuth2TokenService* fake_token_service() {
+ return fake_token_service_.get();
+ }
+
// Creates test extensions and inserts them into list. The name and
// version are all based on their index. If |update_url| is non-null, it
// will be used as the update_url for each extension.
}
}
+ ExtensionDownloader::Factory GetDownloaderFactory() {
+ return base::Bind(&MockService::CreateExtensionDownloader,
+ base::Unretained(this));
+ }
+
+ ExtensionDownloader::Factory GetAuthenticatedDownloaderFactory() {
+ return base::Bind(&MockService::CreateExtensionDownloaderWithIdentity,
+ base::Unretained(this));
+ }
+
+ void OverrideDownloaderDelegate(ExtensionDownloaderDelegate* delegate) {
+ downloader_delegate_override_ = delegate;
+ }
+
protected:
TestExtensionPrefs* const prefs_;
TestingProfile profile_;
PendingExtensionManager pending_extension_manager_;
private:
+ scoped_ptr<ExtensionDownloader> CreateExtensionDownloader(
+ ExtensionDownloaderDelegate* delegate) {
+ return make_scoped_ptr(new ExtensionDownloader(
+ downloader_delegate_override_ ? downloader_delegate_override_
+ : delegate,
+ request_context()));
+ }
+
+ scoped_ptr<ExtensionDownloader> CreateExtensionDownloaderWithIdentity(
+ ExtensionDownloaderDelegate* delegate) {
+ scoped_ptr<FakeIdentityProvider> fake_identity_provider;
+ fake_token_service_.reset(new FakeOAuth2TokenService());
+ fake_identity_provider.reset(new FakeIdentityProvider(
+ fake_token_service_.get()));
+ fake_identity_provider->LogIn(kFakeAccountId);
+ fake_token_service_->AddAccount(kFakeAccountId);
+
+ scoped_ptr<ExtensionDownloader> downloader(
+ CreateExtensionDownloader(delegate));
+ downloader->SetWebstoreIdentityProvider(
+ fake_identity_provider.PassAs<IdentityProvider>());
+ return downloader.Pass();
+ }
+
+ scoped_ptr<FakeOAuth2TokenService> fake_token_service_;
+
+ ExtensionDownloaderDelegate* downloader_delegate_override_;
+
DISALLOW_COPY_AND_ASSIGN(MockService);
};
const bool kIsFromSync = true;
const bool kInstallSilently = true;
const bool kMarkAcknowledged = false;
+ const bool kRemoteInstall = false;
std::string id = id_util::GenerateId(base::StringPrintf("extension%i", i));
pending_extension_manager->AddForTesting(
kInstallSilently,
Manifest::INTERNAL,
Extension::NO_FLAGS,
- kMarkAcknowledged));
+ kMarkAcknowledged,
+ kRemoteInstall));
}
}
class ServiceForManifestTests : public MockService {
public:
explicit ServiceForManifestTests(TestExtensionPrefs* prefs)
- : MockService(prefs), registry_(ExtensionRegistry::Get(profile())) {}
+ : MockService(prefs),
+ registry_(ExtensionRegistry::Get(profile())) {
+ }
virtual ~ServiceForManifestTests() {}
const std::string& id,
const base::FilePath& extension_path,
bool file_ownership_passed,
- const GURL& download_url,
CrxInstaller** out_crx_installer) OVERRIDE {
extension_id_ = id;
install_path_ = extension_path;
- download_url_ = download_url;
if (ContainsKey(fake_crx_installers_, id)) {
*out_crx_installer = fake_crx_installers_[id];
const std::string& extension_id() const { return extension_id_; }
const base::FilePath& install_path() const { return install_path_; }
- const GURL& download_url() const { return download_url_; }
private:
// Hold the set of ids that UpdateExtension() should fake success on.
std::map<std::string, std::string> params;
ExtractParameters(query, ¶ms);
- std::string omaha_params =
- chrome::OmahaQueryParams::Get(chrome::OmahaQueryParams::CRX);
+ std::string omaha_params = omaha_query_params::OmahaQueryParams::Get(
+ omaha_query_params::OmahaQueryParams::CRX);
std::map<std::string, std::string> expected;
ExtractParameters(omaha_params, &expected);
EXPECT_TRUE(updater->timer_.IsRunning());
updater->timer_.Stop();
updater->TimerFired();
+ content::RunAllBlockingPoolTasksUntilIdle();
}
// Adds a Result with the given data to results.
results->list.push_back(result);
}
- void ResetDownloader(ExtensionUpdater* updater,
- ExtensionDownloader* downloader) {
- EXPECT_FALSE(updater->downloader_.get());
- updater->downloader_.reset(downloader);
- }
-
void StartUpdateCheck(ExtensionDownloader* downloader,
ManifestFetchData* fetch_data) {
downloader->StartUpdateCheck(scoped_ptr<ManifestFetchData>(fetch_data));
// Set up and start the updater.
net::TestURLFetcherFactory factory;
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), 60*60*24, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ 60 * 60 * 24,
+ NULL,
+ service.GetDownloaderFactory());
updater.Start();
// Tell the update that it's time to do update checks.
// option to appear in the x= parameter.
ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0);
fetch_data.AddExtension(
- id, version, &kNeverPingedData, std::string(), std::string());
+ id, version, &kNeverPingedData, std::string(), std::string(), false);
std::map<std::string, std::string> params;
VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms);
// option to appear in the x= parameter.
ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0);
fetch_data.AddExtension(
- id, version, &kNeverPingedData, "bar", std::string());
+ id, version, &kNeverPingedData, "bar", std::string(), false);
std::map<std::string, std::string> params;
VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms);
EXPECT_EQ(id, params["id"]);
// option to appear in the x= parameter.
ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0);
fetch_data.AddExtension(
- id, version, &kNeverPingedData, "a=1&b=2&c", std::string());
+ id, version, &kNeverPingedData, "a=1&b=2&c", std::string(), false);
std::map<std::string, std::string> params;
VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms);
EXPECT_EQ(id, params["id"]);
// Make sure that an installsource= appears in the x= parameter.
ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0);
fetch_data.AddExtension(id, version, &kNeverPingedData,
- kEmptyUpdateUrlData, install_source);
+ kEmptyUpdateUrlData, install_source, false);
std::map<std::string, std::string> params;
VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms);
EXPECT_EQ(id, params["id"]);
const std::string id1 = id_util::GenerateId("1");
const std::string id2 = id_util::GenerateId("2");
fetch_data.AddExtension(
- id1, "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string());
+ id1, "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(),
+ false);
AddParseResult(id1, "1.1", "http://localhost/e1_1.1.crx", &updates);
fetch_data.AddExtension(
- id2, "2.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string());
+ id2, "2.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(),
+ false);
AddParseResult(id2, "2.0.0.0", "http://localhost/e2_2.0.crx", &updates);
EXPECT_CALL(delegate, IsExtensionPending(_)).WillRepeatedly(Return(false));
"1.0.0.0",
&kNeverPingedData,
kEmptyUpdateUrlData,
- std::string());
+ std::string(),
+ false);
AddParseResult(*it, "1.1", "http://localhost/e1_1.1.crx", &updates);
}
void TestMultipleManifestDownloading() {
net::TestURLFetcherFactory factory;
+ factory.set_remove_fetcher_on_delete(true);
net::TestURLFetcher* fetcher = NULL;
- NotificationsObserver observer;
MockService service(prefs_.get());
MockExtensionDownloaderDelegate delegate;
ExtensionDownloader downloader(&delegate, service.request_context());
scoped_ptr<ManifestFetchData> fetch4(new ManifestFetchData(kUpdateUrl, 0));
ManifestFetchData::PingData zeroDays(0, 0, true);
fetch1->AddExtension(
- "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
fetch2->AddExtension(
- "2222", "2.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "2222", "2.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
fetch3->AddExtension(
- "3333", "3.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "3333", "3.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
fetch4->AddExtension(
- "4444", "4.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "4444", "4.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
// This will start the first fetcher and queue the others. The next in queue
- // is started as each fetcher receives its response.
+ // is started as each fetcher receives its response. Note that the fetchers
+ // don't necessarily run in the order that they are started from here.
+ GURL fetch1_url = fetch1->full_url();
+ GURL fetch2_url = fetch2->full_url();
+ GURL fetch3_url = fetch3->full_url();
+ GURL fetch4_url = fetch4->full_url();
downloader.StartUpdateCheck(fetch1.Pass());
downloader.StartUpdateCheck(fetch2.Pass());
downloader.StartUpdateCheck(fetch3.Pass());
downloader.StartUpdateCheck(fetch4.Pass());
RunUntilIdle();
- // The first fetch will fail.
- fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
- EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
- EXPECT_CALL(delegate, OnExtensionDownloadFailed(
- "1111", ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED, _, _));
- fetcher->set_url(kUpdateUrl);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(400);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(&delegate);
-
- // The second fetch gets invalid data.
- const std::string kInvalidXml = "invalid xml";
- fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
- EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
- EXPECT_CALL(delegate, OnExtensionDownloadFailed(
- "2222", ExtensionDownloaderDelegate::MANIFEST_INVALID, _, _))
- .WillOnce(InvokeWithoutArgs(&delegate,
- &MockExtensionDownloaderDelegate::Quit));
- fetcher->set_url(kUpdateUrl);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseString(kInvalidXml);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- delegate.Wait();
- Mock::VerifyAndClearExpectations(&delegate);
-
- // The third fetcher doesn't have an update available.
- const std::string kNoUpdate =
- "<?xml version='1.0' encoding='UTF-8'?>"
- "<gupdate xmlns='http://www.google.com/update2/response'"
- " protocol='2.0'>"
- " <app appid='3333'>"
- " <updatecheck codebase='http://example.com/extension_3.0.0.0.crx'"
- " version='3.0.0.0' prodversionmin='3.0.0.0' />"
- " </app>"
- "</gupdate>";
- fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
- EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
- EXPECT_CALL(delegate, IsExtensionPending("3333")).WillOnce(Return(false));
- EXPECT_CALL(delegate, GetExtensionExistingVersion("3333", _))
- .WillOnce(DoAll(SetArgPointee<1>("3.0.0.0"),
- Return(true)));
- EXPECT_CALL(delegate, OnExtensionDownloadFailed(
- "3333", ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE, _, _))
- .WillOnce(InvokeWithoutArgs(&delegate,
- &MockExtensionDownloaderDelegate::Quit));
- fetcher->set_url(kUpdateUrl);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseString(kNoUpdate);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- delegate.Wait();
- Mock::VerifyAndClearExpectations(&delegate);
+ for (int i = 0; i < 4; ++i) {
+ fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
+ ASSERT_TRUE(fetcher);
+ ASSERT_TRUE(fetcher->delegate());
+ EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
+ EXPECT_FALSE(fetcher->GetOriginalURL().is_empty());
+
+ if (fetcher->GetOriginalURL() == fetch1_url) {
+ // The first fetch will fail.
+ EXPECT_CALL(delegate, OnExtensionDownloadFailed(
+ "1111", ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED, _, _));
+ fetcher->set_url(kUpdateUrl);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(400);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+ Mock::VerifyAndClearExpectations(&delegate);
+ fetch1_url = GURL();
+ } else if (fetcher->GetOriginalURL() == fetch2_url) {
+ // The second fetch gets invalid data.
+ const std::string kInvalidXml = "invalid xml";
+ EXPECT_CALL(delegate, OnExtensionDownloadFailed(
+ "2222", ExtensionDownloaderDelegate::MANIFEST_INVALID, _, _))
+ .WillOnce(InvokeWithoutArgs(
+ &delegate,
+ &MockExtensionDownloaderDelegate::Quit));
+ fetcher->set_url(kUpdateUrl);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(200);
+ fetcher->SetResponseString(kInvalidXml);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ delegate.Wait();
+ Mock::VerifyAndClearExpectations(&delegate);
+ fetch2_url = GURL();
+ } else if (fetcher->GetOriginalURL() == fetch3_url) {
+ // The third fetcher doesn't have an update available.
+ const std::string kNoUpdate =
+ "<?xml version='1.0' encoding='UTF-8'?>"
+ "<gupdate xmlns='http://www.google.com/update2/response'"
+ " protocol='2.0'>"
+ " <app appid='3333'>"
+ " <updatecheck codebase='http://example.com/extension_3.0.0.0.crx'"
+ " version='3.0.0.0' prodversionmin='3.0.0.0' />"
+ " </app>"
+ "</gupdate>";
+ EXPECT_CALL(delegate, IsExtensionPending("3333"))
+ .WillOnce(Return(false));
+ EXPECT_CALL(delegate, GetExtensionExistingVersion("3333", _))
+ .WillOnce(DoAll(SetArgPointee<1>("3.0.0.0"),
+ Return(true)));
+ EXPECT_CALL(delegate, OnExtensionDownloadFailed(
+ "3333", ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE, _, _))
+ .WillOnce(InvokeWithoutArgs(
+ &delegate,
+ &MockExtensionDownloaderDelegate::Quit));
+ fetcher->set_url(kUpdateUrl);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(200);
+ fetcher->SetResponseString(kNoUpdate);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ delegate.Wait();
+ Mock::VerifyAndClearExpectations(&delegate);
+ fetch3_url = GURL();
+ } else if (fetcher->GetOriginalURL() == fetch4_url) {
+ // The last fetcher has an update.
+ NotificationsObserver observer;
+ const std::string kUpdateAvailable =
+ "<?xml version='1.0' encoding='UTF-8'?>"
+ "<gupdate xmlns='http://www.google.com/update2/response'"
+ " protocol='2.0'>"
+ " <app appid='4444'>"
+ " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'"
+ " version='4.0.42.0' prodversionmin='4.0.42.0' />"
+ " </app>"
+ "</gupdate>";
+ EXPECT_CALL(delegate, IsExtensionPending("4444"))
+ .WillOnce(Return(false));
+ EXPECT_CALL(delegate, GetExtensionExistingVersion("4444", _))
+ .WillOnce(DoAll(SetArgPointee<1>("4.0.0.0"),
+ Return(true)));
+ fetcher->set_url(kUpdateUrl);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(200);
+ fetcher->SetResponseString(kUpdateAvailable);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ observer.Wait();
+ Mock::VerifyAndClearExpectations(&delegate);
+
+ // Verify that the downloader decided to update this extension.
+ EXPECT_EQ(1u, observer.UpdatedCount());
+ EXPECT_TRUE(observer.Updated("4444"));
+ fetch4_url = GURL();
+ } else {
+ ADD_FAILURE() << "Unexpected fetch: " << fetcher->GetOriginalURL();
+ }
+ }
- // The last fetcher has an update.
- const std::string kUpdateAvailable =
- "<?xml version='1.0' encoding='UTF-8'?>"
- "<gupdate xmlns='http://www.google.com/update2/response'"
- " protocol='2.0'>"
- " <app appid='4444'>"
- " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'"
- " version='4.0.42.0' prodversionmin='4.0.42.0' />"
- " </app>"
- "</gupdate>";
fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
- EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
- EXPECT_CALL(delegate, IsExtensionPending("4444")).WillOnce(Return(false));
- EXPECT_CALL(delegate, GetExtensionExistingVersion("4444", _))
- .WillOnce(DoAll(SetArgPointee<1>("4.0.0.0"),
- Return(true)));
- fetcher->set_url(kUpdateUrl);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseString(kUpdateAvailable);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- observer.Wait();
- Mock::VerifyAndClearExpectations(&delegate);
-
- // Verify that the downloader decided to update this extension.
- EXPECT_EQ(1u, observer.UpdatedCount());
- EXPECT_TRUE(observer.Updated("4444"));
+ if (fetcher)
+ ADD_FAILURE() << "Unexpected fetch: " << fetcher->GetOriginalURL();
}
void TestManifestRetryDownloading() {
scoped_ptr<ManifestFetchData> fetch(new ManifestFetchData(kUpdateUrl, 0));
ManifestFetchData::PingData zeroDays(0, 0, true);
fetch->AddExtension(
- "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
// This will start the first fetcher.
downloader.StartUpdateCheck(fetch.Pass());
// should not retry.
fetch.reset(new ManifestFetchData(kUpdateUrl, 0));
fetch->AddExtension(
- "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string());
+ "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
// This will start the first fetcher.
downloader.StartUpdateCheck(fetch.Pass());
net::TestURLFetcher* fetcher = NULL;
scoped_ptr<ServiceForDownloadTests> service(
new ServiceForDownloadTests(prefs_.get()));
- ExtensionUpdater updater(service.get(), service->extension_prefs(),
+ ExtensionUpdater updater(service.get(),
+ service->extension_prefs(),
service->pref_service(),
service->profile(),
kUpdateFrequencySecs,
- NULL);
- updater.Start();
+ NULL,
+ service->GetDownloaderFactory());
MockExtensionDownloaderDelegate delegate;
delegate.DelegateTo(&updater);
- ResetDownloader(
- &updater,
- new ExtensionDownloader(&delegate, service->request_context()));
+ service->OverrideDownloaderDelegate(&delegate);
+ updater.Start();
+ updater.EnsureDownloaderCreated();
updater.downloader_->extensions_queue_.set_backoff_policy(
&kNoBackoffPolicy);
const bool kIsFromSync = true;
const bool kInstallSilently = true;
const bool kMarkAcknowledged = false;
+ const bool kRemoteInstall = false;
PendingExtensionManager* pending_extension_manager =
service->pending_extension_manager();
pending_extension_manager->AddForTesting(
kInstallSilently,
Manifest::INTERNAL,
Extension::NO_FLAGS,
- kMarkAcknowledged));
+ kMarkAcknowledged,
+ kRemoteInstall));
}
// Call back the ExtensionUpdater with a 200 response and some test data
EXPECT_EQ(id, service->extension_id());
base::FilePath tmpfile_path = service->install_path();
EXPECT_FALSE(tmpfile_path.empty());
- EXPECT_EQ(test_url, service->download_url());
EXPECT_EQ(extension_file_path, tmpfile_path);
}
}
// Update a single extension in an environment where the download request
- // initially responds with a 403 status. Expect the fetcher to automatically
- // retry with cookies enabled.
- void TestSingleProtectedExtensionDownloading(bool use_https, bool fail) {
+ // initially responds with a 403 status. If |identity_provider| is not NULL,
+ // this will first expect a request which includes an Authorization header
+ // with an OAuth2 bearer token; otherwise, or if OAuth2 failure is simulated,
+ // this expects the downloader to fall back onto cookie-based credentials.
+ void TestProtectedDownload(
+ const std::string& url_prefix,
+ bool enable_oauth2,
+ bool succeed_with_oauth2,
+ int valid_authuser,
+ int max_authuser) {
net::TestURLFetcherFactory factory;
net::TestURLFetcher* fetcher = NULL;
scoped_ptr<ServiceForDownloadTests> service(
new ServiceForDownloadTests(prefs_.get()));
- ExtensionUpdater updater(service.get(), service->extension_prefs(),
- service->pref_service(),
- service->profile(),
- kUpdateFrequencySecs,
- NULL);
+ const ExtensionDownloader::Factory& downloader_factory =
+ enable_oauth2 ? service->GetAuthenticatedDownloaderFactory()
+ : service->GetDownloaderFactory();
+ ExtensionUpdater updater(
+ service.get(),
+ service->extension_prefs(),
+ service->pref_service(),
+ service->profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ downloader_factory);
updater.Start();
- ResetDownloader(
- &updater,
- new ExtensionDownloader(&updater, service->request_context()));
+ updater.EnsureDownloaderCreated();
updater.downloader_->extensions_queue_.set_backoff_policy(
&kNoBackoffPolicy);
- GURL test_url(use_https ? "https://localhost/extension.crx" :
- "http://localhost/extension.crx");
-
+ GURL test_url(base::StringPrintf("%s/extension.crx", url_prefix.c_str()));
std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
std::string hash;
- Version version("0.0.1");
+ Version version("0.0.1");
std::set<int> requests;
requests.insert(0);
scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch(
fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
+ EXPECT_EQ(kExpectedLoadFlags, fetcher->GetLoadFlags());
// Fake a 403 response.
fetcher->set_url(test_url);
fetcher->set_status(net::URLRequestStatus());
fetcher->set_response_code(403);
fetcher->delegate()->OnURLFetchComplete(fetcher);
+
+ if (service->fake_token_service()) {
+ service->fake_token_service()->IssueAllTokensForAccount(
+ kFakeAccountId, kFakeOAuth2Token, base::Time::Now());
+ }
RunUntilIdle();
- // Verify that the fetcher has been switched to protected download mode
- // so that cookies would be sent with the next request (https only).
+ bool using_oauth2 = false;
+ int expected_load_flags = kExpectedLoadFlags;
+ // Verify that the fetch has had its credentials properly incremented.
fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- if (use_https) {
- EXPECT_TRUE(
- fetcher->GetLoadFlags() == kExpectedLoadFlagsForProtectedDownload);
+ net::HttpRequestHeaders fetch_headers;
+ fetcher->GetExtraRequestHeaders(&fetch_headers);
+ // If the download URL is not https, no credentials should be provided.
+ if (!test_url.SchemeIsSecure()) {
+ // No cookies.
+ EXPECT_EQ(kExpectedLoadFlags, fetcher->GetLoadFlags());
+ // No Authorization header.
+ EXPECT_FALSE(fetch_headers.HasHeader(
+ net::HttpRequestHeaders::kAuthorization));
+ expected_load_flags = kExpectedLoadFlags;
} else {
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
+ // HTTPS is in use, so credentials are allowed.
+ if (enable_oauth2 && test_url.DomainIs("google.com")) {
+ // If an IdentityProvider is present and the URL is a google.com
+ // URL, the fetcher should be in OAuth2 mode after the intitial
+ // challenge.
+ EXPECT_TRUE(fetch_headers.HasHeader(
+ net::HttpRequestHeaders::kAuthorization));
+ std::string expected_header_value = base::StringPrintf("Bearer %s",
+ kFakeOAuth2Token);
+ std::string actual_header_value;
+ fetch_headers.GetHeader(net::HttpRequestHeaders::kAuthorization,
+ &actual_header_value);
+ EXPECT_EQ(expected_header_value, actual_header_value);
+ using_oauth2 = true;
+ } else {
+ // No IdentityProvider (or no google.com), so expect cookies instead of
+ // an Authorization header.
+ EXPECT_FALSE(fetch_headers.HasHeader(
+ net::HttpRequestHeaders::kAuthorization));
+ EXPECT_EQ(kExpectedLoadFlagsForDownloadWithCookies,
+ fetcher->GetLoadFlags());
+ expected_load_flags = kExpectedLoadFlagsForDownloadWithCookies;
+ }
}
- // Attempt to fetch again after the auth failure.
- if (fail) {
- // Fail and verify that the fetch queue is cleared.
- fetcher->set_url(test_url);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(403);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- RunUntilIdle();
- EXPECT_EQ(0U, updater.downloader_->extensions_queue_.active_request());
- } else {
- // Succeed
+ bool success = false;
+ if (using_oauth2) {
+ if (succeed_with_oauth2) {
+ success = true;
+ } else {
+ // Simulate OAuth2 failure and ensure that we fall back on cookies.
+ fetcher->set_url(test_url);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(403);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+
+ const ExtensionDownloader::ExtensionFetch& fetch =
+ *updater.downloader_->extensions_queue_.active_request();
+ EXPECT_EQ(0, GetAuthUserQueryValue(fetch.url));
+ EXPECT_EQ(ExtensionDownloader::ExtensionFetch::CREDENTIALS_COOKIES,
+ fetch.credentials);
+
+ fetcher = factory.GetFetcherByID(
+ ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
+ fetcher->GetExtraRequestHeaders(&fetch_headers);
+ EXPECT_FALSE(fetch_headers.HasHeader(
+ net::HttpRequestHeaders::kAuthorization));
+ EXPECT_EQ(kExpectedLoadFlagsForDownloadWithCookies,
+ fetcher->GetLoadFlags());
+ expected_load_flags = kExpectedLoadFlagsForDownloadWithCookies;
+ }
+ }
+
+ if (!success) {
+ // Not yet ready to simulate a successful fetch. At this point we begin
+ // simulating cookie-based authentication with increasing values of
+ // authuser (starting from 0.)
+ int user_index = 0;
+ for (; user_index <= max_authuser; ++user_index) {
+ const ExtensionDownloader::ExtensionFetch& fetch =
+ *updater.downloader_->extensions_queue_.active_request();
+ EXPECT_EQ(user_index, GetAuthUserQueryValue(fetch.url));
+ if (user_index == valid_authuser) {
+ success = true;
+ break;
+ }
+ // Simulate an authorization failure which should elicit an increment
+ // of the authuser value.
+ fetcher =
+ factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
+ EXPECT_EQ(expected_load_flags, fetcher->GetLoadFlags());
+ fetcher->set_url(fetch.url);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(403);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+ }
+
+ // Simulate exhaustion of all available authusers.
+ if (!success && user_index > max_authuser) {
+ const ExtensionDownloader::ExtensionFetch& fetch =
+ *updater.downloader_->extensions_queue_.active_request();
+ fetcher =
+ factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
+ fetcher->set_url(fetch.url);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(401);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+ }
+ }
+
+ // Simulate successful authorization with a 200 response.
+ if (success) {
+ fetcher =
+ factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
base::FilePath extension_file_path(FILE_PATH_LITERAL("/whatever"));
fetcher->set_url(test_url);
fetcher->set_status(net::URLRequestStatus());
EXPECT_EQ(id, service->extension_id());
base::FilePath tmpfile_path = service->install_path();
EXPECT_FALSE(tmpfile_path.empty());
- EXPECT_EQ(test_url, service->download_url());
EXPECT_EQ(extension_file_path, tmpfile_path);
}
}
net::TestURLFetcherFactory factory;
net::TestURLFetcher* fetcher = NULL;
ServiceForDownloadTests service(prefs_.get());
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
updater.Start();
- ResetDownloader(
- &updater,
- new ExtensionDownloader(&updater, service.request_context()));
+ updater.EnsureDownloaderCreated();
updater.downloader_->extensions_queue_.set_backoff_policy(
&kNoBackoffPolicy);
base::FilePath tmpfile_path = service.install_path();
EXPECT_FALSE(tmpfile_path.empty());
EXPECT_EQ(id1, service.extension_id());
- EXPECT_EQ(url1, service.download_url());
RunUntilIdle();
// Make sure the second fetch finished and asked the service to do an
// The second install should not have run, because the first has not
// sent a notification that it finished.
EXPECT_EQ(id1, service.extension_id());
- EXPECT_EQ(url1, service.download_url());
// Fake install notice. This should start the second installation,
// which will be checked below.
}
EXPECT_EQ(id2, service.extension_id());
- EXPECT_EQ(url2, service.download_url());
EXPECT_FALSE(service.install_path().empty());
// Make sure the correct crx contents were passed for the update call.
}
void TestGalleryRequestsWithBrand(bool use_organic_brand_code) {
- google_util::BrandForTesting brand_for_testing(
+ google_brand::BrandForTesting brand_for_testing(
use_organic_brand_code ? "GGLS" : "TEST");
// We want to test a variety of combinations of expected ping conditions for
if (active_bit)
prefs->SetActiveBit(id, true);
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
ExtensionUpdater::CheckParams params;
updater.Start();
updater.CheckNow(params);
+ content::RunAllBlockingPoolTasksUntilIdle();
// Make the updater do manifest fetching, and note the urls it tries to
// fetch.
Manifest::INTERNAL);
service.set_extensions(tmp, ExtensionList());
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
updater.Start();
- ResetDownloader(
- &updater,
- new ExtensionDownloader(&updater, service.request_context()));
+ updater.EnsureDownloaderCreated();
ManifestFetchData fetch_data(update_url, 0);
const Extension* extension = tmp[0].get();
extension->VersionString(),
&kNeverPingedData,
kEmptyUpdateUrlData,
- std::string());
+ std::string(),
+ false);
UpdateManifest::Results results;
results.daystart_elapsed_seconds = 750;
TestSingleExtensionDownloading(true, false, true);
}
-TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloading) {
- TestSingleProtectedExtensionDownloading(true, false);
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadCookieAuth) {
+ TestProtectedDownload(
+ "https://chrome.google.com/webstore/download",
+ false, false, // No OAuth2 support
+ 0, 0);
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadCookieFailure) {
+ TestProtectedDownload(
+ "https://chrome.google.com/webstore/download",
+ false, false, // No OAuth2 support
+ 0, -1); // max_authuser=-1 simulates no valid authuser value.
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithNonDefaultAuthUser1) {
+ TestProtectedDownload("https://google.com", false, false, 1, 1);
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithNonDefaultAuthUser2) {
+ TestProtectedDownload("https://google.com", false, false, 2, 2);
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadAuthUserExhaustionFailure) {
+ TestProtectedDownload("https://google.com", false, false, 2, 5);
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithOAuth2Token) {
+ TestProtectedDownload(
+ "https://google.com",
+ true, true,
+ 0, -1);
+}
+
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithOAuth2Failure) {
+ TestProtectedDownload(
+ "https://google.com",
+ true, false,
+ 0, -1);
}
-TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloadingFailure) {
- TestSingleProtectedExtensionDownloading(true, true);
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadNoOAuth2WithNonGoogleDomain) {
+ TestProtectedDownload(
+ "https://not-google.com",
+ true, true,
+ 0, -1);
}
-TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloadingNoHTTPS) {
- TestSingleProtectedExtensionDownloading(false, false);
+TEST_F(ExtensionUpdaterTest, ProtectedDownloadFailWithoutHTTPS) {
+ TestProtectedDownload(
+ "http://google.com",
+ true, true,
+ 0, 0);
}
TEST_F(ExtensionUpdaterTest, TestMultipleExtensionDownloadingUpdatesFail) {
TEST_F(ExtensionUpdaterTest, TestNonAutoUpdateableLocations) {
net::TestURLFetcherFactory factory;
ServiceForManifestTests service(prefs_.get());
- ExtensionUpdater updater(&service, service.extension_prefs(),
- service.pref_service(), service.profile(),
- kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
MockExtensionDownloaderDelegate delegate;
- // Set the downloader directly, so that all its events end up in the mock
- // |delegate|.
- ExtensionDownloader* downloader =
- new ExtensionDownloader(&delegate, service.request_context());
- ResetDownloader(&updater, downloader);
+ service.OverrideDownloaderDelegate(&delegate);
// Non-internal non-external extensions should be rejected.
ExtensionList extensions;
// These expectations fail if the delegate's methods are invoked for the
// first extension, which has a non-matching id.
- EXPECT_CALL(delegate, GetUpdateUrlData(updateable_id)).WillOnce(Return(""));
+ EXPECT_CALL(delegate,
+ GetUpdateUrlData(updateable_id)).WillOnce(Return(""));
EXPECT_CALL(delegate, GetPingDataForExtension(updateable_id, _));
service.set_extensions(extensions, ExtensionList());
ExtensionUpdater::CheckParams params;
updater.Start();
updater.CheckNow(params);
+ content::RunAllBlockingPoolTasksUntilIdle();
}
TEST_F(ExtensionUpdaterTest, TestUpdatingDisabledExtensions) {
net::TestURLFetcherFactory factory;
ServiceForManifestTests service(prefs_.get());
- ExtensionUpdater updater(&service, service.extension_prefs(),
- service.pref_service(), service.profile(),
- kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
MockExtensionDownloaderDelegate delegate;
- // Set the downloader directly, so that all its events end up in the mock
- // |delegate|.
- ExtensionDownloader* downloader =
- new ExtensionDownloader(&delegate, service.request_context());
- ResetDownloader(&updater, downloader);
+ service.OverrideDownloaderDelegate(&delegate);
// Non-internal non-external extensions should be rejected.
ExtensionList enabled_extensions;
// We expect that both enabled and disabled extensions are auto-updated.
EXPECT_CALL(delegate, GetUpdateUrlData(enabled_id)).WillOnce(Return(""));
EXPECT_CALL(delegate, GetPingDataForExtension(enabled_id, _));
- EXPECT_CALL(delegate, GetUpdateUrlData(disabled_id)).WillOnce(Return(""));
+ EXPECT_CALL(delegate,
+ GetUpdateUrlData(disabled_id)).WillOnce(Return(""));
EXPECT_CALL(delegate, GetPingDataForExtension(disabled_id, _));
service.set_extensions(enabled_extensions, disabled_extensions);
ExtensionUpdater::CheckParams params;
updater.Start();
updater.CheckNow(params);
+ content::RunAllBlockingPoolTasksUntilIdle();
}
TEST_F(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
TEST_F(ExtensionUpdaterTest, TestCheckSoon) {
ServiceForManifestTests service(prefs_.get());
net::TestURLFetcherFactory factory;
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), kUpdateFrequencySecs, NULL);
+ ExtensionUpdater updater(&service,
+ service.extension_prefs(),
+ service.pref_service(),
+ service.profile(),
+ kUpdateFrequencySecs,
+ NULL,
+ service.GetDownloaderFactory());
EXPECT_FALSE(updater.WillCheckSoon());
updater.Start();
EXPECT_FALSE(updater.WillCheckSoon());