blob: c253848f96e734853bcc4f6383e1e21f357b2d3e [file] [log] [blame]
[email protected]6014d672008-12-05 00:38:251// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f0397fa2008-12-11 17:59:585#include <algorithm>
[email protected]6014d672008-12-05 00:38:256#include <vector>
7
8#include "base/file_path.h"
9#include "base/file_util.h"
[email protected]8d6d9ff2009-02-20 08:14:3910#include "base/json_reader.h"
[email protected]6014d672008-12-05 00:38:2511#include "base/message_loop.h"
12#include "base/path_service.h"
13#include "base/string_util.h"
[email protected]f0397fa2008-12-11 17:59:5814#include "chrome/browser/extensions/extension.h"
[email protected]bb28e062009-02-27 17:19:1815#include "chrome/browser/extensions/extension_error_reporter.h"
[email protected]6014d672008-12-05 00:38:2516#include "chrome/browser/extensions/extensions_service.h"
17#include "chrome/common/chrome_paths.h"
18#include "chrome/common/json_value_serializer.h"
19#include "testing/gtest/include/gtest/gtest.h"
[email protected]f66c110c2008-12-05 20:26:2920#include "testing/platform_test.h"
[email protected]6014d672008-12-05 00:38:2521
[email protected]f0397fa2008-12-11 17:59:5822namespace {
23
24struct ExtensionsOrder {
25 bool operator()(const Extension* a, const Extension* b) {
26 return a->name() < b->name();
27 }
28};
29
[email protected]bb28e062009-02-27 17:19:1830static std::vector<std::string> GetErrors() {
31 const std::vector<std::string>* errors =
32 ExtensionErrorReporter::GetInstance()->GetErrors();
33 std::vector<std::string> ret_val;
34
35 for (std::vector<std::string>::const_iterator iter = errors->begin();
36 iter != errors->end(); ++iter) {
37 if (iter->find(".svn") == std::string::npos) {
38 ret_val.push_back(*iter);
39 }
40 }
41
42 // The tests rely on the errors being in a certain order, which can vary
43 // depending on how filesystem iteration works.
44 std::stable_sort(ret_val.begin(), ret_val.end());
45
46 return ret_val;
47}
48
[email protected]f0397fa2008-12-11 17:59:5849} // namespace
[email protected]6014d672008-12-05 00:38:2550
51// A mock implementation of ExtensionsServiceFrontendInterface for testing the
52// backend.
53class ExtensionsServiceTestFrontend
54 : public ExtensionsServiceFrontendInterface {
55 public:
[email protected]cc655912009-01-29 23:19:1956
[email protected]3acbd422008-12-08 18:25:0057 ~ExtensionsServiceTestFrontend() {
58 for (ExtensionList::iterator iter = extensions_.begin();
59 iter != extensions_.end(); ++iter) {
60 delete *iter;
61 }
62 }
63
[email protected]6014d672008-12-05 00:38:2564 ExtensionList* extensions() {
[email protected]3acbd422008-12-08 18:25:0065 return &extensions_;
[email protected]6014d672008-12-05 00:38:2566 }
67
[email protected]cc655912009-01-29 23:19:1968 std::vector<FilePath>* installed() {
69 return &installed_;
70 }
71
[email protected]6014d672008-12-05 00:38:2572 // ExtensionsServiceFrontendInterface
73 virtual MessageLoop* GetMessageLoop() {
74 return &message_loop_;
75 }
76
[email protected]3cf4f0992009-02-03 23:00:3077 virtual void InstallExtension(const FilePath& extension_path) {
78 }
79
80 virtual void LoadExtension(const FilePath& extension_path) {
81 }
82
[email protected]cc5da332009-03-04 08:02:5183 virtual void OnExtensionsLoaded(ExtensionList* new_extensions) {
[email protected]08816d0d2008-12-08 18:43:5384 extensions_.insert(extensions_.end(), new_extensions->begin(),
85 new_extensions->end());
86 delete new_extensions;
[email protected]bb28e062009-02-27 17:19:1887 // In the tests we rely on extensions being in particular order, which is
88 // not always the case (and is not guaranteed by used APIs).
[email protected]f0397fa2008-12-11 17:59:5889 std::stable_sort(extensions_.begin(), extensions_.end(), ExtensionsOrder());
[email protected]cc655912009-01-29 23:19:1990 }
91
[email protected]b0beaa662009-02-26 00:04:1592 virtual void OnExtensionInstalled(FilePath path, bool is_update) {
[email protected]cc655912009-01-29 23:19:1993 installed_.push_back(path);
94 }
95
96 void TestInstallExtension(const FilePath& path,
97 ExtensionsServiceBackend* backend,
98 bool should_succeed) {
99 ASSERT_TRUE(file_util::PathExists(path));
[email protected]cc5da332009-03-04 08:02:51100 backend->InstallExtension(path,
[email protected]b0beaa662009-02-26 00:04:15101 scoped_refptr<ExtensionsServiceFrontendInterface>(this));
[email protected]cc655912009-01-29 23:19:19102 message_loop_.RunAllPending();
[email protected]bb28e062009-02-27 17:19:18103 std::vector<std::string> errors = GetErrors();
[email protected]cc655912009-01-29 23:19:19104 if (should_succeed) {
[email protected]37eeb5a2009-02-26 23:36:17105 EXPECT_EQ(1u, installed_.size()) << path.value();
[email protected]bb28e062009-02-27 17:19:18106 EXPECT_EQ(0u, errors.size()) << path.value();
107 for (std::vector<std::string>::iterator err = errors.begin();
108 err != errors.end(); ++err) {
[email protected]37eeb5a2009-02-26 23:36:17109 LOG(ERROR) << *err;
110 }
[email protected]cc655912009-01-29 23:19:19111 } else {
[email protected]37eeb5a2009-02-26 23:36:17112 EXPECT_EQ(0u, installed_.size()) << path.value();
[email protected]bb28e062009-02-27 17:19:18113 EXPECT_EQ(1u, errors.size()) << path.value();
[email protected]cc655912009-01-29 23:19:19114 }
[email protected]bb28e062009-02-27 17:19:18115
[email protected]cc655912009-01-29 23:19:19116 installed_.clear();
[email protected]bb28e062009-02-27 17:19:18117 ExtensionErrorReporter::GetInstance()->ClearErrors();
[email protected]cc655912009-01-29 23:19:19118 }
119
120
[email protected]6014d672008-12-05 00:38:25121 private:
122 MessageLoop message_loop_;
[email protected]3acbd422008-12-08 18:25:00123 ExtensionList extensions_;
[email protected]cc655912009-01-29 23:19:19124 std::vector<FilePath> installed_;
[email protected]6014d672008-12-05 00:38:25125};
126
[email protected]f66c110c2008-12-05 20:26:29127// make the test a PlatformTest to setup autorelease pools properly on mac
[email protected]bb28e062009-02-27 17:19:18128class ExtensionsServiceTest : public testing::Test {
129 public:
130 static void SetUpTestCase() {
131 ExtensionErrorReporter::Init(false); // no noisy errors
132 }
133
134 virtual void SetUp() {
135 ExtensionErrorReporter::GetInstance()->ClearErrors();
136 }
137};
[email protected]6014d672008-12-05 00:38:25138
[email protected]54cb3c92009-02-17 22:30:21139// Test loading good extensions from the profile directory.
140TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) {
[email protected]cc655912009-01-29 23:19:19141 FilePath extensions_path;
142 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
143 extensions_path = extensions_path.AppendASCII("extensions");
[email protected]54cb3c92009-02-17 22:30:21144 extensions_path = extensions_path.AppendASCII("good");
[email protected]6014d672008-12-05 00:38:25145
[email protected]cc5da332009-03-04 08:02:51146 scoped_refptr<ExtensionsServiceBackend> backend(
147 new ExtensionsServiceBackend(extensions_path));
[email protected]6014d672008-12-05 00:38:25148 scoped_refptr<ExtensionsServiceTestFrontend> frontend(
149 new ExtensionsServiceTestFrontend);
150
151 std::vector<Extension*> extensions;
[email protected]cc5da332009-03-04 08:02:51152 backend->LoadExtensionsFromInstallDirectory(
[email protected]b0beaa662009-02-26 00:04:15153 scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get()));
[email protected]6014d672008-12-05 00:38:25154 frontend->GetMessageLoop()->RunAllPending();
155
[email protected]bb28e062009-02-27 17:19:18156 std::vector<std::string> errors = GetErrors();
157 for (std::vector<std::string>::iterator err = errors.begin();
158 err != errors.end(); ++err) {
[email protected]37eeb5a2009-02-26 23:36:17159 LOG(ERROR) << *err;
160 }
[email protected]18a12352009-01-31 01:33:28161 ASSERT_EQ(3u, frontend->extensions()->size());
[email protected]6014d672008-12-05 00:38:25162
[email protected]e92475f2009-03-03 00:15:59163 EXPECT_EQ(std::string("00123456789abcdef0123456789abcdef0123456"),
[email protected]6014d672008-12-05 00:38:25164 frontend->extensions()->at(0)->id());
[email protected]e1cec06c2008-12-18 01:22:23165 EXPECT_EQ(std::string("My extension 1"),
[email protected]6014d672008-12-05 00:38:25166 frontend->extensions()->at(0)->name());
[email protected]e1cec06c2008-12-18 01:22:23167 EXPECT_EQ(std::string("The first extension that I made."),
[email protected]6014d672008-12-05 00:38:25168 frontend->extensions()->at(0)->description());
[email protected]eab9b452009-01-23 20:48:59169
170 Extension* extension = frontend->extensions()->at(0);
[email protected]34aa8dc2009-02-19 07:03:05171 const UserScriptList& scripts = extension->content_scripts();
[email protected]e66de892009-03-20 20:38:43172 ASSERT_EQ(2u, scripts.size());
[email protected]d2a69e22009-02-05 22:51:54173 EXPECT_EQ(2u, scripts[0].url_patterns().size());
174 EXPECT_EQ("http://*.google.com/*",
175 scripts[0].url_patterns()[0].GetAsString());
176 EXPECT_EQ("https://*.google.com/*",
177 scripts[0].url_patterns()[1].GetAsString());
[email protected]e66de892009-03-20 20:38:43178 EXPECT_EQ(2u, scripts[0].js_scripts().size());
[email protected]cc655912009-01-29 23:19:19179 EXPECT_EQ(extension->path().AppendASCII("script1.js").value(),
[email protected]3cfbd0e2009-03-18 21:26:24180 scripts[0].js_scripts()[0].path().value());
[email protected]cc655912009-01-29 23:19:19181 EXPECT_EQ(extension->path().AppendASCII("script2.js").value(),
[email protected]e66de892009-03-20 20:38:43182 scripts[0].js_scripts()[1].path().value());
183 EXPECT_EQ(1u, scripts[1].url_patterns().size());
184 EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString());
[email protected]829f8e22009-03-09 01:47:37185 EXPECT_EQ(extension->path().AppendASCII("js_files").AppendASCII("script3.js")
[email protected]e66de892009-03-20 20:38:43186 .value(), scripts[1].js_scripts()[0].path().value());
[email protected]6014d672008-12-05 00:38:25187
[email protected]e92475f2009-03-03 00:15:59188 EXPECT_EQ(std::string("10123456789abcdef0123456789abcdef0123456"),
[email protected]6014d672008-12-05 00:38:25189 frontend->extensions()->at(1)->id());
[email protected]e1cec06c2008-12-18 01:22:23190 EXPECT_EQ(std::string("My extension 2"),
[email protected]6014d672008-12-05 00:38:25191 frontend->extensions()->at(1)->name());
[email protected]e1cec06c2008-12-18 01:22:23192 EXPECT_EQ(std::string(""),
[email protected]6014d672008-12-05 00:38:25193 frontend->extensions()->at(1)->description());
[email protected]367230c52009-02-21 01:44:30194 EXPECT_EQ(frontend->extensions()->at(1)->path().AppendASCII("npapi").value(),
195 frontend->extensions()->at(1)->plugins_dir().value());
[email protected]34aa8dc2009-02-19 07:03:05196 ASSERT_EQ(0u, frontend->extensions()->at(1)->content_scripts().size());
[email protected]18a12352009-01-31 01:33:28197
[email protected]e92475f2009-03-03 00:15:59198 EXPECT_EQ(std::string("20123456789abcdef0123456789abcdef0123456"),
[email protected]18a12352009-01-31 01:33:28199 frontend->extensions()->at(2)->id());
200 EXPECT_EQ(std::string("My extension 3"),
201 frontend->extensions()->at(2)->name());
202 EXPECT_EQ(std::string(""),
203 frontend->extensions()->at(2)->description());
[email protected]34aa8dc2009-02-19 07:03:05204 ASSERT_EQ(0u, frontend->extensions()->at(2)->content_scripts().size());
[email protected]6014d672008-12-05 00:38:25205};
[email protected]cc655912009-01-29 23:19:19206
[email protected]54cb3c92009-02-17 22:30:21207// Test loading bad extensions from the profile directory.
208TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectoryFail) {
209 FilePath extensions_path;
210 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
211 extensions_path = extensions_path.AppendASCII("extensions");
212 extensions_path = extensions_path.AppendASCII("bad");
213
[email protected]cc5da332009-03-04 08:02:51214 scoped_refptr<ExtensionsServiceBackend> backend(
215 new ExtensionsServiceBackend(extensions_path));
[email protected]54cb3c92009-02-17 22:30:21216 scoped_refptr<ExtensionsServiceTestFrontend> frontend(
217 new ExtensionsServiceTestFrontend);
218
219 std::vector<Extension*> extensions;
[email protected]cc5da332009-03-04 08:02:51220 backend->LoadExtensionsFromInstallDirectory(
[email protected]b0beaa662009-02-26 00:04:15221 scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get()));
[email protected]54cb3c92009-02-17 22:30:21222 frontend->GetMessageLoop()->RunAllPending();
223
[email protected]bb28e062009-02-27 17:19:18224 EXPECT_EQ(4u, GetErrors().size());
[email protected]8d6d9ff2009-02-20 08:14:39225 EXPECT_EQ(0u, frontend->extensions()->size());
226
[email protected]bb28e062009-02-27 17:19:18227 EXPECT_TRUE(MatchPattern(GetErrors()[0],
[email protected]8d6d9ff2009-02-20 08:14:39228 std::string("Could not load extension from '*'. * ") +
[email protected]bb28e062009-02-27 17:19:18229 JSONReader::kBadRootElementType)) << GetErrors()[0];
[email protected]8d6d9ff2009-02-20 08:14:39230
[email protected]bb28e062009-02-27 17:19:18231 EXPECT_TRUE(MatchPattern(GetErrors()[1],
[email protected]8d6d9ff2009-02-20 08:14:39232 std::string("Could not load extension from '*'. ") +
[email protected]3cfbd0e2009-03-18 21:26:24233 Extension::kMissingFileError)) << GetErrors()[1];
[email protected]8d6d9ff2009-02-20 08:14:39234
[email protected]bb28e062009-02-27 17:19:18235 EXPECT_TRUE(MatchPattern(GetErrors()[2],
[email protected]8d6d9ff2009-02-20 08:14:39236 std::string("Could not load extension from '*'. ") +
[email protected]bb28e062009-02-27 17:19:18237 Extension::kInvalidManifestError)) << GetErrors()[2];
[email protected]8d6d9ff2009-02-20 08:14:39238
[email protected]bb28e062009-02-27 17:19:18239 EXPECT_TRUE(MatchPattern(GetErrors()[3],
[email protected]37eeb5a2009-02-26 23:36:17240 "Could not load extension from '*'. Could not read '*' file.")) <<
[email protected]bb28e062009-02-27 17:19:18241 GetErrors()[3];
[email protected]54cb3c92009-02-17 22:30:21242};
243
[email protected]cc655912009-01-29 23:19:19244// Test installing extensions.
245TEST_F(ExtensionsServiceTest, InstallExtension) {
246 FilePath extensions_path;
247 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
248 extensions_path = extensions_path.AppendASCII("extensions");
249
[email protected]cc5da332009-03-04 08:02:51250 FilePath install_dir;
251 file_util::CreateNewTempDirectory(FILE_PATH_LITERAL("ext_test"),
252 &install_dir);
253 scoped_refptr<ExtensionsServiceBackend> backend(
254 new ExtensionsServiceBackend(install_dir));
[email protected]cc655912009-01-29 23:19:19255 scoped_refptr<ExtensionsServiceTestFrontend> frontend(
256 new ExtensionsServiceTestFrontend);
257
258 FilePath path = extensions_path.AppendASCII("good.crx");
259
260 // A simple extension that should install without error.
261 frontend->TestInstallExtension(path, backend, true);
262 // TODO(erikkay): verify the contents of the installed extension.
263
264 // Installing the same extension twice should fail.
265 frontend->TestInstallExtension(path, backend, false);
266
267 // 0-length extension file.
268 path = extensions_path.AppendASCII("not_an_extension.crx");
269 frontend->TestInstallExtension(path, backend, false);
270
271 // Bad magic number.
272 path = extensions_path.AppendASCII("bad_magic.crx");
273 frontend->TestInstallExtension(path, backend, false);
274
275 // Poorly formed JSON.
276 path = extensions_path.AppendASCII("bad_json.crx");
277 frontend->TestInstallExtension(path, backend, false);
278
279 // Incorrect zip hash.
280 path = extensions_path.AppendASCII("bad_hash.crx");
281 frontend->TestInstallExtension(path, backend, false);
282
283 // TODO(erikkay): add more tests for many of the failure cases.
284 // TODO(erikkay): add tests for upgrade cases.
285}
286
[email protected]3cf4f0992009-02-03 23:00:30287TEST_F(ExtensionsServiceTest, LoadExtension) {
288 FilePath extensions_path;
289 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
290 extensions_path = extensions_path.AppendASCII("extensions");
291
[email protected]cc5da332009-03-04 08:02:51292 scoped_refptr<ExtensionsServiceBackend> backend(
293 new ExtensionsServiceBackend(extensions_path));
[email protected]3cf4f0992009-02-03 23:00:30294 scoped_refptr<ExtensionsServiceTestFrontend> frontend(
295 new ExtensionsServiceTestFrontend);
296
[email protected]54cb3c92009-02-17 22:30:21297 FilePath ext1 = extensions_path.AppendASCII("good").AppendASCII("extension1")
298 .AppendASCII("1");
[email protected]b0beaa662009-02-26 00:04:15299 backend->LoadSingleExtension(ext1,
300 scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get()));
[email protected]3cf4f0992009-02-03 23:00:30301 frontend->GetMessageLoop()->RunAllPending();
[email protected]bb28e062009-02-27 17:19:18302 EXPECT_EQ(0u, GetErrors().size());
[email protected]3cf4f0992009-02-03 23:00:30303 ASSERT_EQ(1u, frontend->extensions()->size());
304
[email protected]54cb3c92009-02-17 22:30:21305 FilePath no_manifest = extensions_path.AppendASCII("bad")
306 .AppendASCII("no_manifest").AppendASCII("1");
[email protected]b0beaa662009-02-26 00:04:15307 backend->LoadSingleExtension(no_manifest,
308 scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get()));
[email protected]3cf4f0992009-02-03 23:00:30309 frontend->GetMessageLoop()->RunAllPending();
[email protected]bb28e062009-02-27 17:19:18310 EXPECT_EQ(1u, GetErrors().size());
[email protected]3cf4f0992009-02-03 23:00:30311 ASSERT_EQ(1u, frontend->extensions()->size());
312}