summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authorasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 00:19:31 +0000
committerasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 00:19:31 +0000
commitf4ea11288982f7b94ad7a7780cf0aa1a08e29509 (patch)
treeffb3e5ef8aa56511216b67cecc03f6ddc44d0e40 /chrome/browser/extensions
parenta6d953ed61489bec9075f7441df3c2d559946de1 (diff)
downloadchromium_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.cc75
-rw-r--r--chrome/browser/extensions/autoupdate_interceptor.h42
-rw-r--r--chrome/browser/extensions/crx_installer.cc4
-rw-r--r--chrome/browser/extensions/extension_browsertest.cc25
-rw-r--r--chrome/browser/extensions/extension_browsertest.h9
-rw-r--r--chrome/browser/extensions/extension_browsertests_misc.cc51
-rw-r--r--chrome/browser/extensions/extension_updater.cc10
-rw-r--r--chrome/browser/extensions/extension_updater.h6
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);
};