#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_sync_data.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/test_extension_prefs.h"
#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/extensions/test_extension_system.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/prefs/pref_service_syncable.h"
-#include "chrome/common/omaha_query_params/omaha_query_params.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_details.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_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"
using base::TimeDelta;
using content::BrowserThread;
using testing::DoAll;
+using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE;
+int kExpectedLoadFlagsForProtectedDownload = net::LOAD_DISABLE_CACHE;
+
const ManifestFetchData::PingData kNeverPingedData(
ManifestFetchData::kNeverPinged, ManifestFetchData::kNeverPinged, true);
quit_closure_.Run();
}
+ void DelegateTo(ExtensionDownloaderDelegate* delegate) {
+ ON_CALL(*this, OnExtensionDownloadFailed(_, _, _, _))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::OnExtensionDownloadFailed));
+ ON_CALL(*this, OnExtensionDownloadFinished(_, _, _, _, _, _, _))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::OnExtensionDownloadFinished));
+ ON_CALL(*this, GetPingDataForExtension(_, _))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::GetPingDataForExtension));
+ ON_CALL(*this, GetUpdateUrlData(_))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::GetUpdateUrlData));
+ ON_CALL(*this, IsExtensionPending(_))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::IsExtensionPending));
+ ON_CALL(*this, GetExtensionExistingVersion(_, _))
+ .WillByDefault(Invoke(delegate,
+ &ExtensionDownloaderDelegate::GetExtensionExistingVersion));
+ }
+
private:
base::Closure quit_closure_;
};
class ServiceForManifestTests : public MockService {
public:
explicit ServiceForManifestTests(TestExtensionPrefs* prefs)
- : MockService(prefs) {
- }
+ : MockService(prefs), registry_(ExtensionRegistry::Get(profile())) {}
virtual ~ServiceForManifestTests() {}
virtual const Extension* GetExtensionById(
const std::string& id, bool include_disabled) const OVERRIDE {
- const Extension* result = extensions_.GetByID(id);
+ const Extension* result = registry_->enabled_extensions().GetByID(id);
if (result || !include_disabled)
return result;
- return disabled_extensions_.GetByID(id);
+ return registry_->disabled_extensions().GetByID(id);
}
virtual const ExtensionSet* extensions() const OVERRIDE {
- return &extensions_;
- }
-
- virtual const ExtensionSet* disabled_extensions() const OVERRIDE {
- return &disabled_extensions_;
+ return ®istry_->enabled_extensions();
}
virtual PendingExtensionManager* pending_extension_manager() OVERRIDE {
}
virtual bool IsExtensionEnabled(const std::string& id) const OVERRIDE {
- return !disabled_extensions_.Contains(id);
+ return !registry_->disabled_extensions().Contains(id);
}
- void set_extensions(ExtensionList extensions) {
+ void set_extensions(ExtensionList extensions,
+ ExtensionList disabled_extensions) {
+ registry_->ClearAll();
for (ExtensionList::const_iterator it = extensions.begin();
it != extensions.end(); ++it) {
- extensions_.Insert(*it);
+ registry_->AddEnabled(*it);
}
- }
-
- void set_disabled_extensions(ExtensionList disabled_extensions) {
for (ExtensionList::const_iterator it = disabled_extensions.begin();
it != disabled_extensions.end(); ++it) {
- disabled_extensions_.Insert(*it);
+ registry_->AddDisabled(*it);
}
}
private:
- ExtensionSet extensions_;
- ExtensionSet disabled_extensions_;
+ ExtensionRegistry* registry_;
};
class ServiceForDownloadTests : public MockService {
} else {
service.CreateTestExtensions(1, 1, &extensions, &update_url,
Manifest::INTERNAL);
- service.set_extensions(extensions);
+ service.set_extensions(extensions, ExtensionList());
}
// Set up and start the updater.
Mock::VerifyAndClearExpectations(&delegate);
}
- void TestSingleExtensionDownloading(bool pending, bool retry) {
+ void TestSingleExtensionDownloading(bool pending, bool retry, bool fail) {
net::TestURLFetcherFactory factory;
net::TestURLFetcher* fetcher = NULL;
scoped_ptr<ServiceForDownloadTests> service(
kUpdateFrequencySecs,
NULL);
updater.Start();
+ MockExtensionDownloaderDelegate delegate;
+ delegate.DelegateTo(&updater);
ResetDownloader(
&updater,
- new ExtensionDownloader(&updater, service->request_context()));
+ new ExtensionDownloader(&delegate, service->request_context()));
updater.downloader_->extensions_queue_.set_backoff_policy(
&kNoBackoffPolicy);
fetcher->set_url(test_url);
fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseFilePath(extension_file_path);
+ if (fail) {
+ fetcher->set_response_code(404);
+ EXPECT_CALL(delegate, OnExtensionDownloadFailed(id, _, _, requests));
+ } else {
+ fetcher->set_response_code(200);
+ fetcher->SetResponseFilePath(extension_file_path);
+ EXPECT_CALL(delegate, OnExtensionDownloadFinished(
+ id, _, _, _, version.GetString(), _, requests));
+ }
fetcher->delegate()->OnURLFetchComplete(fetcher);
RunUntilIdle();
- // Expect that ExtensionUpdater asked the mock extensions service to install
- // a file with the test data for the right id.
- 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);
+ if (fail) {
+ // Don't expect any extension to have been installed.
+ EXPECT_TRUE(service->extension_id().empty());
+ } else {
+ // Expect that ExtensionUpdater asked the mock extensions service to
+ // install a file with the test data for the right id.
+ 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) {
+ 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);
+ updater.Start();
+ ResetDownloader(
+ &updater,
+ new ExtensionDownloader(&updater, service->request_context()));
+ updater.downloader_->extensions_queue_.set_backoff_policy(
+ &kNoBackoffPolicy);
+
+ GURL test_url(use_https ? "https://localhost/extension.crx" :
+ "http://localhost/extension.crx");
+
+ std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ std::string hash;
+ Version version("0.0.1");
+ std::set<int> requests;
+ requests.insert(0);
+ scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch(
+ new ExtensionDownloader::ExtensionFetch(
+ id, test_url, hash, version.GetString(), requests));
+ updater.downloader_->FetchUpdatedExtension(fetch.Pass());
+
+ fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
+ EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
+
+ // Fake a 403 response.
+ fetcher->set_url(test_url);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(403);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+
+ // Verify that the fetcher has been switched to protected download mode
+ // so that cookies would be sent with the next request (https only).
+ fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
+ EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
+ if (use_https) {
+ EXPECT_TRUE(
+ fetcher->GetLoadFlags() == kExpectedLoadFlagsForProtectedDownload);
+ } else {
+ EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
+ }
+
+ // 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
+ base::FilePath extension_file_path(FILE_PATH_LITERAL("/whatever"));
+ fetcher->set_url(test_url);
+ fetcher->set_status(net::URLRequestStatus());
+ fetcher->set_response_code(200);
+ fetcher->SetResponseFilePath(extension_file_path);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ RunUntilIdle();
+
+ // Verify installation would proceed as normal.
+ 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);
+ }
}
// Two extensions are updated. If |updates_start_running| is true, the
service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(),
Manifest::INTERNAL);
EXPECT_EQ(2u, tmp.size());
- service.set_extensions(tmp);
+ service.set_extensions(tmp, ExtensionList());
ExtensionPrefs* prefs = service.extension_prefs();
const std::string& id = tmp[0]->id();
ExtensionList tmp;
service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(),
Manifest::INTERNAL);
- service.set_extensions(tmp);
+ service.set_extensions(tmp, ExtensionList());
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
}
TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloading) {
- TestSingleExtensionDownloading(false, false);
+ TestSingleExtensionDownloading(false, false, false);
}
TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingPending) {
- TestSingleExtensionDownloading(true, false);
+ TestSingleExtensionDownloading(true, false, false);
}
TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingWithRetry) {
- TestSingleExtensionDownloading(false, true);
+ TestSingleExtensionDownloading(false, true, false);
}
TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingPendingWithRetry) {
- TestSingleExtensionDownloading(true, true);
+ TestSingleExtensionDownloading(true, true, false);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailure) {
+ TestSingleExtensionDownloading(false, false, true);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailureWithRetry) {
+ TestSingleExtensionDownloading(false, true, true);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailurePending) {
+ TestSingleExtensionDownloading(true, false, true);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloading) {
+ TestSingleProtectedExtensionDownloading(true, false);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloadingFailure) {
+ TestSingleProtectedExtensionDownloading(true, true);
+}
+
+TEST_F(ExtensionUpdaterTest, TestSingleProtectedExtensionDownloadingNoHTTPS) {
+ TestSingleProtectedExtensionDownloading(false, false);
}
TEST_F(ExtensionUpdaterTest, TestMultipleExtensionDownloadingUpdatesFail) {
EXPECT_CALL(delegate, GetUpdateUrlData(updateable_id)).WillOnce(Return(""));
EXPECT_CALL(delegate, GetPingDataForExtension(updateable_id, _));
- service.set_extensions(extensions);
+ service.set_extensions(extensions, ExtensionList());
ExtensionUpdater::CheckParams params;
updater.Start();
updater.CheckNow(params);
EXPECT_CALL(delegate, GetUpdateUrlData(disabled_id)).WillOnce(Return(""));
EXPECT_CALL(delegate, GetPingDataForExtension(disabled_id, _));
- service.set_extensions(enabled_extensions);
- service.set_disabled_extensions(disabled_extensions);
+ service.set_extensions(enabled_extensions, disabled_extensions);
ExtensionUpdater::CheckParams params;
updater.Start();
updater.CheckNow(params);