diff options
author | asargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 00:19:31 +0000 |
---|---|---|
committer | asargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 00:19:31 +0000 |
commit | f4ea11288982f7b94ad7a7780cf0aa1a08e29509 (patch) | |
tree | ffb3e5ef8aa56511216b67cecc03f6ddc44d0e40 /chrome/browser/extensions | |
parent | a6d953ed61489bec9075f7441df3c2d559946de1 (diff) | |
download | chromium_src-f4ea11288982f7b94ad7a7780cf0aa1a08e29509.zip chromium_src-f4ea11288982f7b94ad7a7780cf0aa1a08e29509.tar.gz chromium_src-f4ea11288982f7b94ad7a7780cf0aa1a08e29509.tar.bz2 |
Add a browser test for extensions autoupdate.
BUG=17826,19403
TEST=none
Review URL: http://codereview.chromium.org/270019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28923 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/autoupdate_interceptor.cc | 75 | ||||
-rw-r--r-- | chrome/browser/extensions/autoupdate_interceptor.h | 42 | ||||
-rw-r--r-- | chrome/browser/extensions/crx_installer.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_browsertest.cc | 25 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_browsertest.h | 9 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_browsertests_misc.cc | 51 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_updater.cc | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_updater.h | 6 |
8 files changed, 216 insertions, 6 deletions
diff --git a/chrome/browser/extensions/autoupdate_interceptor.cc b/chrome/browser/extensions/autoupdate_interceptor.cc new file mode 100644 index 0000000..b908133 --- /dev/null +++ b/chrome/browser/extensions/autoupdate_interceptor.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2009 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/autoupdate_interceptor.h" + +#include "base/file_util.h" +#include "chrome/browser/chrome_thread.h" +#include "net/url_request/url_request_test_job.h" +#include "testing/gtest/include/gtest/gtest.h" + +// This is a specialized version of URLRequestTestJob that lets us specify +// response data and make sure the response code is 200, which the autoupdate +// code relies on. +class AutoUpdateTestRequestJob : public URLRequestTestJob { + public: + AutoUpdateTestRequestJob(URLRequest* request, + const std::string& response_data) : URLRequestTestJob( + request, URLRequestTestJob::test_headers(), response_data, true) {} + virtual int GetResponseCode() const { return 200; } +}; + + +AutoUpdateInterceptor::AutoUpdateInterceptor() { + URLRequest::RegisterRequestInterceptor(this); +} + +AutoUpdateInterceptor::~AutoUpdateInterceptor() { + URLRequest::UnregisterRequestInterceptor(this); +} + + +URLRequestJob* AutoUpdateInterceptor::MaybeIntercept(URLRequest* request) { + EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); + if (request->url().scheme() != "http" || + request->url().host() != "localhost") { + return NULL; + } + + // Search for this request's url, ignoring any query parameters. + GURL url = request->url(); + if (url.has_query()) { + GURL::Replacements replacements; + replacements.ClearQuery(); + url = url.ReplaceComponents(replacements); + } + std::map<GURL, FilePath>::iterator i = responses_.find(url); + if (i == responses_.end()) { + return NULL; + } + std::string contents; + EXPECT_TRUE(file_util::ReadFileToString(i->second, &contents)); + + return new AutoUpdateTestRequestJob(request, contents); +} + + +void AutoUpdateInterceptor::SetResponse(const std::string url, + const FilePath& path) { + EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); + GURL gurl(url); + EXPECT_EQ("http", gurl.scheme()); + EXPECT_EQ("localhost", gurl.host()); + EXPECT_TRUE(file_util::PathExists(path)); + responses_[gurl] = path; +} + + +void AutoUpdateInterceptor::SetResponseOnIOThread(const std::string url, + const FilePath& path) { + MessageLoop* io_loop = ChromeThread::GetMessageLoop(ChromeThread::IO); + io_loop->PostTask(FROM_HERE, + NewRunnableMethod(this, &AutoUpdateInterceptor::SetResponse, + url, path)); +} diff --git a/chrome/browser/extensions/autoupdate_interceptor.h b/chrome/browser/extensions/autoupdate_interceptor.h new file mode 100644 index 0000000..4a4284a --- /dev/null +++ b/chrome/browser/extensions/autoupdate_interceptor.h @@ -0,0 +1,42 @@ +// Copyright (c) 2009 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_AUTOUPDATE_INTERCEPTOR_H_ +#define CHROME_BROWSER_EXTENSIONS_AUTOUPDATE_INTERCEPTOR_H_ + +#include <map> +#include <string> + +#include "googleurl/src/gurl.h" +#include "net/url_request/url_request.h" + +// This url request interceptor lets us respond to localhost http request urls +// with the contents of files on disk for use in tests. +class AutoUpdateInterceptor + : public URLRequest::Interceptor, + public base::RefCountedThreadSafe<AutoUpdateInterceptor> { + public: + AutoUpdateInterceptor(); + virtual ~AutoUpdateInterceptor(); + + // When computing matches, this ignores query parameters (since the autoupdate + // fetch code appends a bunch of them to manifest fetches). + virtual URLRequestJob* MaybeIntercept(URLRequest* request); + + // When requests for |url| arrive, respond with the contents of |path|. The + // hostname of |url| must be "localhost" to avoid DNS lookups, and the scheme + // must be "http" so MaybeIntercept can ignore "chrome" and other schemes. + // Also, the match for |url| will ignore any query parameters. + void SetResponse(const std::string url, const FilePath& path); + + // A helper function to call SetResponse on the I/O thread. + void SetResponseOnIOThread(const std::string url, const FilePath& path); + + private: + std::map<GURL, FilePath> responses_; + + DISALLOW_COPY_AND_ASSIGN(AutoUpdateInterceptor); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_AUTOUPDATE_INTERCEPTOR_H_ diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index ac7ea52..7bb69d0 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -261,9 +261,9 @@ void CrxInstaller::ReportFailureFromUIThread(const std::string& error) { DCHECK(MessageLoop::current() == ui_loop_); NotificationService* service = NotificationService::current(); - service->Notify(NotificationType::NO_THEME_DETECTED, + service->Notify(NotificationType::EXTENSION_INSTALL_ERROR, Source<CrxInstaller>(this), - NotificationService::NoDetails()); + Details<const std::string>(&error)); // This isn't really necessary, it is only used because unit tests expect to // see errors get reported via this interface. diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index b7acc21..22e7829 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -194,6 +194,20 @@ bool ExtensionBrowserTest::WaitForExtensionHostsToLoad() { return true; } +bool ExtensionBrowserTest::WaitForExtensionInstall() { + int before = extension_installs_observed_; + ui_test_utils::RegisterAndWait(NotificationType::EXTENSION_INSTALLED, this, + kTimeoutMs); + return extension_installs_observed_ == (before + 1); +} + +bool ExtensionBrowserTest::WaitForExtensionInstallError() { + int before = extension_installs_observed_; + ui_test_utils::RegisterAndWait(NotificationType::EXTENSION_INSTALL_ERROR, + this, kTimeoutMs); + return extension_installs_observed_ == before; +} + void ExtensionBrowserTest::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { @@ -214,6 +228,17 @@ void ExtensionBrowserTest::Observe(NotificationType type, MessageLoopForUI::current()->Quit(); break; + case NotificationType::EXTENSION_INSTALLED: + std::cout << "Got EXTENSION_INSTALLED notification.\n"; + ++extension_installs_observed_; + MessageLoopForUI::current()->Quit(); + break; + + case NotificationType::EXTENSION_INSTALL_ERROR: + std::cout << "Got EXTENSION_INSTALL_ERROR notification.\n"; + MessageLoopForUI::current()->Quit(); + break; + default: NOTREACHED(); break; diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index 5e2b882..938ffe1 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h @@ -48,6 +48,14 @@ class ExtensionBrowserTest // Wait for the number of visible page actions to change to |count|. bool WaitForPageActionVisibilityChangeTo(int count); + // Waits until an extension is installed and loaded. Returns true if an + // install happened before timeout. + bool WaitForExtensionInstall(); + + // Wait for an extension install error to be raised. Returns true if an + // error was raised. + bool WaitForExtensionInstallError(); + // NotificationObserver virtual void Observe(NotificationType type, const NotificationSource& source, @@ -57,6 +65,7 @@ class ExtensionBrowserTest bool installed_; FilePath test_data_dir_; std::string last_loaded_extension_id_; + int extension_installs_observed_; private: bool InstallOrUpdateExtension(const std::string& id, const FilePath& path, diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc index bab50d1..ff4069d 100644 --- a/chrome/browser/extensions/extension_browsertests_misc.cc +++ b/chrome/browser/extensions/extension_browsertests_misc.cc @@ -6,10 +6,12 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/extensions/autoupdate_interceptor.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -714,3 +716,52 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PluginLoadUnload) { EXPECT_FALSE(result); } #endif + +// Tests extension autoupdate. +IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, AutoUpdate) { + FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); + // Note: This interceptor gets requests on the IO thread. + scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor()); + URLFetcher::enable_interception_for_tests(true); + + interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest", + basedir.AppendASCII("manifest_v2.xml")); + interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx", + basedir.AppendASCII("v2.crx")); + + // Install version 1 of the extension. + ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v1.crx"), 1)); + ExtensionsService* service = browser()->profile()->GetExtensionsService(); + const ExtensionList* extensions = service->extensions(); + ASSERT_EQ(1u, extensions->size()); + ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extensions->at(0)->id()); + ASSERT_EQ("1.0", extensions->at(0)->VersionString()); + + // We don't want autoupdate blacklist checks. + service->updater()->set_blacklist_checks_enabled(false); + + // Run autoupdate and make sure version 2 of the extension was installed. + service->updater()->CheckNow(); + ASSERT_TRUE(WaitForExtensionInstall()); + extensions = service->extensions(); + ASSERT_EQ(1u, extensions->size()); + ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extensions->at(0)->id()); + ASSERT_EQ("2.0", extensions->at(0)->VersionString()); + + // Now try doing an update to version 3, which has been incorrectly + // signed. This should fail. + interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest", + basedir.AppendASCII("manifest_v3.xml")); + interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v3.crx", + basedir.AppendASCII("v3.crx")); + + service->updater()->CheckNow(); + ASSERT_TRUE(WaitForExtensionInstallError()); + + // Make sure the extension state is the same as before. + extensions = service->extensions(); + ASSERT_EQ(1u, extensions->size()); + ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extensions->at(0)->id()); + ASSERT_EQ("2.0", extensions->at(0)->VersionString()); +} + diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc index cbd9061..d5db3e6 100644 --- a/chrome/browser/extensions/extension_updater.cc +++ b/chrome/browser/extensions/extension_updater.cc @@ -115,7 +115,8 @@ ExtensionUpdater::ExtensionUpdater(ExtensionUpdateService* service, : service_(service), frequency_seconds_(frequency_seconds), file_io_loop_(file_io_loop), io_loop_(io_loop), prefs_(prefs), file_handler_(new ExtensionUpdaterFileHandler(MessageLoop::current(), - file_io_loop_)) { + file_io_loop_)), + blacklist_checks_enabled_(true) { Init(); } @@ -483,9 +484,10 @@ void ExtensionUpdater::CheckNow() { // Generate a set of update urls for loaded extensions. std::set<GURL> urls; - // We always check blacklist update url - urls.insert(GetBlacklistUpdateUrl( - prefs_->GetString(kExtensionBlacklistUpdateVersion))); + if (blacklist_checks_enabled_) { + urls.insert(GetBlacklistUpdateUrl( + prefs_->GetString(kExtensionBlacklistUpdateVersion))); + } const ExtensionList* extensions = service_->extensions(); for (ExtensionList::const_iterator iter = extensions->begin(); diff --git a/chrome/browser/extensions/extension_updater.h b/chrome/browser/extensions/extension_updater.h index 48808ed..252bfeb 100644 --- a/chrome/browser/extensions/extension_updater.h +++ b/chrome/browser/extensions/extension_updater.h @@ -62,6 +62,11 @@ class ExtensionUpdater // scheduled check. void CheckNow(); + // Set blacklist checks on or off. + void set_blacklist_checks_enabled(bool enabled) { + blacklist_checks_enabled_ = enabled; + } + private: friend class ExtensionUpdaterTest; friend class ExtensionUpdaterFileHandler; @@ -182,6 +187,7 @@ class ExtensionUpdater PrefService* prefs_; scoped_refptr<ExtensionUpdaterFileHandler> file_handler_; + bool blacklist_checks_enabled_; DISALLOW_COPY_AND_ASSIGN(ExtensionUpdater); }; |