blob: 5d7aac75778ef124bc259a22dad40782dbbb877d [file] [log] [blame]
[email protected]4dad9ad82009-11-25 20:47:521// Copyright (c) 2009 The Chromium Authors. All rights reserved.
[email protected]6014d672008-12-05 00:38:252// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]bf73f0b2010-02-10 19:26:595#include "chrome/browser/extensions/extensions_service_unittest.h"
6
[email protected]f0397fa2008-12-11 17:59:587#include <algorithm>
[email protected]6014d672008-12-05 00:38:258#include <vector>
9
[email protected]24b538a2010-02-27 01:22:4410#include "base/basictypes.h"
[email protected]36a784c2009-06-23 06:21:0811#include "base/command_line.h"
[email protected]6014d672008-12-05 00:38:2512#include "base/file_util.h"
[email protected]93d49d72009-10-23 20:00:2013#include "base/json/json_reader.h"
[email protected]6014d672008-12-05 00:38:2514#include "base/message_loop.h"
15#include "base/path_service.h"
[email protected]aa142702010-03-26 01:26:3316#include "base/scoped_ptr.h"
[email protected]24b538a2010-02-27 01:22:4417#include "base/string16.h"
[email protected]6014d672008-12-05 00:38:2518#include "base/string_util.h"
[email protected]24b538a2010-02-27 01:22:4419#include "base/task.h"
[email protected]aa142702010-03-26 01:26:3320#include "base/version.h"
[email protected]ea587b02010-05-21 15:01:3521#include "chrome/browser/chrome_thread.h"
[email protected]da0aa3b2009-12-06 21:41:0322#include "chrome/browser/extensions/crx_installer.h"
[email protected]a17f9462009-06-09 02:56:4123#include "chrome/browser/extensions/extension_creator.h"
[email protected]14a000d2010-04-29 21:44:2424#include "chrome/browser/extensions/extension_error_reporter.h"
[email protected]6014d672008-12-05 00:38:2525#include "chrome/browser/extensions/extensions_service.h"
[email protected]a1257b12009-06-12 02:51:3426#include "chrome/browser/extensions/external_extension_provider.h"
[email protected]27b985d2009-06-25 17:53:1527#include "chrome/browser/extensions/external_pref_extension_provider.h"
[email protected]d8b08c92010-06-07 13:13:2828#include "chrome/browser/pref_value_store.h"
[email protected]5b1a0e22009-05-26 19:00:5829#include "chrome/common/extensions/extension.h"
[email protected]cb691e82009-07-13 14:59:0130#include "chrome/common/extensions/extension_constants.h"
[email protected]942690b132010-05-11 06:42:1431#include "chrome/common/extensions/extension_resource.h"
[email protected]7197f4992009-03-23 05:05:4932#include "chrome/common/extensions/url_pattern.h"
[email protected]6014d672008-12-05 00:38:2533#include "chrome/common/chrome_paths.h"
[email protected]e2eb43112009-05-29 21:19:5434#include "chrome/common/chrome_switches.h"
[email protected]6014d672008-12-05 00:38:2535#include "chrome/common/json_value_serializer.h"
[email protected]894bb502009-05-21 22:39:5736#include "chrome/common/notification_registrar.h"
37#include "chrome/common/notification_service.h"
38#include "chrome/common/notification_type.h"
[email protected]36a784c2009-06-23 06:21:0839#include "chrome/common/pref_names.h"
[email protected]24b538a2010-02-27 01:22:4440#include "chrome/common/url_constants.h"
[email protected]894bb502009-05-21 22:39:5741#include "chrome/test/testing_profile.h"
[email protected]24b538a2010-02-27 01:22:4442#include "googleurl/src/gurl.h"
[email protected]6014d672008-12-05 00:38:2543#include "testing/gtest/include/gtest/gtest.h"
[email protected]f66c110c2008-12-05 20:26:2944#include "testing/platform_test.h"
[email protected]24b538a2010-02-27 01:22:4445#include "webkit/database/database_tracker.h"
46#include "webkit/database/database_util.h"
[email protected]c10da4b02010-03-25 14:38:3247#include "net/base/cookie_monster.h"
48#include "net/base/cookie_options.h"
[email protected]6014d672008-12-05 00:38:2549
[email protected]c6d474f82009-12-16 21:11:0650namespace keys = extension_manifest_keys;
51
[email protected]f0397fa2008-12-11 17:59:5852namespace {
53
[email protected]df4956e2009-06-10 16:53:4254// Extension ids used during testing.
[email protected]5a2721f62009-06-13 07:08:2055const char* const all_zero = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
56const char* const zero_n_one = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
57const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj";
58const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk";
59const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
60const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
[email protected]d7eaf572009-07-01 21:57:0061const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln";
[email protected]5a2721f62009-06-13 07:08:2062const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
63const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
[email protected]6d2e60bd2010-06-03 22:37:3964const char* const app_crx = "hnbefahlpjbkldcaldefcnonockppomb";
[email protected]df4956e2009-06-10 16:53:4265
[email protected]f0397fa2008-12-11 17:59:5866struct ExtensionsOrder {
67 bool operator()(const Extension* a, const Extension* b) {
68 return a->name() < b->name();
69 }
70};
71
[email protected]bb28e062009-02-27 17:19:1872static std::vector<std::string> GetErrors() {
73 const std::vector<std::string>* errors =
74 ExtensionErrorReporter::GetInstance()->GetErrors();
75 std::vector<std::string> ret_val;
76
77 for (std::vector<std::string>::const_iterator iter = errors->begin();
78 iter != errors->end(); ++iter) {
79 if (iter->find(".svn") == std::string::npos) {
80 ret_val.push_back(*iter);
81 }
82 }
83
84 // The tests rely on the errors being in a certain order, which can vary
85 // depending on how filesystem iteration works.
86 std::stable_sort(ret_val.begin(), ret_val.end());
87
88 return ret_val;
89}
90
[email protected]f0397fa2008-12-11 17:59:5891} // namespace
[email protected]6014d672008-12-05 00:38:2592
[email protected]a1257b12009-06-12 02:51:3493class MockExtensionProvider : public ExternalExtensionProvider {
94 public:
95 explicit MockExtensionProvider(Extension::Location location)
96 : location_(location) {}
97 virtual ~MockExtensionProvider() {}
98
99 void UpdateOrAddExtension(const std::string& id,
100 const std::string& version,
[email protected]f5ad7542009-07-24 17:38:59101 const FilePath& path) {
[email protected]a1257b12009-06-12 02:51:34102 extension_map_[id] = std::make_pair(version, path);
103 }
104
105 void RemoveExtension(const std::string& id) {
106 extension_map_.erase(id);
107 }
108
109 // ExternalExtensionProvider implementation:
110 virtual void VisitRegisteredExtension(
111 Visitor* visitor, const std::set<std::string>& ids_to_ignore) const {
112 for (DataMap::const_iterator i = extension_map_.begin();
113 i != extension_map_.end(); ++i) {
114 if (ids_to_ignore.find(i->first) != ids_to_ignore.end())
115 continue;
116 scoped_ptr<Version> version;
117 version.reset(Version::GetVersionFromString(i->second.first));
118
119 visitor->OnExternalExtensionFound(
[email protected]7577a5c52009-07-30 06:21:58120 i->first, version.get(), i->second.second, location_);
[email protected]a1257b12009-06-12 02:51:34121 }
122 }
123
[email protected]f5ad7542009-07-24 17:38:59124 virtual Version* RegisteredVersion(const std::string& id,
[email protected]a1257b12009-06-12 02:51:34125 Extension::Location* location) const {
126 DataMap::const_iterator it = extension_map_.find(id);
127 if (it == extension_map_.end())
128 return NULL;
129
130 if (location)
131 *location = location_;
132 return Version::GetVersionFromString(it->second.first);
133 }
134
135 private:
136 typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap;
137 DataMap extension_map_;
138 Extension::Location location_;
[email protected]27b985d2009-06-25 17:53:15139
140 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
141};
142
143class MockProviderVisitor : public ExternalExtensionProvider::Visitor {
144 public:
[email protected]eb752082009-09-28 21:18:32145 MockProviderVisitor() : ids_found_(0) {
[email protected]27b985d2009-06-25 17:53:15146 }
147
[email protected]f5ad7542009-07-24 17:38:59148 int Visit(const std::string& json_data,
149 const std::set<std::string>& ignore_list) {
[email protected]27b985d2009-06-25 17:53:15150 // Give the test json file to the provider for parsing.
151 provider_.reset(new ExternalPrefExtensionProvider());
152 provider_->SetPreferencesForTesting(json_data);
153
154 // We also parse the file into a dictionary to compare what we get back
155 // from the provider.
156 JSONStringValueSerializer serializer(json_data);
[email protected]ba399672010-04-06 15:42:39157 Value* json_value = serializer.Deserialize(NULL, NULL);
[email protected]27b985d2009-06-25 17:53:15158
[email protected]ba399672010-04-06 15:42:39159 if (!json_value || !json_value->IsType(Value::TYPE_DICTIONARY)) {
[email protected]27b985d2009-06-25 17:53:15160 NOTREACHED() << L"Unable to deserialize json data";
161 return -1;
162 } else {
163 DictionaryValue* external_extensions =
164 static_cast<DictionaryValue*>(json_value);
165 prefs_.reset(external_extensions);
166 }
167
168 // Reset our counter.
169 ids_found_ = 0;
170 // Ask the provider to look up all extensions (and return the ones
171 // found (that are not on the ignore list).
172 provider_->VisitRegisteredExtension(this, ignore_list);
173
174 return ids_found_;
175 }
176
177 virtual void OnExternalExtensionFound(const std::string& id,
178 const Version* version,
[email protected]7577a5c52009-07-30 06:21:58179 const FilePath& path,
180 Extension::Location unused) {
[email protected]27b985d2009-06-25 17:53:15181 ++ids_found_;
182 DictionaryValue* pref;
183 // This tests is to make sure that the provider only notifies us of the
184 // values we gave it. So if the id we doesn't exist in our internal
185 // dictionary then something is wrong.
186 EXPECT_TRUE(prefs_->GetDictionary(ASCIIToWide(id), &pref))
187 << L"Got back ID (" << id.c_str() << ") we weren't expecting";
188
189 if (pref) {
190 // Ask provider if the extension we got back is registered.
191 Extension::Location location = Extension::INVALID;
192 scoped_ptr<Version> v1(provider_->RegisteredVersion(id, NULL));
193 scoped_ptr<Version> v2(provider_->RegisteredVersion(id, &location));
194 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
195 EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str());
196 EXPECT_EQ(Extension::EXTERNAL_PREF, location);
197
198 // Remove it so we won't count it ever again.
199 prefs_->Remove(ASCIIToWide(id), NULL);
200 }
201 }
202
203 private:
204 int ids_found_;
205
206 scoped_ptr<ExternalPrefExtensionProvider> provider_;
207 scoped_ptr<DictionaryValue> prefs_;
208
209 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
[email protected]a1257b12009-06-12 02:51:34210};
211
[email protected]bf73f0b2010-02-10 19:26:59212class ExtensionTestingProfile : public TestingProfile {
[email protected]6014d672008-12-05 00:38:25213 public:
[email protected]bf73f0b2010-02-10 19:26:59214 ExtensionTestingProfile() {
215 }
216
217 void set_extensions_service(ExtensionsService* service) {
218 service_ = service;
219 }
220 virtual ExtensionsService* GetExtensionsService() { return service_; }
221
222 private:
223 ExtensionsService* service_;
224};
225
226// Our message loop may be used in tests which require it to be an IO loop.
227ExtensionsServiceTestBase::ExtensionsServiceTestBase()
228 : loop_(MessageLoop::TYPE_IO),
229 ui_thread_(ChromeThread::UI, &loop_),
[email protected]c10da4b02010-03-25 14:38:32230 webkit_thread_(ChromeThread::WEBKIT, &loop_),
231 file_thread_(ChromeThread::FILE, &loop_),
232 io_thread_(ChromeThread::IO, &loop_) {
[email protected]bf73f0b2010-02-10 19:26:59233}
234
235ExtensionsServiceTestBase::~ExtensionsServiceTestBase() {
[email protected]c10da4b02010-03-25 14:38:32236 // Drop our reference to ExtensionsService and TestingProfile, so that they
237 // can be destroyed while ChromeThreads and MessageLoop are still around (they
238 // are used in the destruction process).
[email protected]bf73f0b2010-02-10 19:26:59239 service_ = NULL;
[email protected]c10da4b02010-03-25 14:38:32240 profile_.reset(NULL);
[email protected]bf73f0b2010-02-10 19:26:59241 MessageLoop::current()->RunAllPending();
242}
243
244void ExtensionsServiceTestBase::InitializeExtensionsService(
245 const FilePath& pref_file, const FilePath& extensions_install_dir) {
[email protected]6d2e60bd2010-06-03 22:37:39246 // Must setup the commandline here, since Extension caches the switch value
247 // when the prefs are registered.
248 CommandLine::ForCurrentProcess()->AppendSwitch(
249 switches::kEnableExtensionToolstrips);
250 CommandLine::ForCurrentProcess()->AppendSwitch(
251 switches::kEnableApps);
252
[email protected]bf73f0b2010-02-10 19:26:59253 ExtensionTestingProfile* profile = new ExtensionTestingProfile();
[email protected]d8b08c92010-06-07 13:13:28254 // Create a preference service that only contains user defined
255 // preference values.
256 prefs_.reset(new PrefService(new PrefValueStore(
257 NULL, /* No managed preference values */
258 new JsonPrefStore( /* user defined preference values */
[email protected]ea587b02010-05-21 15:01:35259 pref_file,
[email protected]d8b08c92010-06-07 13:13:28260 ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE)),
261 NULL /* No suggested preference values */ )));
[email protected]ea587b02010-05-21 15:01:35262
[email protected]fee8f0222010-03-17 01:13:37263 Profile::RegisterUserPrefs(prefs_.get());
264 browser::RegisterUserPrefs(prefs_.get());
[email protected]bf73f0b2010-02-10 19:26:59265 profile_.reset(profile);
266
[email protected]bf73f0b2010-02-10 19:26:59267 service_ = new ExtensionsService(profile_.get(),
268 CommandLine::ForCurrentProcess(),
269 prefs_.get(),
270 extensions_install_dir,
271 false);
272 service_->set_extensions_enabled(true);
273 service_->set_show_extensions_prompts(false);
274 profile->set_extensions_service(service_.get());
275
276 // When we start up, we want to make sure there is no external provider,
277 // since the ExtensionService on Windows will use the Registry as a default
278 // provider and if there is something already registered there then it will
279 // interfere with the tests. Those tests that need an external provider
280 // will register one specifically.
281 service_->ClearProvidersForTesting();
282
283 total_successes_ = 0;
284}
285
286void ExtensionsServiceTestBase::InitializeInstalledExtensionsService(
287 const FilePath& prefs_file, const FilePath& source_install_dir) {
288 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
289 FilePath path_ = temp_dir_.path();
290 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
291 file_util::Delete(path_, true);
292 file_util::CreateDirectory(path_);
293 FilePath temp_prefs = path_.Append(FILE_PATH_LITERAL("Preferences"));
294 file_util::CopyFile(prefs_file, temp_prefs);
295
296 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions"));
297 file_util::Delete(extensions_install_dir_, true);
298 file_util::CopyDirectory(source_install_dir, extensions_install_dir_, true);
299
300 InitializeExtensionsService(temp_prefs, extensions_install_dir_);
301}
302
303void ExtensionsServiceTestBase::InitializeEmptyExtensionsService() {
304 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
305 FilePath path_ = temp_dir_.path();
306 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
307 file_util::Delete(path_, true);
308 file_util::CreateDirectory(path_);
309 FilePath prefs_filename = path_
310 .Append(FILE_PATH_LITERAL("TestPreferences"));
311 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions"));
312 file_util::Delete(extensions_install_dir_, true);
313 file_util::CreateDirectory(extensions_install_dir_);
314
315 InitializeExtensionsService(prefs_filename, extensions_install_dir_);
316}
317
318// static
319void ExtensionsServiceTestBase::SetUpTestCase() {
320 ExtensionErrorReporter::Init(false); // no noisy errors
321}
322
323void ExtensionsServiceTestBase::SetUp() {
324 ExtensionErrorReporter::GetInstance()->ClearErrors();
325}
326
327class ExtensionsServiceTest
328 : public ExtensionsServiceTestBase, public NotificationObserver {
329 public:
330 ExtensionsServiceTest() : installed_(NULL) {
[email protected]ae09ca62009-08-21 19:46:46331 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
[email protected]894bb502009-05-21 22:39:57332 NotificationService::AllSources());
333 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
334 NotificationService::AllSources());
335 registrar_.Add(this, NotificationType::EXTENSION_INSTALLED,
336 NotificationService::AllSources());
[email protected]e2eb43112009-05-29 21:19:54337 registrar_.Add(this, NotificationType::THEME_INSTALLED,
338 NotificationService::AllSources());
[email protected]a9b00ac2009-06-25 21:03:23339 }
[email protected]cc655912009-01-29 23:19:19340
[email protected]894bb502009-05-21 22:39:57341 virtual void Observe(NotificationType type,
342 const NotificationSource& source,
343 const NotificationDetails& details) {
344 switch (type.value) {
[email protected]ae09ca62009-08-21 19:46:46345 case NotificationType::EXTENSION_LOADED: {
346 Extension* extension = Details<Extension>(details).ptr();
347 loaded_.push_back(extension);
[email protected]894bb502009-05-21 22:39:57348 // The tests rely on the errors being in a certain order, which can vary
349 // depending on how filesystem iteration works.
350 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder());
351 break;
352 }
353
[email protected]9f1087e2009-06-15 17:29:32354 case NotificationType::EXTENSION_UNLOADED: {
355 Extension* e = Details<Extension>(details).ptr();
356 unloaded_id_ = e->id();
357 ExtensionList::iterator i =
358 std::find(loaded_.begin(), loaded_.end(), e);
359 // TODO(erikkay) fix so this can be an assert. Right now the tests
360 // are manually calling clear() on loaded_, so this isn't doable.
361 if (i == loaded_.end())
362 return;
363 loaded_.erase(i);
[email protected]894bb502009-05-21 22:39:57364 break;
[email protected]9f1087e2009-06-15 17:29:32365 }
[email protected]894bb502009-05-21 22:39:57366 case NotificationType::EXTENSION_INSTALLED:
[email protected]e2eb43112009-05-29 21:19:54367 case NotificationType::THEME_INSTALLED:
[email protected]894bb502009-05-21 22:39:57368 installed_ = Details<Extension>(details).ptr();
369 break;
370
[email protected]894bb502009-05-21 22:39:57371 default:
372 DCHECK(false);
[email protected]3acbd422008-12-08 18:25:00373 }
374 }
375
[email protected]a1257b12009-06-12 02:51:34376 void SetMockExternalProvider(Extension::Location location,
377 ExternalExtensionProvider* provider) {
378 service_->SetProviderForTesting(location, provider);
379 }
380
[email protected]9197f3b2009-06-02 00:49:27381 protected:
[email protected]d55e7602009-12-16 04:20:42382 void TestExternalProvider(MockExtensionProvider* provider,
383 Extension::Location location);
384
[email protected]9197f3b2009-06-02 00:49:27385 void InstallExtension(const FilePath& path,
[email protected]d2d89d82009-06-08 21:01:53386 bool should_succeed) {
[email protected]cc655912009-01-29 23:19:19387 ASSERT_TRUE(file_util::PathExists(path));
[email protected]6ef635e42009-07-26 06:16:12388 service_->InstallExtension(path);
[email protected]894bb502009-05-21 22:39:57389 loop_.RunAllPending();
[email protected]bb28e062009-02-27 17:19:18390 std::vector<std::string> errors = GetErrors();
[email protected]cc655912009-01-29 23:19:19391 if (should_succeed) {
[email protected]902f7cd2009-05-22 19:02:19392 ++total_successes_;
393
[email protected]a57209872009-05-04 22:53:14394 EXPECT_TRUE(installed_) << path.value();
[email protected]9197f3b2009-06-02 00:49:27395
[email protected]a1257b12009-06-12 02:51:34396 ASSERT_EQ(1u, loaded_.size()) << path.value();
[email protected]bb28e062009-02-27 17:19:18397 EXPECT_EQ(0u, errors.size()) << path.value();
[email protected]902f7cd2009-05-22 19:02:19398 EXPECT_EQ(total_successes_, service_->extensions()->size()) <<
399 path.value();
[email protected]61b411612009-11-10 23:17:41400 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) <<
[email protected]d2d89d82009-06-08 21:01:53401 path.value();
[email protected]bb28e062009-02-27 17:19:18402 for (std::vector<std::string>::iterator err = errors.begin();
403 err != errors.end(); ++err) {
[email protected]37eeb5a2009-02-26 23:36:17404 LOG(ERROR) << *err;
405 }
[email protected]cc655912009-01-29 23:19:19406 } else {
[email protected]a57209872009-05-04 22:53:14407 EXPECT_FALSE(installed_) << path.value();
[email protected]86a274072009-06-11 02:06:45408 EXPECT_EQ(0u, loaded_.size()) << path.value();
[email protected]bb28e062009-02-27 17:19:18409 EXPECT_EQ(1u, errors.size()) << path.value();
[email protected]cc655912009-01-29 23:19:19410 }
[email protected]bb28e062009-02-27 17:19:18411
[email protected]a57209872009-05-04 22:53:14412 installed_ = NULL;
[email protected]894bb502009-05-21 22:39:57413 loaded_.clear();
[email protected]bb28e062009-02-27 17:19:18414 ExtensionErrorReporter::GetInstance()->ClearErrors();
[email protected]cc655912009-01-29 23:19:19415 }
416
[email protected]7577a5c52009-07-30 06:21:58417 void UpdateExtension(const std::string& id, const FilePath& in_path,
[email protected]aa142702010-03-26 01:26:33418 bool should_succeed, bool should_install,
419 bool expect_report_on_failure) {
[email protected]7577a5c52009-07-30 06:21:58420 ASSERT_TRUE(file_util::PathExists(in_path));
[email protected]e957fe52009-06-23 16:51:05421
[email protected]7577a5c52009-07-30 06:21:58422 // We need to copy this to a temporary location because Update() will delete
423 // it.
[email protected]a1295ba22009-09-02 03:33:39424 FilePath path = temp_dir_.path();
425 path = path.Append(in_path.BaseName());
[email protected]7577a5c52009-07-30 06:21:58426 ASSERT_TRUE(file_util::CopyFile(in_path, path));
[email protected]e957fe52009-06-23 16:51:05427
[email protected]5c8516202010-03-18 21:43:34428 service_->UpdateExtension(id, path, GURL());
[email protected]e957fe52009-06-23 16:51:05429 loop_.RunAllPending();
430 std::vector<std::string> errors = GetErrors();
431
[email protected]e957fe52009-06-23 16:51:05432 if (should_succeed) {
433 EXPECT_EQ(0u, errors.size()) << path.value();
[email protected]aa142702010-03-26 01:26:33434 EXPECT_EQ(should_install ? 1u : 0u, service_->extensions()->size());
[email protected]e957fe52009-06-23 16:51:05435 } else {
436 if (expect_report_on_failure) {
437 EXPECT_EQ(1u, errors.size()) << path.value();
438 }
[email protected]e957fe52009-06-23 16:51:05439 }
[email protected]7577a5c52009-07-30 06:21:58440
441 // Update() should delete the temporary input file.
442 EXPECT_FALSE(file_util::PathExists(path));
[email protected]e957fe52009-06-23 16:51:05443 }
444
[email protected]25b34332009-06-05 21:53:19445 void ValidatePrefKeyCount(size_t count) {
446 DictionaryValue* dict =
[email protected]a9b00ac2009-06-25 21:03:23447 prefs_->GetMutableDictionary(L"extensions.settings");
[email protected]25b34332009-06-05 21:53:19448 ASSERT_TRUE(dict != NULL);
[email protected]4dad9ad82009-11-25 20:47:52449 EXPECT_EQ(count, dict->size());
[email protected]25b34332009-06-05 21:53:19450 }
451
[email protected]6b75ec32009-08-14 06:37:18452 void ValidateBooleanPref(const std::string& extension_id,
453 const std::wstring& pref_path,
[email protected]c6d474f82009-12-16 21:11:06454 bool expected_val) {
[email protected]6b75ec32009-08-14 06:37:18455 std::wstring msg = L" while checking: ";
456 msg += ASCIIToWide(extension_id);
457 msg += L" ";
458 msg += pref_path;
459 msg += L" == ";
[email protected]c6d474f82009-12-16 21:11:06460 msg += expected_val ? L"true" : L"false";
[email protected]6b75ec32009-08-14 06:37:18461
462 const DictionaryValue* dict =
463 prefs_->GetDictionary(L"extensions.settings");
464 ASSERT_TRUE(dict != NULL) << msg;
465 DictionaryValue* pref = NULL;
466 ASSERT_TRUE(dict->GetDictionary(ASCIIToWide(extension_id), &pref)) << msg;
467 EXPECT_TRUE(pref != NULL) << msg;
468 bool val;
[email protected]4c91487e2009-10-02 04:11:04469 ASSERT_TRUE(pref->GetBoolean(pref_path, &val)) << msg;
[email protected]c6d474f82009-12-16 21:11:06470 EXPECT_EQ(expected_val, val) << msg;
[email protected]6b75ec32009-08-14 06:37:18471 }
472
473 bool IsPrefExist(const std::string& extension_id,
474 const std::wstring& pref_path) {
475 const DictionaryValue* dict =
476 prefs_->GetDictionary(L"extensions.settings");
477 if (dict == NULL) return false;
478 DictionaryValue* pref = NULL;
479 if (!dict->GetDictionary(ASCIIToWide(extension_id), &pref)) {
480 return false;
481 }
482 if (pref == NULL) {
483 return false;
484 }
485 bool val;
486 if (!pref->GetBoolean(pref_path, &val)) {
487 return false;
488 }
489 return true;
490 }
491
492 void ValidateIntegerPref(const std::string& extension_id,
493 const std::wstring& pref_path,
[email protected]c6d474f82009-12-16 21:11:06494 int expected_val) {
[email protected]25b34332009-06-05 21:53:19495 std::wstring msg = L" while checking: ";
496 msg += ASCIIToWide(extension_id);
497 msg += L" ";
498 msg += pref_path;
499 msg += L" == ";
[email protected]c6d474f82009-12-16 21:11:06500 msg += IntToWString(expected_val);
[email protected]25b34332009-06-05 21:53:19501
502 const DictionaryValue* dict =
[email protected]a9b00ac2009-06-25 21:03:23503 prefs_->GetDictionary(L"extensions.settings");
[email protected]25b34332009-06-05 21:53:19504 ASSERT_TRUE(dict != NULL) << msg;
505 DictionaryValue* pref = NULL;
506 ASSERT_TRUE(dict->GetDictionary(ASCIIToWide(extension_id), &pref)) << msg;
507 EXPECT_TRUE(pref != NULL) << msg;
508 int val;
[email protected]4c91487e2009-10-02 04:11:04509 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg;
[email protected]c6d474f82009-12-16 21:11:06510 EXPECT_EQ(expected_val, val) << msg;
511 }
512
513 void ValidateStringPref(const std::string& extension_id,
514 const std::wstring& pref_path,
515 const std::string& expected_val) {
516 std::wstring msg = L" while checking: ";
517 msg += ASCIIToWide(extension_id);
518 msg += L".manifest.";
519 msg += pref_path;
520 msg += L" == ";
521 msg += ASCIIToWide(expected_val);
522
523 const DictionaryValue* dict =
524 prefs_->GetDictionary(L"extensions.settings");
525 ASSERT_TRUE(dict != NULL) << msg;
526 DictionaryValue* pref = NULL;
527 std::string manifest_path = extension_id + ".manifest";
528 ASSERT_TRUE(dict->GetDictionary(ASCIIToWide(manifest_path), &pref)) << msg;
529 EXPECT_TRUE(pref != NULL) << msg;
530 std::string val;
531 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg;
532 EXPECT_EQ(expected_val, val) << msg;
[email protected]25b34332009-06-05 21:53:19533 }
534
[email protected]6b75ec32009-08-14 06:37:18535 void SetPrefInteg(const std::string& extension_id,
536 const std::wstring& pref_path,
537 int value) {
[email protected]a1257b12009-06-12 02:51:34538 std::wstring msg = L" while setting: ";
539 msg += ASCIIToWide(extension_id);
540 msg += L" ";
541 msg += pref_path;
542 msg += L" = ";
543 msg += IntToWString(value);
544
545 const DictionaryValue* dict =
[email protected]a9b00ac2009-06-25 21:03:23546 prefs_->GetMutableDictionary(L"extensions.settings");
[email protected]a1257b12009-06-12 02:51:34547 ASSERT_TRUE(dict != NULL) << msg;
548 DictionaryValue* pref = NULL;
549 ASSERT_TRUE(dict->GetDictionary(ASCIIToWide(extension_id), &pref)) << msg;
550 EXPECT_TRUE(pref != NULL) << msg;
551 pref->SetInteger(pref_path, value);
552 }
553
[email protected]25b34332009-06-05 21:53:19554 protected:
[email protected]9f1087e2009-06-15 17:29:32555 ExtensionList loaded_;
[email protected]894bb502009-05-21 22:39:57556 std::string unloaded_id_;
557 Extension* installed_;
[email protected]894bb502009-05-21 22:39:57558
[email protected]6014d672008-12-05 00:38:25559 private:
[email protected]894bb502009-05-21 22:39:57560 NotificationRegistrar registrar_;
[email protected]bb28e062009-02-27 17:19:18561};
[email protected]6014d672008-12-05 00:38:25562
[email protected]a3278802009-07-24 17:50:20563FilePath::StringType NormalizeSeperators(FilePath::StringType path) {
[email protected]a9b00ac2009-06-25 21:03:23564#if defined(FILE_PATH_USES_WIN_SEPARATORS)
565 FilePath::StringType ret_val;
566 for (size_t i = 0; i < path.length(); i++) {
567 if (FilePath::IsSeparator(path[i]))
568 path[i] = FilePath::kSeparators[0];
569 }
570#endif // FILE_PATH_USES_WIN_SEPARATORS
571 return path;
572}
[email protected]54cb3c92009-02-17 22:30:21573// Test loading good extensions from the profile directory.
[email protected]a9b00ac2009-06-25 21:03:23574TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) {
575 // Initialize the test dir with a good Preferences/extensions.
576 FilePath source_install_dir;
577 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir));
578 source_install_dir = source_install_dir
579 .AppendASCII("extensions")
580 .AppendASCII("good")
581 .AppendASCII("Extensions");
582 FilePath pref_path = source_install_dir
583 .DirName()
584 .AppendASCII("Preferences");
585 InitializeInstalledExtensionsService(pref_path, source_install_dir);
[email protected]6014d672008-12-05 00:38:25586
[email protected]9f1087e2009-06-15 17:29:32587 service_->Init();
[email protected]894bb502009-05-21 22:39:57588 loop_.RunAllPending();
[email protected]6014d672008-12-05 00:38:25589
[email protected]894bb502009-05-21 22:39:57590 ASSERT_EQ(3u, loaded_.size());
[email protected]6014d672008-12-05 00:38:25591
[email protected]fbcc40302009-06-12 20:45:45592 EXPECT_EQ(std::string(good0), loaded_[0]->id());
[email protected]e1cec06c2008-12-18 01:22:23593 EXPECT_EQ(std::string("My extension 1"),
[email protected]894bb502009-05-21 22:39:57594 loaded_[0]->name());
[email protected]e1cec06c2008-12-18 01:22:23595 EXPECT_EQ(std::string("The first extension that I made."),
[email protected]894bb502009-05-21 22:39:57596 loaded_[0]->description());
597 EXPECT_EQ(Extension::INTERNAL, loaded_[0]->location());
[email protected]61b411612009-11-10 23:17:41598 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false));
[email protected]894bb502009-05-21 22:39:57599 EXPECT_EQ(3u, service_->extensions()->size());
[email protected]eab9b452009-01-23 20:48:59600
[email protected]25b34332009-06-05 21:53:19601 ValidatePrefKeyCount(3);
[email protected]6b75ec32009-08-14 06:37:18602 ValidateIntegerPref(good0, L"state", Extension::ENABLED);
603 ValidateIntegerPref(good0, L"location", Extension::INTERNAL);
604 ValidateIntegerPref(good1, L"state", Extension::ENABLED);
605 ValidateIntegerPref(good1, L"location", Extension::INTERNAL);
606 ValidateIntegerPref(good2, L"state", Extension::ENABLED);
607 ValidateIntegerPref(good2, L"location", Extension::INTERNAL);
[email protected]25b34332009-06-05 21:53:19608
[email protected]894bb502009-05-21 22:39:57609 Extension* extension = loaded_[0];
[email protected]34aa8dc2009-02-19 07:03:05610 const UserScriptList& scripts = extension->content_scripts();
[email protected]bbc945542009-07-26 00:11:42611 const std::vector<Extension::ToolstripInfo>& toolstrips =
612 extension->toolstrips();
[email protected]e66de892009-03-20 20:38:43613 ASSERT_EQ(2u, scripts.size());
[email protected]f0488f2f2009-07-01 05:25:22614 EXPECT_EQ(3u, scripts[0].url_patterns().size());
[email protected]62771442009-11-22 02:25:04615 EXPECT_EQ("file://*",
[email protected]5f8681f2009-11-18 03:21:13616 scripts[0].url_patterns()[0].GetAsString());
[email protected]62771442009-11-22 02:25:04617 EXPECT_EQ("http://*.google.com/*",
[email protected]5f8681f2009-11-18 03:21:13618 scripts[0].url_patterns()[1].GetAsString());
[email protected]62771442009-11-22 02:25:04619 EXPECT_EQ("https://*.google.com/*",
[email protected]f0488f2f2009-07-01 05:25:22620 scripts[0].url_patterns()[2].GetAsString());
[email protected]e66de892009-03-20 20:38:43621 EXPECT_EQ(2u, scripts[0].js_scripts().size());
[email protected]9194b3f2009-10-20 15:27:21622 ExtensionResource resource00(scripts[0].js_scripts()[0].extension_root(),
623 scripts[0].js_scripts()[0].relative_path());
[email protected]a14b16b2009-10-28 12:41:29624 FilePath expected_path(extension->path().AppendASCII("script1.js"));
625 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
626 EXPECT_TRUE(resource00.ComparePathWithDefault(expected_path));
[email protected]9194b3f2009-10-20 15:27:21627 ExtensionResource resource01(scripts[0].js_scripts()[1].extension_root(),
628 scripts[0].js_scripts()[1].relative_path());
[email protected]a14b16b2009-10-28 12:41:29629 expected_path = extension->path().AppendASCII("script2.js");
630 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
631 EXPECT_TRUE(resource01.ComparePathWithDefault(expected_path));
[email protected]c533bb22009-06-03 19:06:11632 EXPECT_TRUE(extension->plugins().empty());
[email protected]e66de892009-03-20 20:38:43633 EXPECT_EQ(1u, scripts[1].url_patterns().size());
634 EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString());
[email protected]9194b3f2009-10-20 15:27:21635 ExtensionResource resource10(scripts[1].js_scripts()[0].extension_root(),
636 scripts[1].js_scripts()[0].relative_path());
[email protected]a14b16b2009-10-28 12:41:29637 expected_path =
638 extension->path().AppendASCII("js_files").AppendASCII("script3.js");
639 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
640 EXPECT_TRUE(resource10.ComparePathWithDefault(expected_path));
[email protected]35506352009-08-07 18:58:19641 const std::vector<URLPattern> permissions = extension->host_permissions();
[email protected]7197f4992009-03-23 05:05:49642 ASSERT_EQ(2u, permissions.size());
643 EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString());
644 EXPECT_EQ("https://*.google.com/*", permissions[1].GetAsString());
[email protected]d5cef1b2009-03-21 05:36:49645 ASSERT_EQ(2u, toolstrips.size());
[email protected]bbc945542009-07-26 00:11:42646 EXPECT_EQ(extension->GetResourceURL("toolstrip1.html"),
647 toolstrips[0].toolstrip);
[email protected]e7a89e12009-07-26 23:29:47648 EXPECT_EQ(extension->GetResourceURL("lorem_ipsum.html"),
649 toolstrips[0].mole);
650 EXPECT_EQ(200, toolstrips[0].mole_height);
[email protected]bbc945542009-07-26 00:11:42651 EXPECT_EQ(extension->GetResourceURL("toolstrip2.html"),
652 toolstrips[1].toolstrip);
[email protected]6014d672008-12-05 00:38:25653
[email protected]25b34332009-06-05 21:53:19654 EXPECT_EQ(std::string(good1), loaded_[1]->id());
[email protected]894bb502009-05-21 22:39:57655 EXPECT_EQ(std::string("My extension 2"), loaded_[1]->name());
656 EXPECT_EQ(std::string(""), loaded_[1]->description());
[email protected]81067e02009-07-27 15:12:09657 EXPECT_EQ(loaded_[1]->GetResourceURL("background.html"),
658 loaded_[1]->background_url());
[email protected]894bb502009-05-21 22:39:57659 EXPECT_EQ(0u, loaded_[1]->content_scripts().size());
[email protected]c533bb22009-06-03 19:06:11660 EXPECT_EQ(2u, loaded_[1]->plugins().size());
661 EXPECT_EQ(loaded_[1]->path().AppendASCII("content_plugin.dll").value(),
662 loaded_[1]->plugins()[0].path.value());
663 EXPECT_TRUE(loaded_[1]->plugins()[0].is_public);
664 EXPECT_EQ(loaded_[1]->path().AppendASCII("extension_plugin.dll").value(),
665 loaded_[1]->plugins()[1].path.value());
666 EXPECT_FALSE(loaded_[1]->plugins()[1].is_public);
[email protected]894bb502009-05-21 22:39:57667 EXPECT_EQ(Extension::INTERNAL, loaded_[1]->location());
[email protected]18a12352009-01-31 01:33:28668
[email protected]25b34332009-06-05 21:53:19669 EXPECT_EQ(std::string(good2), loaded_[2]->id());
[email protected]894bb502009-05-21 22:39:57670 EXPECT_EQ(std::string("My extension 3"), loaded_[2]->name());
671 EXPECT_EQ(std::string(""), loaded_[2]->description());
[email protected]7a379f02010-01-08 23:14:12672 EXPECT_EQ(0u, loaded_[2]->content_scripts().size());
[email protected]894bb502009-05-21 22:39:57673 EXPECT_EQ(Extension::INTERNAL, loaded_[2]->location());
[email protected]6014d672008-12-05 00:38:25674};
[email protected]cc655912009-01-29 23:19:19675
[email protected]54cb3c92009-02-17 22:30:21676// Test loading bad extensions from the profile directory.
[email protected]a9b00ac2009-06-25 21:03:23677TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectoryFail) {
[email protected]c6d474f82009-12-16 21:11:06678 // Initialize the test dir with a bad Preferences/extensions.
[email protected]a9b00ac2009-06-25 21:03:23679 FilePath source_install_dir;
680 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir));
681 source_install_dir = source_install_dir
682 .AppendASCII("extensions")
683 .AppendASCII("bad")
684 .AppendASCII("Extensions");
685 FilePath pref_path = source_install_dir
686 .DirName()
687 .AppendASCII("Preferences");
[email protected]54cb3c92009-02-17 22:30:21688
[email protected]a9b00ac2009-06-25 21:03:23689 InitializeInstalledExtensionsService(pref_path, source_install_dir);
[email protected]54cb3c92009-02-17 22:30:21690
[email protected]9f1087e2009-06-15 17:29:32691 service_->Init();
[email protected]894bb502009-05-21 22:39:57692 loop_.RunAllPending();
[email protected]54cb3c92009-02-17 22:30:21693
[email protected]a9b00ac2009-06-25 21:03:23694 ASSERT_EQ(4u, GetErrors().size());
695 ASSERT_EQ(0u, loaded_.size());
[email protected]25b34332009-06-05 21:53:19696
[email protected]c5a72482009-12-03 23:32:57697 EXPECT_TRUE(MatchPatternASCII(GetErrors()[0],
[email protected]d7b36dc2009-10-29 21:47:40698 std::string("Could not load extension from '*'. ") +
699 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[0];
[email protected]8d6d9ff2009-02-20 08:14:39700
[email protected]c5a72482009-12-03 23:32:57701 EXPECT_TRUE(MatchPatternASCII(GetErrors()[1],
[email protected]8d6d9ff2009-02-20 08:14:39702 std::string("Could not load extension from '*'. ") +
[email protected]f6f5b8b2009-10-09 21:28:19703 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[1];
[email protected]8d6d9ff2009-02-20 08:14:39704
[email protected]c5a72482009-12-03 23:32:57705 EXPECT_TRUE(MatchPatternASCII(GetErrors()[2],
[email protected]8d6d9ff2009-02-20 08:14:39706 std::string("Could not load extension from '*'. ") +
[email protected]cb691e82009-07-13 14:59:01707 extension_manifest_errors::kMissingFile)) << GetErrors()[2];
[email protected]a9b00ac2009-06-25 21:03:23708
[email protected]c5a72482009-12-03 23:32:57709 EXPECT_TRUE(MatchPatternASCII(GetErrors()[3],
[email protected]a9b00ac2009-06-25 21:03:23710 std::string("Could not load extension from '*'. ") +
[email protected]f6f5b8b2009-10-09 21:28:19711 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[3];
[email protected]54cb3c92009-02-17 22:30:21712};
713
[email protected]894bb502009-05-21 22:39:57714// Test that partially deleted extensions are cleaned up during startup
715// Test loading bad extensions from the profile directory.
716TEST_F(ExtensionsServiceTest, CleanupOnStartup) {
[email protected]b6ab96d2009-08-20 18:58:19717 FilePath source_install_dir;
718 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir));
719 source_install_dir = source_install_dir
720 .AppendASCII("extensions")
721 .AppendASCII("good")
722 .AppendASCII("Extensions");
723 FilePath pref_path = source_install_dir
724 .DirName()
725 .AppendASCII("Preferences");
[email protected]a9b00ac2009-06-25 21:03:23726
[email protected]b6ab96d2009-08-20 18:58:19727 InitializeInstalledExtensionsService(pref_path, source_install_dir);
[email protected]894bb502009-05-21 22:39:57728
[email protected]b6ab96d2009-08-20 18:58:19729 // Simulate that one of them got partially deleted by clearing its pref.
[email protected]9b410dee2009-10-08 21:12:35730 DictionaryValue* dict = prefs_->GetMutableDictionary(L"extensions.settings");
[email protected]932342a2009-10-08 21:27:17731 ASSERT_TRUE(dict != NULL);
[email protected]9b410dee2009-10-08 21:12:35732 dict->Remove(L"behllobkkfkfnphdnhnkndlbkcpglgmj", NULL);
[email protected]894bb502009-05-21 22:39:57733
734 service_->Init();
735 loop_.RunAllPending();
736
[email protected]a9b00ac2009-06-25 21:03:23737 file_util::FileEnumerator dirs(extensions_install_dir_, false,
[email protected]9f1087e2009-06-15 17:29:32738 file_util::FileEnumerator::DIRECTORIES);
739 size_t count = 0;
740 while (!dirs.Next().empty())
741 count++;
742
[email protected]894bb502009-05-21 22:39:57743 // We should have only gotten two extensions now.
[email protected]9f1087e2009-06-15 17:29:32744 EXPECT_EQ(2u, count);
[email protected]e2eb43112009-05-29 21:19:54745
[email protected]894bb502009-05-21 22:39:57746 // And extension1 dir should now be toast.
[email protected]b6ab96d2009-08-20 18:58:19747 FilePath extension_dir = extensions_install_dir_
748 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj");
749 ASSERT_FALSE(file_util::PathExists(extension_dir));
[email protected]894bb502009-05-21 22:39:57750}
751
[email protected]d7eaf572009-07-01 21:57:00752// Test installing extensions. This test tries to install few extensions using
753// crx files. If you need to change those crx files, feel free to repackage
754// them, throw away the key used and change the id's above.
[email protected]da0aa3b2009-12-06 21:41:03755TEST_F(ExtensionsServiceTest, InstallExtension) {
[email protected]a9b00ac2009-06-25 21:03:23756 InitializeEmptyExtensionsService();
757
[email protected]cc655912009-01-29 23:19:19758 FilePath extensions_path;
759 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
760 extensions_path = extensions_path.AppendASCII("extensions");
761
[email protected]e2eb43112009-05-29 21:19:54762 // Extensions not enabled.
[email protected]7577a5c52009-07-30 06:21:58763 set_extensions_enabled(false);
[email protected]894bb502009-05-21 22:39:57764 FilePath path = extensions_path.AppendASCII("good.crx");
[email protected]d2d89d82009-06-08 21:01:53765 InstallExtension(path, false);
[email protected]7577a5c52009-07-30 06:21:58766 set_extensions_enabled(true);
[email protected]e2eb43112009-05-29 21:19:54767
[email protected]25b34332009-06-05 21:53:19768 ValidatePrefKeyCount(0);
769
[email protected]e2eb43112009-05-29 21:19:54770 // A simple extension that should install without error.
771 path = extensions_path.AppendASCII("good.crx");
[email protected]d2d89d82009-06-08 21:01:53772 InstallExtension(path, true);
[email protected]cc655912009-01-29 23:19:19773 // TODO(erikkay): verify the contents of the installed extension.
774
[email protected]25b34332009-06-05 21:53:19775 int pref_count = 0;
776 ValidatePrefKeyCount(++pref_count);
[email protected]6b75ec32009-08-14 06:37:18777 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
778 ValidateIntegerPref(good_crx, L"location", Extension::INTERNAL);
[email protected]25b34332009-06-05 21:53:19779
[email protected]902f7cd2009-05-22 19:02:19780 // An extension with page actions.
781 path = extensions_path.AppendASCII("page_action.crx");
[email protected]d2d89d82009-06-08 21:01:53782 InstallExtension(path, true);
[email protected]25b34332009-06-05 21:53:19783 ValidatePrefKeyCount(++pref_count);
[email protected]6b75ec32009-08-14 06:37:18784 ValidateIntegerPref(page_action, L"state", Extension::ENABLED);
785 ValidateIntegerPref(page_action, L"location", Extension::INTERNAL);
[email protected]902f7cd2009-05-22 19:02:19786
[email protected]9f1087e2009-06-15 17:29:32787 // Bad signature.
[email protected]fbcc40302009-06-12 20:45:45788 path = extensions_path.AppendASCII("bad_signature.crx");
789 InstallExtension(path, false);
[email protected]d7eaf572009-07-01 21:57:00790 ValidatePrefKeyCount(pref_count);
[email protected]fbcc40302009-06-12 20:45:45791
[email protected]cc655912009-01-29 23:19:19792 // 0-length extension file.
793 path = extensions_path.AppendASCII("not_an_extension.crx");
[email protected]d2d89d82009-06-08 21:01:53794 InstallExtension(path, false);
[email protected]25b34332009-06-05 21:53:19795 ValidatePrefKeyCount(pref_count);
[email protected]cc655912009-01-29 23:19:19796
797 // Bad magic number.
798 path = extensions_path.AppendASCII("bad_magic.crx");
[email protected]d2d89d82009-06-08 21:01:53799 InstallExtension(path, false);
[email protected]25b34332009-06-05 21:53:19800 ValidatePrefKeyCount(pref_count);
[email protected]cc655912009-01-29 23:19:19801
[email protected]99872e32009-09-25 22:02:49802 // Extensions cannot have folders or files that have underscores except ofr in
803 // certain whitelisted cases (eg _locales). This is an example of a broader
804 // class of validation that we do to the directory structure of the extension.
805 // We did not used to handle this correctly for installation.
806 path = extensions_path.AppendASCII("bad_underscore.crx");
807 InstallExtension(path, false);
808 ValidatePrefKeyCount(pref_count);
809
[email protected]cc655912009-01-29 23:19:19810 // TODO(erikkay): add more tests for many of the failure cases.
811 // TODO(erikkay): add tests for upgrade cases.
812}
813
[email protected]da0aa3b2009-12-06 21:41:03814// Install a user script (they get converted automatically to an extension)
815TEST_F(ExtensionsServiceTest, InstallUserScript) {
816 // The details of script conversion are tested elsewhere, this just tests
817 // integration with ExtensionsService.
818 InitializeEmptyExtensionsService();
819
820 FilePath path;
821 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
822 path = path.AppendASCII("extensions")
823 .AppendASCII("user_script_basic.user.js");
824
825 ASSERT_TRUE(file_util::PathExists(path));
[email protected]6dfbbf82010-03-12 23:09:16826 scoped_refptr<CrxInstaller> installer(
827 new CrxInstaller(service_->install_directory(),
828 service_,
829 NULL)); // silent install
830 installer->InstallUserScript(
[email protected]da0aa3b2009-12-06 21:41:03831 path,
[email protected]6dfbbf82010-03-12 23:09:16832 GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js"));
[email protected]da0aa3b2009-12-06 21:41:03833
834 loop_.RunAllPending();
835 std::vector<std::string> errors = GetErrors();
836 EXPECT_TRUE(installed_) << "Nothing was installed.";
837 ASSERT_EQ(1u, loaded_.size()) << "Nothing was loaded.";
838 EXPECT_EQ(0u, errors.size()) << "There were errors: "
839 << JoinString(errors, ',');
840 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) <<
841 path.value();
842
843 installed_ = NULL;
844 loaded_.clear();
845 ExtensionErrorReporter::GetInstance()->ClearErrors();
846}
847
[email protected]a17f9462009-06-09 02:56:41848// Test Packaging and installing an extension.
[email protected]a17f9462009-06-09 02:56:41849TEST_F(ExtensionsServiceTest, PackExtension) {
[email protected]a9b00ac2009-06-25 21:03:23850 InitializeEmptyExtensionsService();
[email protected]a17f9462009-06-09 02:56:41851 FilePath extensions_path;
852 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
853 extensions_path = extensions_path.AppendASCII("extensions");
[email protected]a9b00ac2009-06-25 21:03:23854 FilePath input_directory = extensions_path
855 .AppendASCII("good")
856 .AppendASCII("Extensions")
857 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
858 .AppendASCII("1.0.0.0");
[email protected]a17f9462009-06-09 02:56:41859
[email protected]aca3e9b2009-11-03 01:14:21860 ScopedTempDir temp_dir;
861 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
862 FilePath output_directory = temp_dir.path();
863
[email protected]a17f9462009-06-09 02:56:41864 FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
865 FilePath privkey_path(output_directory.AppendASCII("privkey.pem"));
866
867 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
868 ASSERT_TRUE(creator->Run(input_directory, crx_path, FilePath(),
869 privkey_path));
870
[email protected]a17f9462009-06-09 02:56:41871 ASSERT_TRUE(file_util::PathExists(privkey_path));
[email protected]5a2721f62009-06-13 07:08:20872 InstallExtension(crx_path, true);
[email protected]0dc2ca82009-11-17 07:06:16873
874 // Try packing with invalid paths.
875 creator.reset(new ExtensionCreator());
876 ASSERT_FALSE(creator->Run(FilePath(), FilePath(), FilePath(), FilePath()));
877
878 // Try packing an empty directory. Should fail because an empty directory is
879 // not a valid extension.
880 ScopedTempDir temp_dir2;
881 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
882 creator.reset(new ExtensionCreator());
883 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
884 FilePath()));
885
886 // Try packing with an invalid manifest.
887 std::string invalid_manifest_content = "I am not a manifest.";
888 ASSERT_TRUE(file_util::WriteFile(
[email protected]99efb7b12009-12-18 02:39:16889 temp_dir2.path().Append(Extension::kManifestFilename),
[email protected]0dc2ca82009-11-17 07:06:16890 invalid_manifest_content.c_str(), invalid_manifest_content.size()));
891 creator.reset(new ExtensionCreator());
892 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
893 FilePath()));
[email protected]a17f9462009-06-09 02:56:41894}
895
896// Test Packaging and installing an extension using an openssl generated key.
897// The openssl is generated with the following:
[email protected]a1257b12009-06-12 02:51:34898// > openssl genrsa -out privkey.pem 1024
[email protected]df4956e2009-06-10 16:53:42899// > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem
[email protected]a1257b12009-06-12 02:51:34900// The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a
[email protected]a17f9462009-06-09 02:56:41901// PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects.
902TEST_F(ExtensionsServiceTest, PackExtensionOpenSSLKey) {
[email protected]a9b00ac2009-06-25 21:03:23903 InitializeEmptyExtensionsService();
[email protected]a17f9462009-06-09 02:56:41904 FilePath extensions_path;
905 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
906 extensions_path = extensions_path.AppendASCII("extensions");
[email protected]a9b00ac2009-06-25 21:03:23907 FilePath input_directory = extensions_path
908 .AppendASCII("good")
909 .AppendASCII("Extensions")
910 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
911 .AppendASCII("1.0.0.0");
[email protected]a17f9462009-06-09 02:56:41912 FilePath privkey_path(extensions_path.AppendASCII(
913 "openssl_privkey_asn1.pem"));
914 ASSERT_TRUE(file_util::PathExists(privkey_path));
915
[email protected]aca3e9b2009-11-03 01:14:21916 ScopedTempDir temp_dir;
917 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
918 FilePath output_directory = temp_dir.path();
919
[email protected]a17f9462009-06-09 02:56:41920 FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
921
922 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
923 ASSERT_TRUE(creator->Run(input_directory, crx_path, privkey_path,
924 FilePath()));
925
[email protected]5a2721f62009-06-13 07:08:20926 InstallExtension(crx_path, true);
[email protected]a17f9462009-06-09 02:56:41927}
[email protected]a17f9462009-06-09 02:56:41928
[email protected]e2eb43112009-05-29 21:19:54929TEST_F(ExtensionsServiceTest, InstallTheme) {
[email protected]a9b00ac2009-06-25 21:03:23930 InitializeEmptyExtensionsService();
[email protected]e2eb43112009-05-29 21:19:54931 FilePath extensions_path;
932 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
933 extensions_path = extensions_path.AppendASCII("extensions");
934
935 // A theme.
936 FilePath path = extensions_path.AppendASCII("theme.crx");
[email protected]d2d89d82009-06-08 21:01:53937 InstallExtension(path, true);
[email protected]25b34332009-06-05 21:53:19938 int pref_count = 0;
939 ValidatePrefKeyCount(++pref_count);
[email protected]6b75ec32009-08-14 06:37:18940 ValidateIntegerPref(theme_crx, L"state", Extension::ENABLED);
941 ValidateIntegerPref(theme_crx, L"location", Extension::INTERNAL);
[email protected]e2eb43112009-05-29 21:19:54942
[email protected]6ef635e42009-07-26 06:16:12943 // A theme when extensions are disabled. Themes can be installed, even when
944 // extensions are disabled.
[email protected]7577a5c52009-07-30 06:21:58945 set_extensions_enabled(false);
[email protected]e2eb43112009-05-29 21:19:54946 path = extensions_path.AppendASCII("theme2.crx");
[email protected]6ef635e42009-07-26 06:16:12947 InstallExtension(path, true);
[email protected]25b34332009-06-05 21:53:19948 ValidatePrefKeyCount(++pref_count);
[email protected]6b75ec32009-08-14 06:37:18949 ValidateIntegerPref(theme2_crx, L"state", Extension::ENABLED);
950 ValidateIntegerPref(theme2_crx, L"location", Extension::INTERNAL);
[email protected]494c06e2009-07-25 01:06:42951
[email protected]25b34332009-06-05 21:53:19952 // A theme with extension elements. Themes cannot have extension elements so
953 // this test should fail.
[email protected]7577a5c52009-07-30 06:21:58954 set_extensions_enabled(true);
[email protected]e2eb43112009-05-29 21:19:54955 path = extensions_path.AppendASCII("theme_with_extension.crx");
[email protected]d2d89d82009-06-08 21:01:53956 InstallExtension(path, false);
[email protected]25b34332009-06-05 21:53:19957 ValidatePrefKeyCount(pref_count);
[email protected]12198912009-06-05 03:41:22958
959 // A theme with image resources missing (misspelt path).
960 path = extensions_path.AppendASCII("theme_missing_image.crx");
[email protected]d2d89d82009-06-08 21:01:53961 InstallExtension(path, false);
[email protected]25b34332009-06-05 21:53:19962 ValidatePrefKeyCount(pref_count);
[email protected]e2eb43112009-05-29 21:19:54963}
964
[email protected]584245e52010-06-17 01:08:13965TEST_F(ExtensionsServiceTest, LoadLocalizedTheme) {
966 // Load.
967 InitializeEmptyExtensionsService();
968 FilePath extension_path;
969 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
970 extension_path = extension_path
971 .AppendASCII("extensions")
972 .AppendASCII("theme_i18n");
973
974 service_->LoadExtension(extension_path);
975 loop_.RunAllPending();
976 EXPECT_EQ(0u, GetErrors().size());
977 ASSERT_EQ(1u, loaded_.size());
978 EXPECT_EQ(1u, service_->extensions()->size());
979 EXPECT_EQ("name", service_->extensions()->at(0)->name());
980 EXPECT_EQ("description", service_->extensions()->at(0)->description());
981}
982
983TEST_F(ExtensionsServiceTest, InstallLocalizedTheme) {
984 // Pack.
985 InitializeEmptyExtensionsService();
986 FilePath extension_path;
987 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
988 extension_path = extension_path
989 .AppendASCII("extensions")
990 .AppendASCII("theme_i18n");
991
992 FilePath crx_path;
993 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &crx_path));
994 crx_path = crx_path.AppendASCII("theme.crx");
995 FilePath pem_path = crx_path.DirName().AppendASCII("theme.pem");
996
997 ASSERT_TRUE(file_util::Delete(crx_path, false));
998 ASSERT_TRUE(file_util::Delete(pem_path, false));
999 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
1000 ASSERT_TRUE(creator->Run(extension_path, crx_path, FilePath(), pem_path));
1001 ASSERT_TRUE(file_util::PathExists(crx_path));
1002
1003 // Install.
1004 service_->UnloadAllExtensions();
1005 InstallExtension(crx_path, true);
1006 EXPECT_EQ(0u, GetErrors().size());
1007 EXPECT_EQ(1u, service_->extensions()->size());
1008 EXPECT_EQ("name", service_->extensions()->at(0)->name());
1009 EXPECT_EQ("description", service_->extensions()->at(0)->description());
1010}
1011
[email protected]669ee492010-06-15 17:36:571012TEST_F(ExtensionsServiceTest, InstallApps) {
[email protected]6d2e60bd2010-06-03 22:37:391013 InitializeEmptyExtensionsService();
1014 FilePath extensions_path;
1015 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1016 extensions_path = extensions_path.AppendASCII("extensions");
1017
1018 // An empty app.
1019 InstallExtension(extensions_path.AppendASCII("app1.crx"), true);
1020 int pref_count = 0;
1021 ValidatePrefKeyCount(++pref_count);
1022 ValidateIntegerPref(app_crx, L"state", Extension::ENABLED);
1023 ValidateIntegerPref(app_crx, L"location", Extension::INTERNAL);
1024
1025 // Another app with non-overlapping extent. Should succeed.
1026 InstallExtension(extensions_path.AppendASCII("app2.crx"), true);
1027 ValidatePrefKeyCount(++pref_count);
1028
1029 // A third app whose extent overlaps the first. Should fail.
1030 InstallExtension(extensions_path.AppendASCII("app3.crx"), false);
1031 ValidatePrefKeyCount(pref_count);
1032}
1033
[email protected]894bb502009-05-21 22:39:571034// Test that when an extension version is reinstalled, nothing happens.
1035TEST_F(ExtensionsServiceTest, Reinstall) {
[email protected]a9b00ac2009-06-25 21:03:231036 InitializeEmptyExtensionsService();
[email protected]894bb502009-05-21 22:39:571037 FilePath extensions_path;
1038 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1039 extensions_path = extensions_path.AppendASCII("extensions");
1040
1041 // A simple extension that should install without error.
1042 FilePath path = extensions_path.AppendASCII("good.crx");
1043 service_->InstallExtension(path);
1044 loop_.RunAllPending();
1045
1046 ASSERT_TRUE(installed_);
1047 ASSERT_EQ(1u, loaded_.size());
1048 ASSERT_EQ(0u, GetErrors().size());
[email protected]25b34332009-06-05 21:53:191049 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181050 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
1051 ValidateIntegerPref(good_crx, L"location", Extension::INTERNAL);
[email protected]894bb502009-05-21 22:39:571052
1053 installed_ = NULL;
1054 loaded_.clear();
1055 ExtensionErrorReporter::GetInstance()->ClearErrors();
1056
[email protected]ca3dbf52010-05-19 22:27:061057 // Reinstall the same version, it should overwrite the previous one.
[email protected]894bb502009-05-21 22:39:571058 service_->InstallExtension(path);
1059 loop_.RunAllPending();
1060
[email protected]ca3dbf52010-05-19 22:27:061061 ASSERT_TRUE(installed_);
1062 ASSERT_EQ(1u, loaded_.size());
[email protected]894bb502009-05-21 22:39:571063 ASSERT_EQ(0u, GetErrors().size());
[email protected]25b34332009-06-05 21:53:191064 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181065 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
1066 ValidateIntegerPref(good_crx, L"location", Extension::INTERNAL);
[email protected]894bb502009-05-21 22:39:571067}
1068
[email protected]fbcc40302009-06-12 20:45:451069// Test upgrading a signed extension.
1070TEST_F(ExtensionsServiceTest, UpgradeSignedGood) {
[email protected]a9b00ac2009-06-25 21:03:231071 InitializeEmptyExtensionsService();
[email protected]fbcc40302009-06-12 20:45:451072 FilePath extensions_path;
1073 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1074 extensions_path = extensions_path.AppendASCII("extensions");
1075
1076 FilePath path = extensions_path.AppendASCII("good.crx");
1077 service_->InstallExtension(path);
1078 loop_.RunAllPending();
1079
1080 ASSERT_TRUE(installed_);
1081 ASSERT_EQ(1u, loaded_.size());
[email protected]9f1087e2009-06-15 17:29:321082 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
[email protected]fbcc40302009-06-12 20:45:451083 ASSERT_EQ(0u, GetErrors().size());
1084
1085 // Upgrade to version 2.0
1086 path = extensions_path.AppendASCII("good2.crx");
1087 service_->InstallExtension(path);
1088 loop_.RunAllPending();
1089
1090 ASSERT_TRUE(installed_);
[email protected]9f1087e2009-06-15 17:29:321091 ASSERT_EQ(1u, loaded_.size());
1092 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
[email protected]fbcc40302009-06-12 20:45:451093 ASSERT_EQ(0u, GetErrors().size());
1094}
1095
1096// Test upgrading a signed extension with a bad signature.
1097TEST_F(ExtensionsServiceTest, UpgradeSignedBad) {
[email protected]a9b00ac2009-06-25 21:03:231098 InitializeEmptyExtensionsService();
[email protected]fbcc40302009-06-12 20:45:451099 FilePath extensions_path;
1100 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1101 extensions_path = extensions_path.AppendASCII("extensions");
1102
1103 FilePath path = extensions_path.AppendASCII("good.crx");
1104 service_->InstallExtension(path);
1105 loop_.RunAllPending();
1106
1107 ASSERT_TRUE(installed_);
1108 ASSERT_EQ(1u, loaded_.size());
1109 ASSERT_EQ(0u, GetErrors().size());
1110 installed_ = NULL;
1111
1112 // Try upgrading with a bad signature. This should fail during the unpack,
1113 // because the key will not match the signature.
1114 path = extensions_path.AppendASCII("good2_bad_signature.crx");
1115 service_->InstallExtension(path);
1116 loop_.RunAllPending();
1117
1118 ASSERT_FALSE(installed_);
1119 ASSERT_EQ(1u, loaded_.size());
1120 ASSERT_EQ(1u, GetErrors().size());
1121}
1122
[email protected]e957fe52009-06-23 16:51:051123// Test a normal update via the UpdateExtension API
1124TEST_F(ExtensionsServiceTest, UpdateExtension) {
[email protected]a9b00ac2009-06-25 21:03:231125 InitializeEmptyExtensionsService();
[email protected]e957fe52009-06-23 16:51:051126 FilePath extensions_path;
1127 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1128 extensions_path = extensions_path.AppendASCII("extensions");
1129
1130 FilePath path = extensions_path.AppendASCII("good.crx");
1131
1132 InstallExtension(path, true);
1133 Extension* good = service_->extensions()->at(0);
1134 ASSERT_EQ("1.0.0.0", good->VersionString());
1135 ASSERT_EQ(good_crx, good->id());
1136
1137 path = extensions_path.AppendASCII("good2.crx");
[email protected]aa142702010-03-26 01:26:331138 UpdateExtension(good_crx, path, true, true, true);
[email protected]e957fe52009-06-23 16:51:051139 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
1140}
1141
1142// Test updating a not-already-installed extension - this should fail
1143TEST_F(ExtensionsServiceTest, UpdateNotInstalledExtension) {
[email protected]a9b00ac2009-06-25 21:03:231144 InitializeEmptyExtensionsService();
[email protected]e957fe52009-06-23 16:51:051145 FilePath extensions_path;
1146 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1147 extensions_path = extensions_path.AppendASCII("extensions");
1148
1149 FilePath path = extensions_path.AppendASCII("good.crx");
[email protected]aa142702010-03-26 01:26:331150 UpdateExtension(good_crx, path, true, false, true);
[email protected]e957fe52009-06-23 16:51:051151 loop_.RunAllPending();
1152
1153 ASSERT_EQ(0u, service_->extensions()->size());
1154 ASSERT_FALSE(installed_);
1155 ASSERT_EQ(0u, loaded_.size());
1156}
1157
1158// Makes sure you can't downgrade an extension via UpdateExtension
1159TEST_F(ExtensionsServiceTest, UpdateWillNotDowngrade) {
[email protected]a9b00ac2009-06-25 21:03:231160 InitializeEmptyExtensionsService();
[email protected]e957fe52009-06-23 16:51:051161 FilePath extensions_path;
1162 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1163 extensions_path = extensions_path.AppendASCII("extensions");
1164
1165 FilePath path = extensions_path.AppendASCII("good2.crx");
1166
1167 InstallExtension(path, true);
1168 Extension* good = service_->extensions()->at(0);
1169 ASSERT_EQ("1.0.0.1", good->VersionString());
1170 ASSERT_EQ(good_crx, good->id());
1171
1172 // Change path from good2.crx -> good.crx
1173 path = extensions_path.AppendASCII("good.crx");
[email protected]aa142702010-03-26 01:26:331174 UpdateExtension(good_crx, path, false, false, true);
[email protected]e957fe52009-06-23 16:51:051175 ASSERT_EQ("1.0.0.1", service_->extensions()->at(0)->VersionString());
1176}
1177
1178// Make sure calling update with an identical version does nothing
1179TEST_F(ExtensionsServiceTest, UpdateToSameVersionIsNoop) {
[email protected]a9b00ac2009-06-25 21:03:231180 InitializeEmptyExtensionsService();
[email protected]e957fe52009-06-23 16:51:051181 FilePath extensions_path;
1182 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1183 extensions_path = extensions_path.AppendASCII("extensions");
1184
1185 FilePath path = extensions_path.AppendASCII("good.crx");
1186
1187 InstallExtension(path, true);
1188 Extension* good = service_->extensions()->at(0);
1189 ASSERT_EQ(good_crx, good->id());
[email protected]aa142702010-03-26 01:26:331190 UpdateExtension(good_crx, path, false, false, false);
1191}
1192
1193// Test adding a pending extension.
1194TEST_F(ExtensionsServiceTest, AddPendingExtension) {
1195 InitializeEmptyExtensionsService();
1196
1197 const std::string kFakeId("fake-id");
1198 const GURL kFakeUpdateURL("http:://fake.update/url");
1199 scoped_ptr<Version> fake_version(Version::GetVersionFromString("4.3.2.1"));
1200 ASSERT_TRUE(fake_version.get());
1201 const bool kFakeIsTheme(false);
1202 const bool kFakeInstallSilently(true);
1203
1204 service_->AddPendingExtension(kFakeId, kFakeUpdateURL,
1205 *fake_version, kFakeIsTheme,
1206 kFakeInstallSilently);
1207 PendingExtensionMap::const_iterator it =
1208 service_->pending_extensions().find(kFakeId);
1209 ASSERT_TRUE(it != service_->pending_extensions().end());
1210 EXPECT_EQ(kFakeUpdateURL, it->second.update_url);
1211 EXPECT_EQ(kFakeIsTheme, it->second.is_theme);
1212 EXPECT_EQ(kFakeInstallSilently, it->second.install_silently);
1213 EXPECT_TRUE(it->second.version.Equals(*fake_version));
1214}
1215
[email protected]aa142702010-03-26 01:26:331216namespace {
1217const char kGoodId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
1218const char kGoodUpdateURL[] = "http://good.update/url";
1219const bool kGoodIsTheme = false;
1220const bool kGoodInstallSilently = true;
1221const char kGoodVersion[] = "1.2.3.4";
1222} // namespace
1223
1224// Test updating a pending extension.
1225TEST_F(ExtensionsServiceTest, UpdatePendingExtension) {
1226 InitializeEmptyExtensionsService();
1227 scoped_ptr<Version> good_version(
1228 Version::GetVersionFromString(kGoodVersion));
1229 ASSERT_TRUE(good_version.get());
1230 service_->AddPendingExtension(kGoodId, GURL(kGoodUpdateURL),
1231 *good_version, kGoodIsTheme,
1232 kGoodInstallSilently);
1233 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), kGoodId));
1234
1235 FilePath extensions_path;
1236 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1237 extensions_path = extensions_path.AppendASCII("extensions");
1238 FilePath path = extensions_path.AppendASCII("good.crx");
1239 UpdateExtension(kGoodId, path, true, true, false);
1240
1241 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId));
1242}
1243
1244// TODO(akalin): Test updating a pending extension non-silently once
1245// we can mock out ExtensionInstallUI and inject our version into
1246// UpdateExtension().
1247
1248// Test updating a pending extension with wrong is_theme.
1249TEST_F(ExtensionsServiceTest, UpdatePendingExtensionWrongIsTheme) {
1250 InitializeEmptyExtensionsService();
1251 scoped_ptr<Version> good_version(
1252 Version::GetVersionFromString(kGoodVersion));
1253 ASSERT_TRUE(good_version.get());
1254 // Add pending extension with a flipped is_theme.
1255 service_->AddPendingExtension(kGoodId, GURL(kGoodUpdateURL),
1256 *good_version, !kGoodIsTheme,
1257 kGoodInstallSilently);
1258 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), kGoodId));
1259
1260 FilePath extensions_path;
1261 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1262 extensions_path = extensions_path.AppendASCII("extensions");
1263 FilePath path = extensions_path.AppendASCII("good.crx");
1264 UpdateExtension(kGoodId, path, true, false, false);
1265
1266 // TODO(akalin): Figure out how to check that the extensions
1267 // directory is cleaned up properly in OnExtensionInstalled().
1268
1269 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), kGoodId));
1270}
1271
1272// Test updating a pending extension for one that is not pending.
1273TEST_F(ExtensionsServiceTest, UpdatePendingExtensionNotPending) {
1274 InitializeEmptyExtensionsService();
1275
1276 FilePath extensions_path;
1277 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1278 extensions_path = extensions_path.AppendASCII("extensions");
1279 FilePath path = extensions_path.AppendASCII("good.crx");
1280 UpdateExtension(kGoodId, path, true, false, false);
1281
1282 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId));
1283}
1284
1285// Test updating a pending extension for one that is already
1286// installed.
1287TEST_F(ExtensionsServiceTest, UpdatePendingExtensionAlreadyInstalled) {
1288 InitializeEmptyExtensionsService();
1289
1290 FilePath extensions_path;
1291 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1292 extensions_path = extensions_path.AppendASCII("extensions");
1293 FilePath path = extensions_path.AppendASCII("good.crx");
1294 InstallExtension(path, true);
1295 ASSERT_EQ(1u, service_->extensions()->size());
1296 Extension* good = service_->extensions()->at(0);
1297
1298 // Use AddPendingExtensionInternal() as AddPendingExtension() would
1299 // balk.
1300 service_->AddPendingExtensionInternal(
1301 good->id(), good->update_url(), *good->version(),
1302 good->IsTheme(), kGoodInstallSilently);
1303
1304 UpdateExtension(good->id(), path, true, true, false);
1305
[email protected]ca3dbf52010-05-19 22:27:061306 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId));
[email protected]e957fe52009-06-23 16:51:051307}
1308
[email protected]6b75ec32009-08-14 06:37:181309// Test pref settings for blacklist and unblacklist extensions.
1310TEST_F(ExtensionsServiceTest, SetUnsetBlacklistInPrefs) {
1311 InitializeEmptyExtensionsService();
1312 std::vector<std::string> blacklist;
1313 blacklist.push_back(good0);
1314 blacklist.push_back("invalid_id"); // an invalid id
1315 blacklist.push_back(good1);
1316 service_->UpdateExtensionBlacklist(blacklist);
1317 // Make sure pref is updated
1318 loop_.RunAllPending();
1319
1320 // blacklist is set for good0,1,2
1321 ValidateBooleanPref(good0, L"blacklist", true);
1322 ValidateBooleanPref(good1, L"blacklist", true);
1323 // invalid_id should not be inserted to pref.
1324 EXPECT_FALSE(IsPrefExist("invalid_id", L"blacklist"));
1325
1326 // remove good1, add good2
1327 blacklist.pop_back();
1328 blacklist.push_back(good2);
1329
1330 service_->UpdateExtensionBlacklist(blacklist);
1331 // only good0 and good1 should be set
1332 ValidateBooleanPref(good0, L"blacklist", true);
1333 EXPECT_FALSE(IsPrefExist(good1, L"blacklist"));
1334 ValidateBooleanPref(good2, L"blacklist", true);
1335 EXPECT_FALSE(IsPrefExist("invalid_id", L"blacklist"));
1336}
1337
1338// Unload installed extension from blacklist.
1339TEST_F(ExtensionsServiceTest, UnloadBlacklistedExtension) {
1340 InitializeEmptyExtensionsService();
1341 FilePath extensions_path;
1342 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1343 extensions_path = extensions_path.AppendASCII("extensions");
1344
1345 FilePath path = extensions_path.AppendASCII("good.crx");
1346
1347 InstallExtension(path, true);
1348 Extension* good = service_->extensions()->at(0);
1349 EXPECT_EQ(good_crx, good->id());
[email protected]aa142702010-03-26 01:26:331350 UpdateExtension(good_crx, path, false, false, false);
[email protected]6b75ec32009-08-14 06:37:181351
1352 std::vector<std::string> blacklist;
1353 blacklist.push_back(good_crx);
1354 service_->UpdateExtensionBlacklist(blacklist);
1355 // Make sure pref is updated
1356 loop_.RunAllPending();
1357
1358 // Now, the good_crx is blacklisted.
1359 ValidateBooleanPref(good_crx, L"blacklist", true);
1360 EXPECT_EQ(0u, service_->extensions()->size());
1361
1362 // Remove good_crx from blacklist
1363 blacklist.pop_back();
1364 service_->UpdateExtensionBlacklist(blacklist);
1365 // Make sure pref is updated
1366 loop_.RunAllPending();
1367 // blacklist value should not be set for good_crx
1368 EXPECT_FALSE(IsPrefExist(good_crx, L"blacklist"));
1369}
1370
1371// Unload installed extension from blacklist.
1372TEST_F(ExtensionsServiceTest, BlacklistedExtensionWillNotInstall) {
1373 InitializeEmptyExtensionsService();
1374 std::vector<std::string> blacklist;
1375 blacklist.push_back(good_crx);
1376 service_->UpdateExtensionBlacklist(blacklist);
1377 // Make sure pref is updated
1378 loop_.RunAllPending();
1379
1380 // Now, the good_crx is blacklisted.
1381 ValidateBooleanPref(good_crx, L"blacklist", true);
1382
1383 // We can not install good_crx.
1384 FilePath extensions_path;
1385 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1386 extensions_path = extensions_path.AppendASCII("extensions");
1387 FilePath path = extensions_path.AppendASCII("good.crx");
1388 service_->InstallExtension(path);
1389 loop_.RunAllPending();
1390 EXPECT_EQ(0u, service_->extensions()->size());
1391 ValidateBooleanPref(good_crx, L"blacklist", true);
1392}
1393
1394// Test loading extensions from the profile directory, except
1395// blacklisted ones.
1396TEST_F(ExtensionsServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) {
1397 // Initialize the test dir with a good Preferences/extensions.
1398 FilePath source_install_dir;
1399 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir));
1400 source_install_dir = source_install_dir
1401 .AppendASCII("extensions")
1402 .AppendASCII("good")
1403 .AppendASCII("Extensions");
1404 FilePath pref_path = source_install_dir
1405 .DirName()
1406 .AppendASCII("Preferences");
1407 InitializeInstalledExtensionsService(pref_path, source_install_dir);
1408
1409 // Blacklist good0.
1410 std::vector<std::string> blacklist;
1411 blacklist.push_back(good0);
1412 service_->UpdateExtensionBlacklist(blacklist);
1413 // Make sure pref is updated
1414 loop_.RunAllPending();
1415
1416 ValidateBooleanPref(good0, L"blacklist", true);
1417
1418 // Load extensions.
1419 service_->Init();
1420 loop_.RunAllPending();
1421
1422 std::vector<std::string> errors = GetErrors();
1423 for (std::vector<std::string>::iterator err = errors.begin();
1424 err != errors.end(); ++err) {
1425 LOG(ERROR) << *err;
1426 }
[email protected]d7b36dc2009-10-29 21:47:401427 ASSERT_EQ(2u, loaded_.size());
[email protected]6b75ec32009-08-14 06:37:181428
1429 EXPECT_NE(std::string(good0), loaded_[0]->id());
1430 EXPECT_NE(std::string(good0), loaded_[1]->id());
1431}
1432
[email protected]894bb502009-05-21 22:39:571433// Tests uninstalling normal extensions
[email protected]631cf822009-05-15 07:01:251434TEST_F(ExtensionsServiceTest, UninstallExtension) {
[email protected]a9b00ac2009-06-25 21:03:231435 InitializeEmptyExtensionsService();
[email protected]631cf822009-05-15 07:01:251436 FilePath extensions_path;
1437 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1438 extensions_path = extensions_path.AppendASCII("extensions");
1439
[email protected]4f313d52009-05-21 00:42:291440 // A simple extension that should install without error.
[email protected]894bb502009-05-21 22:39:571441 FilePath path = extensions_path.AppendASCII("good.crx");
[email protected]d2d89d82009-06-08 21:01:531442 InstallExtension(path, true);
[email protected]631cf822009-05-15 07:01:251443
1444 // The directory should be there now.
[email protected]25b34332009-06-05 21:53:191445 const char* extension_id = good_crx;
[email protected]a9b00ac2009-06-25 21:03:231446 FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id);
[email protected]631cf822009-05-15 07:01:251447 EXPECT_TRUE(file_util::PathExists(extension_path));
1448
[email protected]25b34332009-06-05 21:53:191449 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181450 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
1451 ValidateIntegerPref(good_crx, L"location", Extension::INTERNAL);
[email protected]25b34332009-06-05 21:53:191452
[email protected]894bb502009-05-21 22:39:571453 // Uninstall it.
[email protected]27b985d2009-06-25 17:53:151454 service_->UninstallExtension(extension_id, false);
[email protected]902f7cd2009-05-22 19:02:191455 total_successes_ = 0;
[email protected]894bb502009-05-21 22:39:571456
1457 // We should get an unload notification.
1458 ASSERT_TRUE(unloaded_id_.length());
1459 EXPECT_EQ(extension_id, unloaded_id_);
1460
[email protected]9f1087e2009-06-15 17:29:321461 ValidatePrefKeyCount(0);
[email protected]25b34332009-06-05 21:53:191462
[email protected]894bb502009-05-21 22:39:571463 // The extension should not be in the service anymore.
[email protected]61b411612009-11-10 23:17:411464 ASSERT_FALSE(service_->GetExtensionById(extension_id, false));
[email protected]894bb502009-05-21 22:39:571465 loop_.RunAllPending();
1466
1467 // The directory should be gone.
[email protected]631cf822009-05-15 07:01:251468 EXPECT_FALSE(file_util::PathExists(extension_path));
[email protected]631cf822009-05-15 07:01:251469}
1470
[email protected]c10da4b02010-03-25 14:38:321471// Verifies extension state is removed upon uninstall
1472TEST_F(ExtensionsServiceTest, ClearExtensionData) {
1473 InitializeEmptyExtensionsService();
1474
1475 // Load a test extension.
1476 FilePath path;
1477 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
1478 path = path.AppendASCII("extensions");
1479 path = path.AppendASCII("good.crx");
1480 InstallExtension(path, true);
1481 Extension* extension = service_->GetExtensionById(good_crx, false);
1482 ASSERT_TRUE(extension);
1483 GURL ext_url(extension->url());
1484 string16 origin_id =
1485 webkit_database::DatabaseUtil::GetOriginIdentifier(ext_url);
1486
1487 // Set a cookie for the extension.
1488 net::CookieMonster* cookie_monster = profile_
1489 ->GetRequestContextForExtensions()->GetCookieStore()->GetCookieMonster();
1490 ASSERT_TRUE(cookie_monster);
1491 net::CookieOptions options;
1492 cookie_monster->SetCookieWithOptions(ext_url, "dummy=value", options);
1493 net::CookieMonster::CookieList list =
1494 cookie_monster->GetAllCookiesForURL(ext_url);
1495 EXPECT_EQ(1U, list.size());
1496
1497 // Open a database.
1498 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker();
1499 string16 db_name = UTF8ToUTF16("db");
1500 string16 description = UTF8ToUTF16("db_description");
1501 int64 size;
1502 int64 available;
1503 db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size,
1504 &available);
1505 db_tracker->DatabaseClosed(origin_id, db_name);
1506 std::vector<webkit_database::OriginInfo> origins;
1507 db_tracker->GetAllOriginsInfo(&origins);
1508 EXPECT_EQ(1U, origins.size());
1509 EXPECT_EQ(origin_id, origins[0].GetOrigin());
1510
1511 // Create local storage. We only simulate this by creating the backing file
1512 // since webkit is not initialized.
1513 DOMStorageContext* context =
1514 profile_->GetWebKitContext()->dom_storage_context();
1515 FilePath lso_path = context->GetLocalStorageFilePath(origin_id);
1516 EXPECT_TRUE(file_util::CreateDirectory(lso_path.DirName()));
1517 EXPECT_EQ(0, file_util::WriteFile(lso_path, NULL, 0));
1518 EXPECT_TRUE(file_util::PathExists(lso_path));
1519
1520 // Uninstall the extension.
1521 service_->UninstallExtension(good_crx, false);
1522 loop_.RunAllPending();
1523
1524 // Check that the cookie is gone.
1525 list = cookie_monster->GetAllCookiesForURL(ext_url);
1526 EXPECT_EQ(0U, list.size());
1527
1528 // The database should have vanished as well.
1529 origins.clear();
1530 db_tracker->GetAllOriginsInfo(&origins);
1531 EXPECT_EQ(0U, origins.size());
1532
1533 // Check that the LSO file has been removed.
1534 EXPECT_FALSE(file_util::PathExists(lso_path));
1535}
1536
[email protected]894bb502009-05-21 22:39:571537// Tests loading single extensions (like --load-extension)
[email protected]3cf4f0992009-02-03 23:00:301538TEST_F(ExtensionsServiceTest, LoadExtension) {
[email protected]a9b00ac2009-06-25 21:03:231539 InitializeEmptyExtensionsService();
[email protected]3cf4f0992009-02-03 23:00:301540 FilePath extensions_path;
1541 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1542 extensions_path = extensions_path.AppendASCII("extensions");
1543
[email protected]a9b00ac2009-06-25 21:03:231544 FilePath ext1 = extensions_path
1545 .AppendASCII("good")
1546 .AppendASCII("Extensions")
[email protected]5a2721f62009-06-13 07:08:201547 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
1548 .AppendASCII("1.0.0.0");
[email protected]894bb502009-05-21 22:39:571549 service_->LoadExtension(ext1);
1550 loop_.RunAllPending();
[email protected]bb28e062009-02-27 17:19:181551 EXPECT_EQ(0u, GetErrors().size());
[email protected]894bb502009-05-21 22:39:571552 ASSERT_EQ(1u, loaded_.size());
[email protected]9f1087e2009-06-15 17:29:321553 EXPECT_EQ(Extension::LOAD, loaded_[0]->location());
1554 EXPECT_EQ(1u, service_->extensions()->size());
[email protected]3cf4f0992009-02-03 23:00:301555
[email protected]e8c729a2010-03-09 19:55:191556 ValidatePrefKeyCount(1);
[email protected]25b34332009-06-05 21:53:191557
[email protected]a9b00ac2009-06-25 21:03:231558 FilePath no_manifest = extensions_path
1559 .AppendASCII("bad")
[email protected]93fd78f42009-07-10 16:43:171560 // .AppendASCII("Extensions")
[email protected]a9b00ac2009-06-25 21:03:231561 .AppendASCII("cccccccccccccccccccccccccccccccc")
1562 .AppendASCII("1");
[email protected]894bb502009-05-21 22:39:571563 service_->LoadExtension(no_manifest);
1564 loop_.RunAllPending();
[email protected]bb28e062009-02-27 17:19:181565 EXPECT_EQ(1u, GetErrors().size());
[email protected]894bb502009-05-21 22:39:571566 ASSERT_EQ(1u, loaded_.size());
[email protected]9f1087e2009-06-15 17:29:321567 EXPECT_EQ(1u, service_->extensions()->size());
[email protected]25b34332009-06-05 21:53:191568
1569 // Test uninstall.
[email protected]894bb502009-05-21 22:39:571570 std::string id = loaded_[0]->id();
1571 EXPECT_FALSE(unloaded_id_.length());
[email protected]27b985d2009-06-25 17:53:151572 service_->UninstallExtension(id, false);
[email protected]894bb502009-05-21 22:39:571573 loop_.RunAllPending();
1574 EXPECT_EQ(id, unloaded_id_);
[email protected]9f1087e2009-06-15 17:29:321575 ASSERT_EQ(0u, loaded_.size());
1576 EXPECT_EQ(0u, service_->extensions()->size());
[email protected]3cf4f0992009-02-03 23:00:301577}
[email protected]0b344962009-03-31 04:21:451578
[email protected]894bb502009-05-21 22:39:571579// Tests that we generate IDs when they are not specified in the manifest for
1580// --load-extension.
[email protected]0b344962009-03-31 04:21:451581TEST_F(ExtensionsServiceTest, GenerateID) {
[email protected]a9b00ac2009-06-25 21:03:231582 InitializeEmptyExtensionsService();
[email protected]fbcc40302009-06-12 20:45:451583
[email protected]0b344962009-03-31 04:21:451584 FilePath extensions_path;
1585 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1586 extensions_path = extensions_path.AppendASCII("extensions");
1587
[email protected]0b344962009-03-31 04:21:451588 FilePath no_id_ext = extensions_path.AppendASCII("no_id");
[email protected]894bb502009-05-21 22:39:571589 service_->LoadExtension(no_id_ext);
1590 loop_.RunAllPending();
[email protected]0b344962009-03-31 04:21:451591 EXPECT_EQ(0u, GetErrors().size());
[email protected]894bb502009-05-21 22:39:571592 ASSERT_EQ(1u, loaded_.size());
[email protected]84ac7f32009-10-06 06:17:541593 ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id()));
[email protected]9f1087e2009-06-15 17:29:321594 EXPECT_EQ(loaded_[0]->location(), Extension::LOAD);
[email protected]0b344962009-03-31 04:21:451595
[email protected]e8c729a2010-03-09 19:55:191596 ValidatePrefKeyCount(1);
[email protected]25b34332009-06-05 21:53:191597
[email protected]84ac7f32009-10-06 06:17:541598 std::string previous_id = loaded_[0]->id();
1599
1600 // If we reload the same path, we should get the same extension ID.
[email protected]894bb502009-05-21 22:39:571601 service_->LoadExtension(no_id_ext);
1602 loop_.RunAllPending();
[email protected]84ac7f32009-10-06 06:17:541603 ASSERT_EQ(1u, loaded_.size());
1604 ASSERT_EQ(previous_id, loaded_[0]->id());
[email protected]0b344962009-03-31 04:21:451605}
[email protected]894bb502009-05-21 22:39:571606
[email protected]d55e7602009-12-16 04:20:421607void ExtensionsServiceTest::TestExternalProvider(
1608 MockExtensionProvider* provider, Extension::Location location) {
[email protected]a1257b12009-06-12 02:51:341609 // Verify that starting with no providers loads no extensions.
1610 service_->Init();
1611 loop_.RunAllPending();
1612 ASSERT_EQ(0u, loaded_.size());
1613
[email protected]a1257b12009-06-12 02:51:341614 // Register a test extension externally using the mock registry provider.
[email protected]894bb502009-05-21 22:39:571615 FilePath source_path;
1616 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path));
1617 source_path = source_path.AppendASCII("extensions").AppendASCII("good.crx");
1618
[email protected]a1257b12009-06-12 02:51:341619 // Add the extension.
[email protected]d55e7602009-12-16 04:20:421620 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
[email protected]894bb502009-05-21 22:39:571621
[email protected]9f1087e2009-06-15 17:29:321622 // Reloading extensions should find our externally registered extension
[email protected]894bb502009-05-21 22:39:571623 // and install it.
[email protected]93fd78f42009-07-10 16:43:171624 service_->CheckForExternalUpdates();
[email protected]894bb502009-05-21 22:39:571625 loop_.RunAllPending();
1626
1627 ASSERT_EQ(0u, GetErrors().size());
1628 ASSERT_EQ(1u, loaded_.size());
[email protected]d55e7602009-12-16 04:20:421629 ASSERT_EQ(location, loaded_[0]->location());
[email protected]894bb502009-05-21 22:39:571630 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
[email protected]25b34332009-06-05 21:53:191631 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181632 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
[email protected]d55e7602009-12-16 04:20:421633 ValidateIntegerPref(good_crx, L"location", location);
[email protected]894bb502009-05-21 22:39:571634
[email protected]9f1087e2009-06-15 17:29:321635 // Reload extensions without changing anything. The extension should be
[email protected]894bb502009-05-21 22:39:571636 // loaded again.
1637 loaded_.clear();
[email protected]9f1087e2009-06-15 17:29:321638 service_->ReloadExtensions();
[email protected]894bb502009-05-21 22:39:571639 loop_.RunAllPending();
1640 ASSERT_EQ(0u, GetErrors().size());
1641 ASSERT_EQ(1u, loaded_.size());
[email protected]25b34332009-06-05 21:53:191642 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181643 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
[email protected]d55e7602009-12-16 04:20:421644 ValidateIntegerPref(good_crx, L"location", location);
[email protected]e2eb43112009-05-29 21:19:541645
[email protected]894bb502009-05-21 22:39:571646 // Now update the extension with a new version. We should get upgraded.
1647 source_path = source_path.DirName().AppendASCII("good2.crx");
[email protected]d55e7602009-12-16 04:20:421648 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path);
[email protected]894bb502009-05-21 22:39:571649
1650 loaded_.clear();
[email protected]93fd78f42009-07-10 16:43:171651 service_->CheckForExternalUpdates();
[email protected]894bb502009-05-21 22:39:571652 loop_.RunAllPending();
1653 ASSERT_EQ(0u, GetErrors().size());
1654 ASSERT_EQ(1u, loaded_.size());
1655 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
[email protected]25b34332009-06-05 21:53:191656 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181657 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
[email protected]d55e7602009-12-16 04:20:421658 ValidateIntegerPref(good_crx, L"location", location);
[email protected]894bb502009-05-21 22:39:571659
[email protected]27b985d2009-06-25 17:53:151660 // Uninstall the extension and reload. Nothing should happen because the
[email protected]894bb502009-05-21 22:39:571661 // preference should prevent us from reinstalling.
1662 std::string id = loaded_[0]->id();
[email protected]27b985d2009-06-25 17:53:151663 service_->UninstallExtension(id, false);
[email protected]894bb502009-05-21 22:39:571664 loop_.RunAllPending();
1665
1666 // The extension should also be gone from the install directory.
[email protected]a9b00ac2009-06-25 21:03:231667 FilePath install_path = extensions_install_dir_.AppendASCII(id);
[email protected]894bb502009-05-21 22:39:571668 ASSERT_FALSE(file_util::PathExists(install_path));
1669
1670 loaded_.clear();
[email protected]93fd78f42009-07-10 16:43:171671 service_->CheckForExternalUpdates();
[email protected]894bb502009-05-21 22:39:571672 loop_.RunAllPending();
1673 ASSERT_EQ(0u, loaded_.size());
[email protected]25b34332009-06-05 21:53:191674 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181675 ValidateIntegerPref(good_crx, L"state", Extension::KILLBIT);
[email protected]d55e7602009-12-16 04:20:421676 ValidateIntegerPref(good_crx, L"location", location);
[email protected]25b34332009-06-05 21:53:191677
1678 // Now clear the preference and reinstall.
[email protected]6b75ec32009-08-14 06:37:181679 SetPrefInteg(good_crx, L"state", Extension::ENABLED);
[email protected]a9b00ac2009-06-25 21:03:231680 prefs_->ScheduleSavePersistentPrefs();
[email protected]25b34332009-06-05 21:53:191681
1682 loaded_.clear();
[email protected]93fd78f42009-07-10 16:43:171683 service_->CheckForExternalUpdates();
[email protected]25b34332009-06-05 21:53:191684 loop_.RunAllPending();
1685 ASSERT_EQ(1u, loaded_.size());
[email protected]25b34332009-06-05 21:53:191686 ValidatePrefKeyCount(1);
[email protected]6b75ec32009-08-14 06:37:181687 ValidateIntegerPref(good_crx, L"state", Extension::ENABLED);
[email protected]d55e7602009-12-16 04:20:421688 ValidateIntegerPref(good_crx, L"location", location);
[email protected]25b34332009-06-05 21:53:191689
[email protected]d55e7602009-12-16 04:20:421690 // Now test an externally triggered uninstall (deleting the registry key or
1691 // the pref entry).
1692 provider->RemoveExtension(good_crx);
[email protected]25b34332009-06-05 21:53:191693
1694 loaded_.clear();
[email protected]c6d82c72010-05-19 18:27:051695 service_->UnloadAllExtensions();
[email protected]27b985d2009-06-25 17:53:151696 service_->LoadAllExtensions();
[email protected]25b34332009-06-05 21:53:191697 loop_.RunAllPending();
1698 ASSERT_EQ(0u, loaded_.size());
[email protected]27b985d2009-06-25 17:53:151699 ValidatePrefKeyCount(0);
[email protected]25b34332009-06-05 21:53:191700
[email protected]27b985d2009-06-25 17:53:151701 // The extension should also be gone from the install directory.
1702 ASSERT_FALSE(file_util::PathExists(install_path));
[email protected]abe7a8942009-06-23 05:14:291703
[email protected]d55e7602009-12-16 04:20:421704 // Now test the case where user uninstalls and then the extension is removed
1705 // from the external provider.
[email protected]abe7a8942009-06-23 05:14:291706
[email protected]d55e7602009-12-16 04:20:421707 provider->UpdateOrAddExtension(good_crx, "1.0", source_path);
[email protected]93fd78f42009-07-10 16:43:171708 service_->CheckForExternalUpdates();
[email protected]abe7a8942009-06-23 05:14:291709 loop_.RunAllPending();
1710
[email protected]c1e432a2009-07-22 21:21:481711 ASSERT_EQ(1u, loaded_.size());
[email protected]c6d82c72010-05-19 18:27:051712 ASSERT_EQ(0u, GetErrors().size());
[email protected]d55e7602009-12-16 04:20:421713
1714 // User uninstalls.
1715 loaded_.clear();
1716 service_->UninstallExtension(id, false);
1717 loop_.RunAllPending();
1718 ASSERT_EQ(0u, loaded_.size());
1719
1720 // Then remove the extension from the extension provider.
1721 provider->RemoveExtension(good_crx);
1722
1723 // Should still be at 0.
1724 loaded_.clear();
1725 service_->LoadAllExtensions();
1726 loop_.RunAllPending();
1727 ASSERT_EQ(0u, loaded_.size());
1728 ValidatePrefKeyCount(1);
1729}
1730
1731// Tests the external installation feature
1732#if defined(OS_WIN)
1733TEST_F(ExtensionsServiceTest, ExternalInstallRegistry) {
1734 // This should all work, even when normal extension installation is disabled.
1735 InitializeEmptyExtensionsService();
1736 set_extensions_enabled(false);
1737
1738 // Now add providers. Extension system takes ownership of the objects.
1739 MockExtensionProvider* reg_provider =
1740 new MockExtensionProvider(Extension::EXTERNAL_REGISTRY);
1741 SetMockExternalProvider(Extension::EXTERNAL_REGISTRY, reg_provider);
1742 TestExternalProvider(reg_provider, Extension::EXTERNAL_REGISTRY);
1743}
1744#endif
1745
1746TEST_F(ExtensionsServiceTest, ExternalInstallPref) {
1747 // This should all work, even when normal extension installation is disabled.
1748 InitializeEmptyExtensionsService();
1749 set_extensions_enabled(false);
1750
1751 // Now add providers. Extension system takes ownership of the objects.
1752 MockExtensionProvider* pref_provider =
1753 new MockExtensionProvider(Extension::EXTERNAL_PREF);
1754 SetMockExternalProvider(Extension::EXTERNAL_PREF, pref_provider);
1755 TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF);
[email protected]27b985d2009-06-25 17:53:151756}
1757
1758TEST_F(ExtensionsServiceTest, ExternalPrefProvider) {
[email protected]a9b00ac2009-06-25 21:03:231759 InitializeEmptyExtensionsService();
[email protected]27b985d2009-06-25 17:53:151760 std::string json_data =
1761 "{"
1762 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
1763 "\"external_crx\": \"RandomExtension.crx\","
1764 "\"external_version\": \"1.0\""
1765 "},"
1766 "\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
1767 "\"external_crx\": \"RandomExtension2.crx\","
1768 "\"external_version\": \"2.0\""
1769 "}"
1770 "}";
1771
1772 MockProviderVisitor visitor;
1773 std::set<std::string> ignore_list;
1774 EXPECT_EQ(2, visitor.Visit(json_data, ignore_list));
1775 ignore_list.insert("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
1776 EXPECT_EQ(1, visitor.Visit(json_data, ignore_list));
1777 ignore_list.insert("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
1778 EXPECT_EQ(0, visitor.Visit(json_data, ignore_list));
1779
1780 // Use a json that contains three invalid extensions:
1781 // - One that is missing the 'external_crx' key.
1782 // - One that is missing the 'external_version' key.
1783 // - One that is specifying .. in the path.
1784 // - Plus one valid extension to make sure the json file is parsed properly.
1785 json_data =
1786 "{"
1787 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
1788 "\"external_version\": \"1.0\""
1789 "},"
1790 "\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
1791 "\"external_crx\": \"RandomExtension.crx\""
1792 "},"
1793 "\"cccccccccccccccccccccccccccccccc\": {"
1794 "\"external_crx\": \"..\\\\foo\\\\RandomExtension2.crx\","
1795 "\"external_version\": \"2.0\""
1796 "},"
1797 "\"dddddddddddddddddddddddddddddddddd\": {"
1798 "\"external_crx\": \"RandomValidExtension.crx\","
1799 "\"external_version\": \"1.0\""
1800 "}"
1801 "}";
1802 ignore_list.clear();
1803 EXPECT_EQ(1, visitor.Visit(json_data, ignore_list));
[email protected]e18236b2009-06-22 21:32:101804}
[email protected]36a784c2009-06-23 06:21:081805
[email protected]c6d474f82009-12-16 21:11:061806// Test loading good extensions from the profile directory.
1807TEST_F(ExtensionsServiceTest, LoadAndRelocalizeExtensions) {
1808 // Initialize the test dir with a good Preferences/extensions.
1809 FilePath source_install_dir;
1810 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir));
1811 source_install_dir = source_install_dir
1812 .AppendASCII("extensions")
1813 .AppendASCII("l10n");
1814 FilePath pref_path = source_install_dir.AppendASCII("Preferences");
1815 InitializeInstalledExtensionsService(pref_path, source_install_dir);
1816
1817 service_->Init();
1818 loop_.RunAllPending();
1819
1820 ASSERT_EQ(3u, loaded_.size());
1821
1822 // This was equal to "sr" on load.
1823 ValidateStringPref(loaded_[0]->id(), keys::kCurrentLocale, "en");
1824
1825 // These are untouched by re-localization.
1826 ValidateStringPref(loaded_[1]->id(), keys::kCurrentLocale, "en");
1827 EXPECT_FALSE(IsPrefExist(loaded_[1]->id(), keys::kCurrentLocale));
1828
1829 // This one starts with Serbian name, and gets re-localized into English.
1830 EXPECT_EQ("My name is simple.", loaded_[0]->name());
1831
1832 // These are untouched by re-localization.
1833 EXPECT_EQ("My name is simple.", loaded_[1]->name());
1834 EXPECT_EQ("no l10n", loaded_[2]->name());
1835}
1836
[email protected]f0488f2f2009-07-01 05:25:221837class ExtensionsReadyRecorder : public NotificationObserver {
1838 public:
1839 ExtensionsReadyRecorder() : ready_(false) {
1840 registrar_.Add(this, NotificationType::EXTENSIONS_READY,
1841 NotificationService::AllSources());
1842 }
1843
1844 void set_ready(bool value) { ready_ = value; }
1845 bool ready() { return ready_; }
1846
1847 private:
1848 virtual void Observe(NotificationType type,
1849 const NotificationSource& source,
1850 const NotificationDetails& details) {
1851 switch (type.value) {
1852 case NotificationType::EXTENSIONS_READY:
1853 ready_ = true;
1854 break;
1855 default:
1856 NOTREACHED();
1857 }
1858 }
1859
1860 NotificationRegistrar registrar_;
1861 bool ready_;
1862};
1863
[email protected]36a784c2009-06-23 06:21:081864// Test that we get enabled/disabled correctly for all the pref/command-line
[email protected]27b985d2009-06-25 17:53:151865// combinations. We don't want to derive from the ExtensionsServiceTest class
1866// for this test, so we use ExtensionsServiceTestSimple.
[email protected]f0488f2f2009-07-01 05:25:221867//
1868// Also tests that we always fire EXTENSIONS_READY, no matter whether we are
1869// enabled or not.
[email protected]27b985d2009-06-25 17:53:151870TEST(ExtensionsServiceTestSimple, Enabledness) {
[email protected]f0488f2f2009-07-01 05:25:221871 ExtensionsReadyRecorder recorder;
[email protected]36a784c2009-06-23 06:21:081872 TestingProfile profile;
1873 MessageLoop loop;
[email protected]95d29192009-10-30 01:49:061874 ChromeThread ui_thread(ChromeThread::UI, &loop);
1875 ChromeThread file_thread(ChromeThread::FILE, &loop);
[email protected]36a784c2009-06-23 06:21:081876 scoped_ptr<CommandLine> command_line;
1877 scoped_refptr<ExtensionsService> service;
[email protected]a9b00ac2009-06-25 21:03:231878 FilePath install_dir = profile.GetPath()
1879 .AppendASCII(ExtensionsService::kInstallDirectoryName);
[email protected]36a784c2009-06-23 06:21:081880
[email protected]6d60703b2009-08-29 01:29:231881 // By default, we are enabled.
[email protected]51343d5a2009-10-26 22:39:331882 command_line.reset(new CommandLine(CommandLine::ARGUMENTS_ONLY));
[email protected]a9b00ac2009-06-25 21:03:231883 service = new ExtensionsService(&profile, command_line.get(),
[email protected]95d29192009-10-30 01:49:061884 profile.GetPrefs(), install_dir, false);
[email protected]6d60703b2009-08-29 01:29:231885 EXPECT_TRUE(service->extensions_enabled());
1886 service->Init();
1887 loop.RunAllPending();
1888 EXPECT_TRUE(recorder.ready());
1889
1890 // If either the command line or pref is set, we are disabled.
1891 recorder.set_ready(false);
1892 command_line->AppendSwitch(switches::kDisableExtensions);
1893 service = new ExtensionsService(&profile, command_line.get(),
[email protected]95d29192009-10-30 01:49:061894 profile.GetPrefs(), install_dir, false);
[email protected]36a784c2009-06-23 06:21:081895 EXPECT_FALSE(service->extensions_enabled());
[email protected]f0488f2f2009-07-01 05:25:221896 service->Init();
1897 loop.RunAllPending();
1898 EXPECT_TRUE(recorder.ready());
[email protected]36a784c2009-06-23 06:21:081899
[email protected]f0488f2f2009-07-01 05:25:221900 recorder.set_ready(false);
[email protected]6d60703b2009-08-29 01:29:231901 profile.GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
[email protected]a9b00ac2009-06-25 21:03:231902 service = new ExtensionsService(&profile, command_line.get(),
[email protected]95d29192009-10-30 01:49:061903 profile.GetPrefs(), install_dir, false);
[email protected]6d60703b2009-08-29 01:29:231904 EXPECT_FALSE(service->extensions_enabled());
[email protected]f0488f2f2009-07-01 05:25:221905 service->Init();
1906 loop.RunAllPending();
1907 EXPECT_TRUE(recorder.ready());
[email protected]36a784c2009-06-23 06:21:081908
[email protected]f0488f2f2009-07-01 05:25:221909 recorder.set_ready(false);
[email protected]51343d5a2009-10-26 22:39:331910 command_line.reset(new CommandLine(CommandLine::ARGUMENTS_ONLY));
[email protected]a9b00ac2009-06-25 21:03:231911 service = new ExtensionsService(&profile, command_line.get(),
[email protected]95d29192009-10-30 01:49:061912 profile.GetPrefs(), install_dir, false);
[email protected]6d60703b2009-08-29 01:29:231913 EXPECT_FALSE(service->extensions_enabled());
[email protected]f0488f2f2009-07-01 05:25:221914 service->Init();
1915 loop.RunAllPending();
1916 EXPECT_TRUE(recorder.ready());
[email protected]36a784c2009-06-23 06:21:081917}
[email protected]24b538a2010-02-27 01:22:441918
1919// Test loading extensions that require limited and unlimited storage quotas.
1920TEST_F(ExtensionsServiceTest, StorageQuota) {
1921 InitializeEmptyExtensionsService();
1922
1923 FilePath extensions_path;
1924 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
1925 extensions_path = extensions_path.AppendASCII("extensions")
1926 .AppendASCII("storage_quota");
1927
1928 FilePath limited_quota_ext = extensions_path.AppendASCII("limited_quota")
1929 .AppendASCII("1.0");
1930 FilePath unlimited_quota_ext = extensions_path.AppendASCII("unlimited_quota")
1931 .AppendASCII("1.0");
1932 service_->LoadExtension(limited_quota_ext);
1933 service_->LoadExtension(unlimited_quota_ext);
1934 loop_.RunAllPending();
1935
1936 EXPECT_EQ(2u, loaded_.size());
1937 EXPECT_TRUE(profile_.get());
1938 EXPECT_FALSE(profile_->IsOffTheRecord());
1939
1940 // Open a database in each origin to make the tracker aware
1941 // of the existance of these origins and to get their quotas.
1942 int64 limited_quota = -1;
1943 int64 unlimited_quota = -1;
1944 string16 limited_quota_identifier =
1945 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[0]->url());
1946 string16 unlimited_quota_identifier =
1947 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[1]->url());
1948 string16 db_name = UTF8ToUTF16("db");
1949 string16 description = UTF8ToUTF16("db_description");
1950 int64 database_size;
1951 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker();
1952 db_tracker->DatabaseOpened(limited_quota_identifier, db_name, description,
1953 1, &database_size, &limited_quota);
1954 db_tracker->DatabaseClosed(limited_quota_identifier, db_name);
1955 db_tracker->DatabaseOpened(unlimited_quota_identifier, db_name, description,
1956 1, &database_size, &unlimited_quota);
1957 db_tracker->DatabaseClosed(unlimited_quota_identifier, db_name);
1958
1959 EXPECT_EQ(profile_->GetDatabaseTracker()->GetDefaultQuota(), limited_quota);
1960 EXPECT_EQ(kint64max, unlimited_quota);
1961}
[email protected]1952c7d2010-03-04 23:48:341962
1963// Tests ExtensionsService::register_component_extension().
1964TEST_F(ExtensionsServiceTest, ComponentExtensions) {
1965 InitializeEmptyExtensionsService();
1966
1967 FilePath path;
1968 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
1969 path = path.AppendASCII("extensions")
1970 .AppendASCII("good")
1971 .AppendASCII("Extensions")
1972 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
1973 .AppendASCII("1.0.0.0");
1974
1975 std::string manifest;
1976 ASSERT_TRUE(file_util::ReadFileToString(
1977 path.Append(Extension::kManifestFilename), &manifest));
1978
1979 service_->register_component_extension(
1980 ExtensionsService::ComponentExtensionInfo(manifest, path));
1981 service_->Init();
1982
1983 // Note that we do not pump messages -- the extension should be loaded
1984 // immediately.
1985
1986 EXPECT_EQ(0u, GetErrors().size());
1987 ASSERT_EQ(1u, loaded_.size());
1988 EXPECT_EQ(Extension::COMPONENT, loaded_[0]->location());
1989 EXPECT_EQ(1u, service_->extensions()->size());
1990
1991 // Component extensions shouldn't get recourded in the prefs.
1992 ValidatePrefKeyCount(0);
1993
1994 // Reload all extensions, and make sure it comes back.
1995 std::string extension_id = service_->extensions()->at(0)->id();
1996 loaded_.clear();
1997 service_->ReloadExtensions();
1998 ASSERT_EQ(1u, service_->extensions()->size());
1999 EXPECT_EQ(extension_id, service_->extensions()->at(0)->id());
2000}