blob: bf6c949c7e0778f344f2c0b279a6c1517ab65026 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// Copyright (c) 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_service_unittest.h"
6
7#include <algorithm>
8#include <set>
9#include <vector>
10
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "base/at_exit.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "base/basictypes.h"
13#include "base/bind.h"
14#include "base/command_line.h"
15#include "base/file_util.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010016#include "base/files/file_enumerator.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "base/files/scoped_temp_dir.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "base/json/json_file_value_serializer.h"
19#include "base/json/json_reader.h"
20#include "base/json/json_string_value_serializer.h"
21#include "base/memory/scoped_ptr.h"
22#include "base/memory/weak_ptr.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010023#include "base/message_loop/message_loop.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000024#include "base/path_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000025#include "base/stl_util.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010026#include "base/strings/string16.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027#include "base/strings/string_number_conversions.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010028#include "base/strings/string_util.h"
29#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000030#include "base/version.h"
31#include "chrome/browser/browser_process.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010032#include "chrome/browser/chrome_notification_types.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000033#include "chrome/browser/extensions/app_sync_data.h"
34#include "chrome/browser/extensions/component_loader.h"
35#include "chrome/browser/extensions/crx_installer.h"
36#include "chrome/browser/extensions/default_apps.h"
37#include "chrome/browser/extensions/extension_creator.h"
38#include "chrome/browser/extensions/extension_error_reporter.h"
39#include "chrome/browser/extensions/extension_error_ui.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010040#include "chrome/browser/extensions/extension_notification_observer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000041#include "chrome/browser/extensions/extension_service.h"
42#include "chrome/browser/extensions/extension_sorting.h"
43#include "chrome/browser/extensions/extension_special_storage_policy.h"
44#include "chrome/browser/extensions/extension_sync_data.h"
45#include "chrome/browser/extensions/extension_system.h"
46#include "chrome/browser/extensions/external_install_ui.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000047#include "chrome/browser/extensions/external_policy_loader.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000048#include "chrome/browser/extensions/external_pref_loader.h"
49#include "chrome/browser/extensions/external_provider_impl.h"
50#include "chrome/browser/extensions/external_provider_interface.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010051#include "chrome/browser/extensions/install_observer.h"
52#include "chrome/browser/extensions/install_tracker.h"
53#include "chrome/browser/extensions/install_tracker_factory.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000054#include "chrome/browser/extensions/installed_loader.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000055#include "chrome/browser/extensions/management_policy.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000056#include "chrome/browser/extensions/pack_extension_job.h"
57#include "chrome/browser/extensions/pending_extension_info.h"
58#include "chrome/browser/extensions/pending_extension_manager.h"
59#include "chrome/browser/extensions/test_extension_system.h"
60#include "chrome/browser/extensions/test_management_policy.h"
61#include "chrome/browser/extensions/unpacked_installer.h"
62#include "chrome/browser/extensions/updater/extension_updater.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000063#include "chrome/browser/prefs/browser_prefs.h"
64#include "chrome/browser/prefs/pref_service_mock_builder.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065#include "chrome/browser/prefs/pref_service_syncable.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000066#include "chrome/browser/prefs/scoped_user_pref_update.h"
67#include "chrome/common/chrome_constants.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000068#include "chrome/common/chrome_paths.h"
69#include "chrome/common/chrome_switches.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070#include "chrome/common/extensions/api/plugins/plugins_handler.h"
71#include "chrome/common/extensions/background_info.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000072#include "chrome/common/extensions/extension.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010073#include "chrome/common/extensions/extension_builder.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000074#include "chrome/common/extensions/extension_l10n_util.h"
75#include "chrome/common/extensions/extension_manifest_constants.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010076#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000077#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
78#include "chrome/common/extensions/manifest_url_handler.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000079#include "chrome/common/extensions/permissions/permission_set.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010080#include "chrome/common/extensions/value_builder.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000081#include "chrome/common/pref_names.h"
82#include "chrome/common/url_constants.h"
83#include "chrome/test/base/testing_profile.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000084#include "components/user_prefs/pref_registry_syncable.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000085#include "content/public/browser/dom_storage_context.h"
86#include "content/public/browser/gpu_data_manager.h"
87#include "content/public/browser/indexed_db_context.h"
88#include "content/public/browser/notification_registrar.h"
89#include "content/public/browser/notification_service.h"
90#include "content/public/browser/plugin_service.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010091#include "content/public/browser/render_process_host.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000092#include "content/public/browser/storage_partition.h"
93#include "content/public/common/content_constants.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000094#include "content/public/test/test_browser_thread.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010095#include "content/public/test/test_utils.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000096#include "extensions/common/constants.h"
97#include "extensions/common/extension_resource.h"
98#include "extensions/common/url_pattern.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010099#include "gpu/config/gpu_info.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000100#include "grit/browser_resources.h"
101#include "net/cookies/canonical_cookie.h"
102#include "net/cookies/cookie_monster.h"
103#include "net/cookies/cookie_options.h"
104#include "net/url_request/url_request_context.h"
105#include "net/url_request/url_request_context_getter.h"
106#include "sync/api/string_ordinal.h"
107#include "sync/api/sync_error_factory.h"
108#include "sync/api/sync_error_factory_mock.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100109#include "sync/api/syncable_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000110#include "sync/protocol/app_specifics.pb.h"
111#include "sync/protocol/extension_specifics.pb.h"
112#include "sync/protocol/sync.pb.h"
113#include "testing/gtest/include/gtest/gtest.h"
114#include "testing/platform_test.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100115#include "url/gurl.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100116#include "webkit/browser/database/database_tracker.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100117#include "webkit/browser/quota/quota_manager.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100118#include "webkit/common/database/database_identifier.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000119
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000120#if defined(OS_CHROMEOS)
121#include "chrome/browser/chromeos/extensions/install_limiter.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100122#include "chrome/browser/chromeos/login/user_manager.h"
123#include "chrome/browser/chromeos/settings/cros_settings.h"
124#include "chrome/browser/chromeos/settings/device_settings_service.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000125#endif
126
Ben Murdocheb525c52013-07-10 11:40:50 +0100127using base::DictionaryValue;
128using base::ListValue;
129using base::Value;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000130using content::BrowserContext;
131using content::BrowserThread;
132using content::DOMStorageContext;
133using content::IndexedDBContext;
134using content::PluginService;
135using extensions::APIPermission;
136using extensions::APIPermissionSet;
137using extensions::CrxInstaller;
138using extensions::Extension;
139using extensions::ExtensionCreator;
140using extensions::ExtensionPrefs;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000141using extensions::ExtensionResource;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000142using extensions::ExtensionSystem;
143using extensions::FeatureSwitch;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000144using extensions::Manifest;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000145using extensions::PermissionSet;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100146using extensions::TestExtensionSystem;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000147using extensions::URLPatternSet;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000148
149namespace keys = extension_manifest_keys;
150
151namespace {
152
153// Extension ids used during testing.
154const char* const all_zero = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
155const char* const zero_n_one = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
156const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj";
157const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk";
158const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
159const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
160const char* const hosted_app = "kbmnembihfiondgfjekmnmcbddelicoi";
161const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln";
162const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
163const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
164const char* const permissions_crx = "eagpmdpfmaekmmcejjbmjoecnejeiiin";
165const char* const unpacked = "cbcdidchbppangcjoddlpdjlenngjldk";
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100166const char* const updates_from_webstore = "akjooamlhcgeopfifcmlggaebeocgokj";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000167
168struct ExtensionsOrder {
Ben Murdocheb525c52013-07-10 11:40:50 +0100169 bool operator()(const scoped_refptr<const Extension>& a,
170 const scoped_refptr<const Extension>& b) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000171 return a->name() < b->name();
172 }
173};
174
175static std::vector<string16> GetErrors() {
176 const std::vector<string16>* errors =
177 ExtensionErrorReporter::GetInstance()->GetErrors();
178 std::vector<string16> ret_val;
179
180 for (std::vector<string16>::const_iterator iter = errors->begin();
181 iter != errors->end(); ++iter) {
182 std::string utf8_error = UTF16ToUTF8(*iter);
183 if (utf8_error.find(".svn") == std::string::npos) {
184 ret_val.push_back(*iter);
185 }
186 }
187
188 // The tests rely on the errors being in a certain order, which can vary
189 // depending on how filesystem iteration works.
190 std::stable_sort(ret_val.begin(), ret_val.end());
191
192 return ret_val;
193}
194
195static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
196 int schemes = URLPattern::SCHEME_ALL;
197 extent->AddPattern(URLPattern(schemes, pattern));
198}
199
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000200base::FilePath GetTemporaryFile() {
201 base::FilePath temp_file;
202 CHECK(file_util::CreateTemporaryFile(&temp_file));
203 return temp_file;
204}
205
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100206
207bool WaitForCountNotificationsCallback(int *count) {
208 return --(*count) == 0;
209}
210
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000211} // namespace
212
213class MockExtensionProvider : public extensions::ExternalProviderInterface {
214 public:
215 MockExtensionProvider(
216 VisitorInterface* visitor,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000217 Manifest::Location location)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000218 : location_(location), visitor_(visitor), visit_count_(0) {
219 }
220
221 virtual ~MockExtensionProvider() {}
222
223 void UpdateOrAddExtension(const std::string& id,
224 const std::string& version,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000225 const base::FilePath& path) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000226 extension_map_[id] = std::make_pair(version, path);
227 }
228
229 void RemoveExtension(const std::string& id) {
230 extension_map_.erase(id);
231 }
232
233 // ExternalProvider implementation:
234 virtual void VisitRegisteredExtension() OVERRIDE {
235 visit_count_++;
236 for (DataMap::const_iterator i = extension_map_.begin();
237 i != extension_map_.end(); ++i) {
238 Version version(i->second.first);
239
240 visitor_->OnExternalExtensionFileFound(
241 i->first, &version, i->second.second, location_,
242 Extension::NO_FLAGS, false);
243 }
244 visitor_->OnExternalProviderReady(this);
245 }
246
247 virtual bool HasExtension(const std::string& id) const OVERRIDE {
248 return extension_map_.find(id) != extension_map_.end();
249 }
250
251 virtual bool GetExtensionDetails(
252 const std::string& id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000253 Manifest::Location* location,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000254 scoped_ptr<Version>* version) const OVERRIDE {
255 DataMap::const_iterator it = extension_map_.find(id);
256 if (it == extension_map_.end())
257 return false;
258
259 if (version)
260 version->reset(new Version(it->second.first));
261
262 if (location)
263 *location = location_;
264
265 return true;
266 }
267
268 virtual bool IsReady() const OVERRIDE {
269 return true;
270 }
271
272 virtual void ServiceShutdown() OVERRIDE {
273 }
274
275 int visit_count() const { return visit_count_; }
276 void set_visit_count(int visit_count) {
277 visit_count_ = visit_count;
278 }
279
280 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000281 typedef std::map< std::string, std::pair<std::string, base::FilePath> >
282 DataMap;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000283 DataMap extension_map_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000284 Manifest::Location location_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000285 VisitorInterface* visitor_;
286
287 // visit_count_ tracks the number of calls to VisitRegisteredExtension().
288 // Mutable because it must be incremented on each call to
289 // VisitRegisteredExtension(), which must be a const method to inherit
290 // from the class being mocked.
291 mutable int visit_count_;
292
293 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
294};
295
296class MockProviderVisitor
297 : public extensions::ExternalProviderInterface::VisitorInterface {
298 public:
299 // The provider will return |fake_base_path| from
300 // GetBaseCrxFilePath(). User can test the behavior with
301 // and without an empty path using this parameter.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000302 explicit MockProviderVisitor(base::FilePath fake_base_path)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000303 : ids_found_(0),
304 fake_base_path_(fake_base_path),
305 expected_creation_flags_(Extension::NO_FLAGS) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100306 profile_.reset(new TestingProfile);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000307 }
308
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000309 MockProviderVisitor(base::FilePath fake_base_path,
310 int expected_creation_flags)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000311 : ids_found_(0),
312 fake_base_path_(fake_base_path),
313 expected_creation_flags_(expected_creation_flags) {
314 }
315
316 int Visit(const std::string& json_data) {
317 // Give the test json file to the provider for parsing.
318 provider_.reset(new extensions::ExternalProviderImpl(
319 this,
320 new extensions::ExternalTestingLoader(json_data, fake_base_path_),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100321 profile_.get(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000322 Manifest::EXTERNAL_PREF,
323 Manifest::EXTERNAL_PREF_DOWNLOAD,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000324 Extension::NO_FLAGS));
325
326 // We also parse the file into a dictionary to compare what we get back
327 // from the provider.
328 JSONStringValueSerializer serializer(json_data);
329 Value* json_value = serializer.Deserialize(NULL, NULL);
330
331 if (!json_value || !json_value->IsType(Value::TYPE_DICTIONARY)) {
332 NOTREACHED() << "Unable to deserialize json data";
333 return -1;
334 } else {
335 DictionaryValue* external_extensions =
336 static_cast<DictionaryValue*>(json_value);
337 prefs_.reset(external_extensions);
338 }
339
340 // Reset our counter.
341 ids_found_ = 0;
342 // Ask the provider to look up all extensions and return them.
343 provider_->VisitRegisteredExtension();
344
345 return ids_found_;
346 }
347
348 virtual bool OnExternalExtensionFileFound(const std::string& id,
349 const Version* version,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000350 const base::FilePath& path,
351 Manifest::Location unused,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000352 int creation_flags,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000353 bool mark_acknowledged) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000354 EXPECT_EQ(expected_creation_flags_, creation_flags);
355
356 ++ids_found_;
357 DictionaryValue* pref;
358 // This tests is to make sure that the provider only notifies us of the
359 // values we gave it. So if the id we doesn't exist in our internal
360 // dictionary then something is wrong.
361 EXPECT_TRUE(prefs_->GetDictionary(id, &pref))
362 << "Got back ID (" << id.c_str() << ") we weren't expecting";
363
364 EXPECT_TRUE(path.IsAbsolute());
365 if (!fake_base_path_.empty())
366 EXPECT_TRUE(fake_base_path_.IsParent(path));
367
368 if (pref) {
369 EXPECT_TRUE(provider_->HasExtension(id));
370
371 // Ask provider if the extension we got back is registered.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000372 Manifest::Location location = Manifest::INVALID_LOCATION;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000373 scoped_ptr<Version> v1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000374 base::FilePath crx_path;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000375
376 EXPECT_TRUE(provider_->GetExtensionDetails(id, NULL, &v1));
377 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
378
379 scoped_ptr<Version> v2;
380 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location, &v2));
381 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
382 EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000383 EXPECT_EQ(Manifest::EXTERNAL_PREF, location);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000384
385 // Remove it so we won't count it ever again.
386 prefs_->Remove(id, NULL);
387 }
388 return true;
389 }
390
391 virtual bool OnExternalExtensionUpdateUrlFound(
392 const std::string& id, const GURL& update_url,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000393 Manifest::Location location) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000394 ++ids_found_;
395 DictionaryValue* pref;
396 // This tests is to make sure that the provider only notifies us of the
397 // values we gave it. So if the id we doesn't exist in our internal
398 // dictionary then something is wrong.
399 EXPECT_TRUE(prefs_->GetDictionary(id, &pref))
400 << L"Got back ID (" << id.c_str() << ") we weren't expecting";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000401 EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, location);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000402
403 if (pref) {
404 EXPECT_TRUE(provider_->HasExtension(id));
405
406 // External extensions with update URLs do not have versions.
407 scoped_ptr<Version> v1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000408 Manifest::Location location1 = Manifest::INVALID_LOCATION;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000409 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location1, &v1));
410 EXPECT_FALSE(v1.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000411 EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, location1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000412
413 // Remove it so we won't count it again.
414 prefs_->Remove(id, NULL);
415 }
416 return true;
417 }
418
419 virtual void OnExternalProviderReady(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000420 const extensions::ExternalProviderInterface* provider) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000421 EXPECT_EQ(provider, provider_.get());
422 EXPECT_TRUE(provider->IsReady());
423 }
424
425 private:
426 int ids_found_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000427 base::FilePath fake_base_path_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000428 int expected_creation_flags_;
429 scoped_ptr<extensions::ExternalProviderImpl> provider_;
430 scoped_ptr<DictionaryValue> prefs_;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100431 scoped_ptr<TestingProfile> profile_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000432
433 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
434};
435
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100436ExtensionServiceTestBase::ExtensionServiceInitParams::
437ExtensionServiceInitParams()
438 : autoupdate_enabled(false), is_first_run(true) {
439}
440
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000441// Our message loop may be used in tests which require it to be an IO loop.
442ExtensionServiceTestBase::ExtensionServiceTestBase()
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100443 : loop_(base::MessageLoop::TYPE_IO),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000444 service_(NULL),
445 management_policy_(NULL),
446 expected_extensions_count_(0),
447 ui_thread_(BrowserThread::UI, &loop_),
448 db_thread_(BrowserThread::DB, &loop_),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000449 file_thread_(BrowserThread::FILE, &loop_),
450 file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING, &loop_),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100451 io_thread_(BrowserThread::IO, &loop_) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000452 base::FilePath test_data_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000453 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
454 ADD_FAILURE();
455 return;
456 }
457 data_dir_ = test_data_dir.AppendASCII("extensions");
458}
459
460ExtensionServiceTestBase::~ExtensionServiceTestBase() {
461 // Drop our reference to ExtensionService and TestingProfile, so that they
462 // can be destroyed while BrowserThreads and MessageLoop are still around
463 // (they are used in the destruction process).
464 service_ = NULL;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100465 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000466 profile_.reset(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100467 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000468}
469
470void ExtensionServiceTestBase::InitializeExtensionService(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100471 const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000472 TestingProfile::Builder profile_builder;
473 // Create a PrefService that only contains user defined preference values.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000474 PrefServiceMockBuilder builder;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100475 // If pref_file is empty, TestingProfile automatically creates
476 // TestingPrefServiceSyncable instance.
477 if (!params.pref_file.empty()) {
478 builder.WithUserFilePrefs(params.pref_file,
479 loop_.message_loop_proxy().get());
480 scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
481 new user_prefs::PrefRegistrySyncable);
482 scoped_ptr<PrefServiceSyncable> prefs(
483 builder.CreateSyncable(registry.get()));
484 chrome::RegisterUserProfilePrefs(registry.get());
485 profile_builder.SetPrefService(prefs.Pass());
486 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100487 profile_builder.SetPath(params.profile_path);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000488 profile_ = profile_builder.Build();
489
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100490 TestExtensionSystem* system = static_cast<TestExtensionSystem*>(
491 ExtensionSystem::Get(profile_.get()));
492 if (!params.is_first_run) {
493 ExtensionPrefs* prefs = system->CreateExtensionPrefs(
494 CommandLine::ForCurrentProcess(),
495 params.extensions_install_dir);
496 prefs->SetAlertSystemFirstRun();
497 }
498
499 service_ = system->CreateExtensionService(
500 CommandLine::ForCurrentProcess(),
501 params.extensions_install_dir,
502 params.autoupdate_enabled);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100503 service_->SetFileTaskRunnerForTesting(loop_.message_loop_proxy().get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000504 service_->set_extensions_enabled(true);
505 service_->set_show_extensions_prompts(false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000506 service_->set_install_updates_when_idle_for_test(false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000507
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000508 management_policy_ =
509 ExtensionSystem::Get(profile_.get())->management_policy();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000510
511 // When we start up, we want to make sure there is no external provider,
512 // since the ExtensionService on Windows will use the Registry as a default
513 // provider and if there is something already registered there then it will
514 // interfere with the tests. Those tests that need an external provider
515 // will register one specifically.
516 service_->ClearProvidersForTesting();
517
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000518#if defined(OS_CHROMEOS)
519 extensions::InstallLimiter::Get(profile_.get())->DisableForTest();
520#endif
521
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000522 expected_extensions_count_ = 0;
523}
524
525void ExtensionServiceTestBase::InitializeInstalledExtensionService(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000526 const base::FilePath& prefs_file,
527 const base::FilePath& source_install_dir) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000528 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000529 base::FilePath path = temp_dir_.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000530 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100531 base::DeleteFile(path, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000532 file_util::CreateDirectory(path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000533 base::FilePath temp_prefs = path.Append(FILE_PATH_LITERAL("Preferences"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100534 base::CopyFile(prefs_file, temp_prefs);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000535
536 extensions_install_dir_ = path.Append(FILE_PATH_LITERAL("Extensions"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100537 base::DeleteFile(extensions_install_dir_, true);
538 base::CopyDirectory(source_install_dir, extensions_install_dir_, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000539
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100540 ExtensionServiceInitParams params;
541 params.profile_path = path;
542 params.pref_file = temp_prefs;
543 params.extensions_install_dir = extensions_install_dir_;
544 InitializeExtensionService(params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000545}
546
547void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100548 InitializeExtensionServiceHelper(false, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000549}
550
551void ExtensionServiceTestBase::InitializeExtensionProcessManager() {
552 static_cast<extensions::TestExtensionSystem*>(
553 ExtensionSystem::Get(profile_.get()))->
554 CreateExtensionProcessManager();
555}
556
557void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100558 InitializeExtensionServiceHelper(true, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000559 service_->updater()->Start();
560}
561
562void ExtensionServiceTestBase::InitializeExtensionServiceHelper(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100563 bool autoupdate_enabled, bool is_first_run) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000564 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000565 base::FilePath path = temp_dir_.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000566 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100567 base::DeleteFile(path, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000568 file_util::CreateDirectory(path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000569 base::FilePath prefs_filename =
570 path.Append(FILE_PATH_LITERAL("TestPreferences"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000571 extensions_install_dir_ = path.Append(FILE_PATH_LITERAL("Extensions"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100572 base::DeleteFile(extensions_install_dir_, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000573 file_util::CreateDirectory(extensions_install_dir_);
574
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100575 ExtensionServiceInitParams params;
576 params.profile_path = path;
577 params.pref_file = prefs_filename;
578 params.extensions_install_dir = extensions_install_dir_;
579 params.autoupdate_enabled = autoupdate_enabled;
580 params.is_first_run = is_first_run;
581 InitializeExtensionService(params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000582}
583
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000584// static
585void ExtensionServiceTestBase::SetUpTestCase() {
586 ExtensionErrorReporter::Init(false); // no noisy errors
587}
588
589void ExtensionServiceTestBase::SetUp() {
590 ExtensionErrorReporter::GetInstance()->ClearErrors();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100591 content::RenderProcessHost::SetRunRendererInProcess(true);
592}
593
594void ExtensionServiceTestBase::TearDown() {
595 content::RenderProcessHost::SetRunRendererInProcess(false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000596}
597
598class ExtensionServiceTest
599 : public ExtensionServiceTestBase, public content::NotificationObserver {
600 public:
601 ExtensionServiceTest()
602 : installed_(NULL),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100603 was_update_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000604 override_external_install_prompt_(
605 FeatureSwitch::prompt_for_external_extensions(), false) {
606 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
607 content::NotificationService::AllSources());
608 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
609 content::NotificationService::AllSources());
610 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
611 content::NotificationService::AllSources());
612 }
613
614 virtual void Observe(int type,
615 const content::NotificationSource& source,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000616 const content::NotificationDetails& details) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000617 switch (type) {
618 case chrome::NOTIFICATION_EXTENSION_LOADED: {
619 const Extension* extension =
620 content::Details<const Extension>(details).ptr();
621 loaded_.push_back(make_scoped_refptr(extension));
622 // The tests rely on the errors being in a certain order, which can vary
623 // depending on how filesystem iteration works.
624 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder());
625 break;
626 }
627
628 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
629 const Extension* e =
630 content::Details<extensions::UnloadedExtensionInfo>(
631 details)->extension;
632 unloaded_id_ = e->id();
633 extensions::ExtensionList::iterator i =
634 std::find(loaded_.begin(), loaded_.end(), e);
635 // TODO(erikkay) fix so this can be an assert. Right now the tests
636 // are manually calling clear() on loaded_, so this isn't doable.
637 if (i == loaded_.end())
638 return;
639 loaded_.erase(i);
640 break;
641 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100642 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
643 const extensions::InstalledExtensionInfo* installed_info =
644 content::Details<const extensions::InstalledExtensionInfo>(details)
645 .ptr();
646 installed_ = installed_info->extension;
647 was_update_ = installed_info->is_update;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100648 old_name_ = installed_info->old_name;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000649 break;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100650 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000651
652 default:
653 DCHECK(false);
654 }
655 }
656
657 void AddMockExternalProvider(
658 extensions::ExternalProviderInterface* provider) {
659 service_->AddProviderForTesting(provider);
660 }
661
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100662 void MockSyncStartFlare(bool* was_called,
663 syncer::ModelType* model_type_passed_in,
664 syncer::ModelType model_type) {
665 *was_called = true;
666 *model_type_passed_in = model_type;
667 }
668
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000669 protected:
670 void TestExternalProvider(MockExtensionProvider* provider,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000671 Manifest::Location location);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000672
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000673 void PackCRX(const base::FilePath& dir_path,
674 const base::FilePath& pem_path,
675 const base::FilePath& crx_path) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000676 // Use the existing pem key, if provided.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000677 base::FilePath pem_output_path;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000678 if (pem_path.value().empty()) {
679 pem_output_path = crx_path.DirName().AppendASCII("temp.pem");
680 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100681 ASSERT_TRUE(base::PathExists(pem_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000682 }
683
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100684 ASSERT_TRUE(base::DeleteFile(crx_path, false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000685
686 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
687 ASSERT_TRUE(creator->Run(dir_path,
688 crx_path,
689 pem_path,
690 pem_output_path,
691 ExtensionCreator::kOverwriteCRX));
692
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100693 ASSERT_TRUE(base::PathExists(crx_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000694 }
695
696 // Create a CrxInstaller and start installation. To allow the install
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000697 // to happen, use loop_.RunUntilIdle();. Most tests will not use this
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000698 // method directly. Instead, use InstallCrx(), which waits for
699 // the crx to be installed and does extra error checking.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000700 void StartCRXInstall(const base::FilePath& crx_path) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000701 StartCRXInstall(crx_path, Extension::NO_FLAGS);
702 }
703
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000704 void StartCRXInstall(const base::FilePath& crx_path, int creation_flags) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100705 ASSERT_TRUE(base::PathExists(crx_path))
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000706 << "Path does not exist: "<< crx_path.value().c_str();
707 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
708 installer->set_creation_flags(creation_flags);
709 if (!(creation_flags & Extension::WAS_INSTALLED_BY_DEFAULT)) {
710 installer->set_allow_silent_install(true);
711 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100712
713 content::WindowedNotificationObserver windowed_observer(
714 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
715 content::Source<extensions::CrxInstaller>(installer));
716
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000717 installer->InstallCrx(crx_path);
718 }
719
720 enum InstallState {
721 INSTALL_FAILED,
722 INSTALL_UPDATED,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000723 INSTALL_NEW,
724 INSTALL_WITHOUT_LOAD,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000725 };
726
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000727 const Extension* PackAndInstallCRX(const base::FilePath& dir_path,
728 const base::FilePath& pem_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000729 InstallState install_state,
730 int creation_flags) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000731 base::FilePath crx_path;
732 base::ScopedTempDir temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000733 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
734 crx_path = temp_dir.path().AppendASCII("temp.crx");
735
736 PackCRX(dir_path, pem_path, crx_path);
737 return InstallCRX(crx_path, install_state, creation_flags);
738 }
739
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000740 const Extension* PackAndInstallCRX(const base::FilePath& dir_path,
741 const base::FilePath& pem_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000742 InstallState install_state) {
743 return PackAndInstallCRX(dir_path, pem_path, install_state,
744 Extension::NO_FLAGS);
745 }
746
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000747 const Extension* PackAndInstallCRX(const base::FilePath& dir_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000748 InstallState install_state) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000749 return PackAndInstallCRX(dir_path, base::FilePath(), install_state,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000750 Extension::NO_FLAGS);
751 }
752
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100753 // Attempts to install an extension. Use INSTALL_FAILED if the installation
754 // is expected to fail.
755 // If |install_state| is INSTALL_UPDATED, and |expected_old_name| is
756 // non-empty, expects that the existing extension's title was
757 // |expected_old_name|.
758 const Extension* InstallCRX(const base::FilePath& path,
759 InstallState install_state,
760 int creation_flags,
761 const std::string& expected_old_name) {
762 StartCRXInstall(path, creation_flags);
763 return WaitForCrxInstall(path, install_state, expected_old_name);
764 }
765
766 // Attempts to install an extension. Use INSTALL_FAILED if the installation
767 // is expected to fail.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000768 const Extension* InstallCRX(const base::FilePath& path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000769 InstallState install_state,
770 int creation_flags) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100771 return InstallCRX(path, install_state, creation_flags, "");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000772 }
773
774 // Attempts to install an extension. Use INSTALL_FAILED if the installation
775 // is expected to fail.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000776 const Extension* InstallCRX(const base::FilePath& path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000777 InstallState install_state) {
778 return InstallCRX(path, install_state, Extension::NO_FLAGS);
779 }
780
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000781 const Extension* InstallCRXFromWebStore(const base::FilePath& path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000782 InstallState install_state) {
783 StartCRXInstall(path, Extension::FROM_WEBSTORE);
784 return WaitForCrxInstall(path, install_state);
785 }
786
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000787 const Extension* InstallCRXWithLocation(const base::FilePath& crx_path,
788 Manifest::Location install_location,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000789 InstallState install_state) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100790 EXPECT_TRUE(base::PathExists(crx_path))
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000791 << "Path does not exist: "<< crx_path.value().c_str();
792 // no client (silent install)
793 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000794 installer->set_install_source(install_location);
795 installer->InstallCrx(crx_path);
796
797 return WaitForCrxInstall(crx_path, install_state);
798 }
799
800 // Wait for a CrxInstaller to finish. Used by InstallCRX. Set the
801 // |install_state| to INSTALL_FAILED if the installation is expected to fail.
802 // Returns an Extension pointer if the install succeeded, NULL otherwise.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000803 const Extension* WaitForCrxInstall(const base::FilePath& path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000804 InstallState install_state) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100805 return WaitForCrxInstall(path, install_state, "");
806 }
807
808 // Wait for a CrxInstaller to finish. Used by InstallCRX. Set the
809 // |install_state| to INSTALL_FAILED if the installation is expected to fail.
810 // If |install_state| is INSTALL_UPDATED, and |expected_old_name| is
811 // non-empty, expects that the existing extension's title was
812 // |expected_old_name|.
813 // Returns an Extension pointer if the install succeeded, NULL otherwise.
814 const Extension* WaitForCrxInstall(const base::FilePath& path,
815 InstallState install_state,
816 const std::string& expected_old_name) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100817 content::WindowedNotificationObserver(
818 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
819 content::NotificationService::AllSources()).Wait();
820
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000821 std::vector<string16> errors = GetErrors();
822 const Extension* extension = NULL;
823 if (install_state != INSTALL_FAILED) {
824 if (install_state == INSTALL_NEW)
825 ++expected_extensions_count_;
826
827 EXPECT_TRUE(installed_) << path.value();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100828 // If and only if INSTALL_UPDATED, it should have the is_update flag.
829 EXPECT_EQ(install_state == INSTALL_UPDATED, was_update_)
830 << path.value();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100831 // If INSTALL_UPDATED, old_name_ should match the given string.
832 if (install_state == INSTALL_UPDATED && !expected_old_name.empty())
833 EXPECT_EQ(expected_old_name, old_name_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000834 EXPECT_EQ(0u, errors.size()) << path.value();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000835
836 if (install_state == INSTALL_WITHOUT_LOAD) {
837 EXPECT_EQ(0u, loaded_.size()) << path.value();
838 } else {
839 EXPECT_EQ(1u, loaded_.size()) << path.value();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100840 EXPECT_EQ(expected_extensions_count_, service_->extensions()->size()) <<
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000841 path.value();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100842 extension = loaded_[0].get();
843 EXPECT_TRUE(service_->GetExtensionById(extension->id(), false))
844 << path.value();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000845 }
846
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000847 for (std::vector<string16>::iterator err = errors.begin();
848 err != errors.end(); ++err) {
849 LOG(ERROR) << *err;
850 }
851 } else {
852 EXPECT_FALSE(installed_) << path.value();
853 EXPECT_EQ(0u, loaded_.size()) << path.value();
854 EXPECT_EQ(1u, errors.size()) << path.value();
855 }
856
857 installed_ = NULL;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100858 was_update_ = false;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100859 old_name_ = "";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000860 loaded_.clear();
861 ExtensionErrorReporter::GetInstance()->ClearErrors();
862 return extension;
863 }
864
865 enum UpdateState {
866 FAILED_SILENTLY,
867 FAILED,
868 UPDATED,
869 INSTALLED,
870 ENABLED
871 };
872
873 void BlackListWebGL() {
874 static const std::string json_blacklist =
875 "{\n"
876 " \"name\": \"gpu blacklist\",\n"
877 " \"version\": \"1.0\",\n"
878 " \"entries\": [\n"
879 " {\n"
880 " \"id\": 1,\n"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000881 " \"features\": [\"webgl\"]\n"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000882 " }\n"
883 " ]\n"
884 "}";
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100885 gpu::GPUInfo gpu_info;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000886 content::GpuDataManager::GetInstance()->InitializeForTesting(
887 json_blacklist, gpu_info);
888 }
889
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000890 void UpdateExtension(const std::string& id, const base::FilePath& in_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000891 UpdateState expected_state) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100892 ASSERT_TRUE(base::PathExists(in_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000893
894 // We need to copy this to a temporary location because Update() will delete
895 // it.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000896 base::FilePath path = temp_dir_.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000897 path = path.Append(in_path.BaseName());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100898 ASSERT_TRUE(base::CopyFile(in_path, path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000899
900 int previous_enabled_extension_count =
901 service_->extensions()->size();
902 int previous_installed_extension_count =
903 previous_enabled_extension_count +
904 service_->disabled_extensions()->size();
905
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100906 extensions::CrxInstaller* installer = NULL;
907 service_->UpdateExtension(id, path, GURL(), &installer);
908
909 if (installer) {
910 content::WindowedNotificationObserver(
911 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
912 content::Source<extensions::CrxInstaller>(installer)).Wait();
913 } else {
914 loop_.RunUntilIdle();
915 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000916
917 std::vector<string16> errors = GetErrors();
918 int error_count = errors.size();
919 int enabled_extension_count =
920 service_->extensions()->size();
921 int installed_extension_count =
922 enabled_extension_count + service_->disabled_extensions()->size();
923
924 int expected_error_count = (expected_state == FAILED) ? 1 : 0;
925 EXPECT_EQ(expected_error_count, error_count) << path.value();
926
927 if (expected_state <= FAILED) {
928 EXPECT_EQ(previous_enabled_extension_count,
929 enabled_extension_count);
930 EXPECT_EQ(previous_installed_extension_count,
931 installed_extension_count);
932 } else {
933 int expected_installed_extension_count =
934 (expected_state >= INSTALLED) ? 1 : 0;
935 int expected_enabled_extension_count =
936 (expected_state >= ENABLED) ? 1 : 0;
937 EXPECT_EQ(expected_installed_extension_count,
938 installed_extension_count);
939 EXPECT_EQ(expected_enabled_extension_count,
940 enabled_extension_count);
941 }
942
943 // Update() should the temporary input file.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100944 EXPECT_FALSE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000945 }
946
947 void TerminateExtension(const std::string& id) {
948 const Extension* extension = service_->GetInstalledExtension(id);
949 if (!extension) {
950 ADD_FAILURE();
951 return;
952 }
953 service_->TrackTerminatedExtensionForTest(extension);
954 }
955
956 size_t GetPrefKeyCount() {
957 const DictionaryValue* dict =
958 profile_->GetPrefs()->GetDictionary("extensions.settings");
959 if (!dict) {
960 ADD_FAILURE();
961 return 0;
962 }
963 return dict->size();
964 }
965
966 void UninstallExtension(const std::string& id, bool use_helper) {
967 // Verify that the extension is installed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000968 base::FilePath extension_path = extensions_install_dir_.AppendASCII(id);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100969 EXPECT_TRUE(base::PathExists(extension_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000970 size_t pref_key_count = GetPrefKeyCount();
971 EXPECT_GT(pref_key_count, 0u);
972 ValidateIntegerPref(id, "state", Extension::ENABLED);
973
974 // Uninstall it.
975 if (use_helper) {
976 EXPECT_TRUE(ExtensionService::UninstallExtensionHelper(service_, id));
977 } else {
978 EXPECT_TRUE(service_->UninstallExtension(id, false, NULL));
979 }
980 --expected_extensions_count_;
981
982 // We should get an unload notification.
983 EXPECT_FALSE(unloaded_id_.empty());
984 EXPECT_EQ(id, unloaded_id_);
985
986 // Verify uninstalled state.
987 size_t new_pref_key_count = GetPrefKeyCount();
988 if (new_pref_key_count == pref_key_count) {
989 ValidateIntegerPref(id, "location",
990 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
991 } else {
992 EXPECT_EQ(new_pref_key_count, pref_key_count - 1);
993 }
994
995 // The extension should not be in the service anymore.
996 EXPECT_FALSE(service_->GetInstalledExtension(id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000997 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000998
999 // The directory should be gone.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001000 EXPECT_FALSE(base::PathExists(extension_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001001 }
1002
1003 void ValidatePrefKeyCount(size_t count) {
1004 EXPECT_EQ(count, GetPrefKeyCount());
1005 }
1006
1007 void ValidateBooleanPref(const std::string& extension_id,
1008 const std::string& pref_path,
1009 bool expected_val) {
1010 std::string msg = " while checking: ";
1011 msg += extension_id;
1012 msg += " ";
1013 msg += pref_path;
1014 msg += " == ";
1015 msg += expected_val ? "true" : "false";
1016
1017 PrefService* prefs = profile_->GetPrefs();
1018 const DictionaryValue* dict =
1019 prefs->GetDictionary("extensions.settings");
1020 ASSERT_TRUE(dict != NULL) << msg;
1021 const DictionaryValue* pref = NULL;
1022 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
1023 EXPECT_TRUE(pref != NULL) << msg;
1024 bool val;
1025 ASSERT_TRUE(pref->GetBoolean(pref_path, &val)) << msg;
1026 EXPECT_EQ(expected_val, val) << msg;
1027 }
1028
1029 bool IsPrefExist(const std::string& extension_id,
1030 const std::string& pref_path) {
1031 const DictionaryValue* dict =
1032 profile_->GetPrefs()->GetDictionary("extensions.settings");
1033 if (dict == NULL) return false;
1034 const DictionaryValue* pref = NULL;
1035 if (!dict->GetDictionary(extension_id, &pref)) {
1036 return false;
1037 }
1038 if (pref == NULL) {
1039 return false;
1040 }
1041 bool val;
1042 if (!pref->GetBoolean(pref_path, &val)) {
1043 return false;
1044 }
1045 return true;
1046 }
1047
1048 void ValidateIntegerPref(const std::string& extension_id,
1049 const std::string& pref_path,
1050 int expected_val) {
1051 std::string msg = " while checking: ";
1052 msg += extension_id;
1053 msg += " ";
1054 msg += pref_path;
1055 msg += " == ";
1056 msg += base::IntToString(expected_val);
1057
1058 PrefService* prefs = profile_->GetPrefs();
1059 const DictionaryValue* dict =
1060 prefs->GetDictionary("extensions.settings");
1061 ASSERT_TRUE(dict != NULL) << msg;
1062 const DictionaryValue* pref = NULL;
1063 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
1064 EXPECT_TRUE(pref != NULL) << msg;
1065 int val;
1066 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg;
1067 EXPECT_EQ(expected_val, val) << msg;
1068 }
1069
1070 void ValidateStringPref(const std::string& extension_id,
1071 const std::string& pref_path,
1072 const std::string& expected_val) {
1073 std::string msg = " while checking: ";
1074 msg += extension_id;
1075 msg += ".manifest.";
1076 msg += pref_path;
1077 msg += " == ";
1078 msg += expected_val;
1079
1080 const DictionaryValue* dict =
1081 profile_->GetPrefs()->GetDictionary("extensions.settings");
1082 ASSERT_TRUE(dict != NULL) << msg;
1083 const DictionaryValue* pref = NULL;
1084 std::string manifest_path = extension_id + ".manifest";
1085 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg;
1086 EXPECT_TRUE(pref != NULL) << msg;
1087 std::string val;
1088 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg;
1089 EXPECT_EQ(expected_val, val) << msg;
1090 }
1091
1092 void SetPref(const std::string& extension_id,
1093 const std::string& pref_path,
1094 Value* value,
1095 const std::string& msg) {
1096 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1097 DictionaryValue* dict = update.Get();
1098 ASSERT_TRUE(dict != NULL) << msg;
1099 DictionaryValue* pref = NULL;
1100 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
1101 EXPECT_TRUE(pref != NULL) << msg;
1102 pref->Set(pref_path, value);
1103 }
1104
1105 void SetPrefInteg(const std::string& extension_id,
1106 const std::string& pref_path,
1107 int value) {
1108 std::string msg = " while setting: ";
1109 msg += extension_id;
1110 msg += " ";
1111 msg += pref_path;
1112 msg += " = ";
1113 msg += base::IntToString(value);
1114
1115 SetPref(extension_id, pref_path, Value::CreateIntegerValue(value), msg);
1116 }
1117
1118 void SetPrefBool(const std::string& extension_id,
1119 const std::string& pref_path,
1120 bool value) {
1121 std::string msg = " while setting: ";
1122 msg += extension_id + " " + pref_path;
1123 msg += " = ";
1124 msg += (value ? "true" : "false");
1125
1126 SetPref(extension_id, pref_path, Value::CreateBooleanValue(value), msg);
1127 }
1128
1129 void ClearPref(const std::string& extension_id,
1130 const std::string& pref_path) {
1131 std::string msg = " while clearing: ";
1132 msg += extension_id + " " + pref_path;
1133
1134 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1135 DictionaryValue* dict = update.Get();
1136 ASSERT_TRUE(dict != NULL) << msg;
1137 DictionaryValue* pref = NULL;
1138 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
1139 EXPECT_TRUE(pref != NULL) << msg;
1140 pref->Remove(pref_path, NULL);
1141 }
1142
1143 void SetPrefStringSet(const std::string& extension_id,
1144 const std::string& pref_path,
1145 const std::set<std::string>& value) {
1146 std::string msg = " while setting: ";
1147 msg += extension_id + " " + pref_path;
1148
1149 ListValue* list_value = new ListValue();
1150 for (std::set<std::string>::const_iterator iter = value.begin();
1151 iter != value.end(); ++iter)
1152 list_value->Append(Value::CreateStringValue(*iter));
1153
1154 SetPref(extension_id, pref_path, list_value, msg);
1155 }
1156
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001157 void InitPluginService() {
1158#if defined(ENABLE_PLUGINS)
1159 PluginService::GetInstance()->Init();
1160#endif
1161 }
1162
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001163 protected:
1164 extensions::ExtensionList loaded_;
1165 std::string unloaded_id_;
1166 const Extension* installed_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001167 bool was_update_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001168 std::string old_name_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001169 FeatureSwitch::ScopedOverride override_external_install_prompt_;
1170
1171 private:
1172 content::NotificationRegistrar registrar_;
1173};
1174
1175// Receives notifications from a PackExtensionJob, indicating either that
1176// packing succeeded or that there was some error.
1177class PackExtensionTestClient : public extensions::PackExtensionJob::Client {
1178 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001179 PackExtensionTestClient(const base::FilePath& expected_crx_path,
1180 const base::FilePath& expected_private_key_path);
1181 virtual void OnPackSuccess(const base::FilePath& crx_path,
1182 const base::FilePath& private_key_path) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001183 virtual void OnPackFailure(const std::string& error_message,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001184 ExtensionCreator::ErrorType type) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001185
1186 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001187 const base::FilePath expected_crx_path_;
1188 const base::FilePath expected_private_key_path_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001189 DISALLOW_COPY_AND_ASSIGN(PackExtensionTestClient);
1190};
1191
1192PackExtensionTestClient::PackExtensionTestClient(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001193 const base::FilePath& expected_crx_path,
1194 const base::FilePath& expected_private_key_path)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001195 : expected_crx_path_(expected_crx_path),
1196 expected_private_key_path_(expected_private_key_path) {}
1197
1198// If packing succeeded, we make sure that the package names match our
1199// expectations.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001200void PackExtensionTestClient::OnPackSuccess(
1201 const base::FilePath& crx_path,
1202 const base::FilePath& private_key_path) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001203 // We got the notification and processed it; we don't expect any further tasks
1204 // to be posted to the current thread, so we should stop blocking and continue
1205 // on with the rest of the test.
1206 // This call to |Quit()| matches the call to |Run()| in the
1207 // |PackPunctuatedExtension| test.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001208 base::MessageLoop::current()->Quit();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001209 EXPECT_EQ(expected_crx_path_.value(), crx_path.value());
1210 EXPECT_EQ(expected_private_key_path_.value(), private_key_path.value());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001211 ASSERT_TRUE(base::PathExists(private_key_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001212}
1213
1214// The tests are designed so that we never expect to see a packing error.
1215void PackExtensionTestClient::OnPackFailure(const std::string& error_message,
1216 ExtensionCreator::ErrorType type) {
1217 if (type == ExtensionCreator::kCRXExists)
1218 FAIL() << "Packing should not fail.";
1219 else
1220 FAIL() << "Existing CRX should have been overwritten.";
1221}
1222
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001223// Test loading good extensions from the profile directory.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001224TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) {
1225 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001226
1227 // Initialize the test dir with a good Preferences/extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001228 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001229 .AppendASCII("good")
1230 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001231 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001232 .DirName()
1233 .AppendASCII("Preferences");
1234 InitializeInstalledExtensionService(pref_path, source_install_dir);
1235
1236 service_->Init();
1237
1238 uint32 expected_num_extensions = 3u;
1239 ASSERT_EQ(expected_num_extensions, loaded_.size());
1240
1241 EXPECT_EQ(std::string(good0), loaded_[0]->id());
1242 EXPECT_EQ(std::string("My extension 1"),
1243 loaded_[0]->name());
1244 EXPECT_EQ(std::string("The first extension that I made."),
1245 loaded_[0]->description());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001246 EXPECT_EQ(Manifest::INTERNAL, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001247 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false));
1248 EXPECT_EQ(expected_num_extensions, service_->extensions()->size());
1249
1250 ValidatePrefKeyCount(3);
1251 ValidateIntegerPref(good0, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001252 ValidateIntegerPref(good0, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001253 ValidateIntegerPref(good1, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001254 ValidateIntegerPref(good1, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001255 ValidateIntegerPref(good2, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001256 ValidateIntegerPref(good2, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001257
1258 URLPatternSet expected_patterns;
1259 AddPattern(&expected_patterns, "file:///*");
1260 AddPattern(&expected_patterns, "http://*.google.com/*");
1261 AddPattern(&expected_patterns, "https://*.google.com/*");
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001262 const Extension* extension = loaded_[0].get();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001263 const extensions::UserScriptList& scripts =
1264 extensions::ContentScriptsInfo::GetContentScripts(extension);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001265 ASSERT_EQ(2u, scripts.size());
1266 EXPECT_EQ(expected_patterns, scripts[0].url_patterns());
1267 EXPECT_EQ(2u, scripts[0].js_scripts().size());
1268 ExtensionResource resource00(extension->id(),
1269 scripts[0].js_scripts()[0].extension_root(),
1270 scripts[0].js_scripts()[0].relative_path());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001271 base::FilePath expected_path =
1272 base::MakeAbsoluteFilePath(extension->path().AppendASCII("script1.js"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001273 EXPECT_TRUE(resource00.ComparePathWithDefault(expected_path));
1274 ExtensionResource resource01(extension->id(),
1275 scripts[0].js_scripts()[1].extension_root(),
1276 scripts[0].js_scripts()[1].relative_path());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001277 expected_path =
1278 base::MakeAbsoluteFilePath(extension->path().AppendASCII("script2.js"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001279 EXPECT_TRUE(resource01.ComparePathWithDefault(expected_path));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001280 EXPECT_TRUE(!extensions::PluginInfo::HasPlugins(extension));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001281 EXPECT_EQ(1u, scripts[1].url_patterns().patterns().size());
1282 EXPECT_EQ("http://*.news.com/*",
1283 scripts[1].url_patterns().begin()->GetAsString());
1284 ExtensionResource resource10(extension->id(),
1285 scripts[1].js_scripts()[0].extension_root(),
1286 scripts[1].js_scripts()[0].relative_path());
1287 expected_path =
1288 extension->path().AppendASCII("js_files").AppendASCII("script3.js");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001289 expected_path = base::MakeAbsoluteFilePath(expected_path);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001290 EXPECT_TRUE(resource10.ComparePathWithDefault(expected_path));
1291
1292 expected_patterns.ClearPatterns();
1293 AddPattern(&expected_patterns, "http://*.google.com/*");
1294 AddPattern(&expected_patterns, "https://*.google.com/*");
1295 EXPECT_EQ(expected_patterns,
1296 extension->GetActivePermissions()->explicit_hosts());
1297
1298 EXPECT_EQ(std::string(good1), loaded_[1]->id());
1299 EXPECT_EQ(std::string("My extension 2"), loaded_[1]->name());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001300 EXPECT_EQ(std::string(), loaded_[1]->description());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001301 EXPECT_EQ(loaded_[1]->GetResourceURL("background.html"),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001302 extensions::BackgroundInfo::GetBackgroundURL(loaded_[1].get()));
1303 EXPECT_EQ(0u,
1304 extensions::ContentScriptsInfo::GetContentScripts(loaded_[1].get())
1305 .size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001306
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001307 // We don't parse the plugins section on Chrome OS.
1308#if defined(OS_CHROMEOS)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01001309 EXPECT_TRUE(!extensions::PluginInfo::HasPlugins(loaded_[1].get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001310#else
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001311 ASSERT_TRUE(extensions::PluginInfo::HasPlugins(loaded_[1].get()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001312 const std::vector<extensions::PluginInfo>* plugins =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001313 extensions::PluginInfo::GetPlugins(loaded_[1].get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001314 ASSERT_TRUE(plugins);
1315 ASSERT_EQ(2u, plugins->size());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001316 EXPECT_EQ(loaded_[1]->path().AppendASCII("content_plugin.dll").value(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001317 plugins->at(0).path.value());
1318 EXPECT_TRUE(plugins->at(0).is_public);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001319 EXPECT_EQ(loaded_[1]->path().AppendASCII("extension_plugin.dll").value(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001320 plugins->at(1).path.value());
1321 EXPECT_FALSE(plugins->at(1).is_public);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001322#endif
1323
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001324 EXPECT_EQ(Manifest::INTERNAL, loaded_[1]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001325
1326 int index = expected_num_extensions - 1;
1327 EXPECT_EQ(std::string(good2), loaded_[index]->id());
1328 EXPECT_EQ(std::string("My extension 3"), loaded_[index]->name());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001329 EXPECT_EQ(std::string(), loaded_[index]->description());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001330 EXPECT_EQ(0u,
1331 extensions::ContentScriptsInfo::GetContentScripts(
1332 loaded_[index].get()).size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001333 EXPECT_EQ(Manifest::INTERNAL, loaded_[index]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001334};
1335
1336// Test loading bad extensions from the profile directory.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001337TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectoryFail) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001338 // Initialize the test dir with a bad Preferences/extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001339 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001340 .AppendASCII("bad")
1341 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001342 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001343 .DirName()
1344 .AppendASCII("Preferences");
1345
1346 InitializeInstalledExtensionService(pref_path, source_install_dir);
1347
1348 service_->Init();
1349
1350 ASSERT_EQ(4u, GetErrors().size());
1351 ASSERT_EQ(0u, loaded_.size());
1352
1353 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[0]),
1354 std::string("Could not load extension from '*'. ") +
1355 extension_manifest_errors::kManifestUnreadable)) <<
1356 UTF16ToUTF8(GetErrors()[0]);
1357
1358 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[1]),
1359 std::string("Could not load extension from '*'. ") +
1360 extension_manifest_errors::kManifestUnreadable)) <<
1361 UTF16ToUTF8(GetErrors()[1]);
1362
1363 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[2]),
1364 std::string("Could not load extension from '*'. ") +
1365 extension_manifest_errors::kMissingFile)) <<
1366 UTF16ToUTF8(GetErrors()[2]);
1367
1368 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[3]),
1369 std::string("Could not load extension from '*'. ") +
1370 extension_manifest_errors::kManifestUnreadable)) <<
1371 UTF16ToUTF8(GetErrors()[3]);
1372};
1373
1374// Test that partially deleted extensions are cleaned up during startup
1375// Test loading bad extensions from the profile directory.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001376TEST_F(ExtensionServiceTest, CleanupOnStartup) {
1377 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001378
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001379 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001380 .AppendASCII("good")
1381 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001382 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001383 .DirName()
1384 .AppendASCII("Preferences");
1385
1386 InitializeInstalledExtensionService(pref_path, source_install_dir);
1387
1388 // Simulate that one of them got partially deleted by clearing its pref.
1389 {
1390 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1391 DictionaryValue* dict = update.Get();
1392 ASSERT_TRUE(dict != NULL);
1393 dict->Remove("behllobkkfkfnphdnhnkndlbkcpglgmj", NULL);
1394 }
1395
1396 service_->Init();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01001397 // A delayed task to call GarbageCollectExtensions is posted by
1398 // ExtensionService::Init. As the test won't wait for the delayed task to
1399 // be called, call it manually instead.
1400 service_->GarbageCollectExtensions();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001401 // Wait for GarbageCollectExtensions task to complete.
1402 loop_.RunUntilIdle();
1403
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001404 base::FileEnumerator dirs(extensions_install_dir_, false,
1405 base::FileEnumerator::DIRECTORIES);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001406 size_t count = 0;
1407 while (!dirs.Next().empty())
1408 count++;
1409
1410 // We should have only gotten two extensions now.
1411 EXPECT_EQ(2u, count);
1412
1413 // And extension1 dir should now be toast.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001414 base::FilePath extension_dir = extensions_install_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001415 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001416 ASSERT_FALSE(base::PathExists(extension_dir));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001417}
1418
1419// Test that GarbageCollectExtensions deletes the right versions of an
1420// extension.
1421TEST_F(ExtensionServiceTest, GarbageCollectWithPendingUpdates) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001422 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001423
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001424 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001425 .AppendASCII("pending_updates")
1426 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001427 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001428 .DirName()
1429 .AppendASCII("Preferences");
1430
1431 InitializeInstalledExtensionService(pref_path, source_install_dir);
1432
1433 // This is the directory that is going to be deleted, so make sure it actually
1434 // is there before the garbage collection.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001435 ASSERT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001436 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
1437
1438 service_->GarbageCollectExtensions();
1439 // Wait for GarbageCollectExtensions task to complete.
1440 loop_.RunUntilIdle();
1441
1442 // Verify that the pending update for the first extension didn't get
1443 // deleted.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001444 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001445 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001446 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001447 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001448 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001449 "hpiknbiabeeppbpihjehijgoemciehgk/2")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001450 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001451 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
1452}
1453
1454// Test that pending updates are properly handled on startup.
1455TEST_F(ExtensionServiceTest, UpdateOnStartup) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001456 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001457
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001458 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001459 .AppendASCII("pending_updates")
1460 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001461 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001462 .DirName()
1463 .AppendASCII("Preferences");
1464
1465 InitializeInstalledExtensionService(pref_path, source_install_dir);
1466
1467 // This is the directory that is going to be deleted, so make sure it actually
1468 // is there before the garbage collection.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001469 ASSERT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001470 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
1471
1472 service_->Init();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01001473 // A delayed task to call GarbageCollectExtensions is posted by
1474 // ExtensionService::Init. As the test won't wait for the delayed task to
1475 // be called, call it manually instead.
1476 service_->GarbageCollectExtensions();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001477 // Wait for GarbageCollectExtensions task to complete.
1478 loop_.RunUntilIdle();
1479
1480 // Verify that the pending update for the first extension got installed.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001481 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001482 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001483 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001484 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001485 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001486 "hpiknbiabeeppbpihjehijgoemciehgk/2")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001487 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001488 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
1489
1490 // Make sure update information got deleted.
1491 ExtensionPrefs* prefs = service_->extension_prefs();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001492 EXPECT_FALSE(
1493 prefs->GetDelayedInstallInfo("bjafgdebaacbbbecmhlhpofkepfkgcpa"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001494}
1495
Ben Murdocheb525c52013-07-10 11:40:50 +01001496// Test various cases for delayed install because of missing imports.
1497TEST_F(ExtensionServiceTest, PendingImports) {
1498 InitPluginService();
1499
1500 base::FilePath source_install_dir = data_dir_
1501 .AppendASCII("pending_updates_with_imports")
1502 .AppendASCII("Extensions");
1503 base::FilePath pref_path = source_install_dir
1504 .DirName()
1505 .AppendASCII("Preferences");
1506
1507 InitializeInstalledExtensionService(pref_path, source_install_dir);
1508
1509 // Verify there are no pending extensions initially.
1510 EXPECT_FALSE(service_->pending_extension_manager()->HasPendingExtensions());
1511
1512 service_->Init();
1513 // Wait for GarbageCollectExtensions task to complete.
1514 loop_.RunUntilIdle();
1515
1516 // These extensions are used by the extensions we test below, they must be
1517 // installed.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001518 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Ben Murdocheb525c52013-07-10 11:40:50 +01001519 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001520 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII(
Ben Murdocheb525c52013-07-10 11:40:50 +01001521 "hpiknbiabeeppbpihjehijgoemciehgk/2")));
1522
1523 // Each of these extensions should have been rejected because of dependencies
1524 // that cannot be satisfied.
1525 ExtensionPrefs* prefs = service_->extension_prefs();
1526 EXPECT_FALSE(
1527 prefs->GetDelayedInstallInfo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
1528 EXPECT_FALSE(
1529 prefs->GetInstalledExtensionInfo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
1530 EXPECT_FALSE(
1531 prefs->GetDelayedInstallInfo("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
1532 EXPECT_FALSE(
1533 prefs->GetInstalledExtensionInfo("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
1534 EXPECT_FALSE(
1535 prefs->GetDelayedInstallInfo("cccccccccccccccccccccccccccccccc"));
1536 EXPECT_FALSE(
1537 prefs->GetInstalledExtensionInfo("cccccccccccccccccccccccccccccccc"));
1538
1539 // Make sure the import started for the extension with a dependency.
1540 EXPECT_TRUE(
1541 prefs->GetDelayedInstallInfo("behllobkkfkfnphdnhnkndlbkcpglgmj"));
1542 EXPECT_EQ(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
1543 prefs->GetDelayedInstallReason("behllobkkfkfnphdnhnkndlbkcpglgmj"));
1544
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001545 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
Ben Murdocheb525c52013-07-10 11:40:50 +01001546 "behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0")));
1547
1548 EXPECT_TRUE(service_->pending_extension_manager()->HasPendingExtensions());
1549 std::string pending_id("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
1550 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(pending_id));
1551 // Remove it because we are not testing the pending extension manager's
1552 // ability to download and install extensions.
1553 EXPECT_TRUE(service_->pending_extension_manager()->Remove(pending_id));
1554}
1555
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001556// Test installing extensions. This test tries to install few extensions using
1557// crx files. If you need to change those crx files, feel free to repackage
1558// them, throw away the key used and change the id's above.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001559TEST_F(ExtensionServiceTest, InstallExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001560 InitializeEmptyExtensionService();
1561
1562 // Extensions not enabled.
1563 set_extensions_enabled(false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001564 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001565 InstallCRX(path, INSTALL_FAILED);
1566 set_extensions_enabled(true);
1567
1568 ValidatePrefKeyCount(0);
1569
1570 // A simple extension that should install without error.
1571 path = data_dir_.AppendASCII("good.crx");
1572 InstallCRX(path, INSTALL_NEW);
1573 // TODO(erikkay): verify the contents of the installed extension.
1574
1575 int pref_count = 0;
1576 ValidatePrefKeyCount(++pref_count);
1577 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001578 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001579
1580 // An extension with page actions.
1581 path = data_dir_.AppendASCII("page_action.crx");
1582 InstallCRX(path, INSTALL_NEW);
1583 ValidatePrefKeyCount(++pref_count);
1584 ValidateIntegerPref(page_action, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001585 ValidateIntegerPref(page_action, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001586
1587 // Bad signature.
1588 path = data_dir_.AppendASCII("bad_signature.crx");
1589 InstallCRX(path, INSTALL_FAILED);
1590 ValidatePrefKeyCount(pref_count);
1591
1592 // 0-length extension file.
1593 path = data_dir_.AppendASCII("not_an_extension.crx");
1594 InstallCRX(path, INSTALL_FAILED);
1595 ValidatePrefKeyCount(pref_count);
1596
1597 // Bad magic number.
1598 path = data_dir_.AppendASCII("bad_magic.crx");
1599 InstallCRX(path, INSTALL_FAILED);
1600 ValidatePrefKeyCount(pref_count);
1601
1602 // Extensions cannot have folders or files that have underscores except in
1603 // certain whitelisted cases (eg _locales). This is an example of a broader
1604 // class of validation that we do to the directory structure of the extension.
1605 // We did not used to handle this correctly for installation.
1606 path = data_dir_.AppendASCII("bad_underscore.crx");
1607 InstallCRX(path, INSTALL_FAILED);
1608 ValidatePrefKeyCount(pref_count);
1609
1610 // TODO(erikkay): add more tests for many of the failure cases.
1611 // TODO(erikkay): add tests for upgrade cases.
1612}
1613
Ben Murdochca12bfa2013-07-23 11:17:05 +01001614struct MockInstallObserver : public extensions::InstallObserver {
1615 MockInstallObserver() {
1616 }
1617
1618 virtual ~MockInstallObserver() {
1619 }
1620
1621 virtual void OnBeginExtensionInstall(
1622 const std::string& extension_id,
1623 const std::string& extension_name,
1624 const gfx::ImageSkia& installing_icon,
1625 bool is_app,
1626 bool is_platform_app) OVERRIDE {
1627 }
1628
1629 virtual void OnDownloadProgress(const std::string& extension_id,
1630 int percent_downloaded) OVERRIDE {
1631 }
1632
1633 virtual void OnExtensionInstalled(const Extension* extension) OVERRIDE {
1634 last_extension_installed = extension->id();
1635 }
1636
1637 virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE {
1638 }
1639
1640 virtual void OnExtensionLoaded(const Extension* extension) OVERRIDE {
1641 }
1642
1643 virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE {
1644 }
1645
1646 virtual void OnExtensionUninstalled(const Extension* extension) OVERRIDE {
1647 last_extension_uninstalled = extension->id();
1648 }
1649
1650 virtual void OnAppsReordered() OVERRIDE {
1651 }
1652
1653 virtual void OnAppInstalledToAppList(
1654 const std::string& extension_id) OVERRIDE {
1655 }
1656
1657 virtual void OnShutdown() OVERRIDE {
1658 }
1659
1660 std::string last_extension_installed;
1661 std::string last_extension_uninstalled;
1662};
1663
1664// Test that correct notifications are sent to InstallTracker observers on
1665// extension install and uninstall.
1666TEST_F(ExtensionServiceTest, InstallObserverNotified) {
1667 InitializeEmptyExtensionService();
1668
1669 extensions::InstallTracker* tracker(
1670 extensions::InstallTrackerFactory::GetForProfile(profile_.get()));
1671 MockInstallObserver observer;
1672 tracker->AddObserver(&observer);
1673
1674 // A simple extension that should install without error.
1675 ASSERT_TRUE(observer.last_extension_installed.empty());
1676 base::FilePath path = data_dir_.AppendASCII("good.crx");
1677 InstallCRX(path, INSTALL_NEW);
1678 ASSERT_EQ(good_crx, observer.last_extension_installed);
1679
1680 // Uninstall the extension.
1681 ASSERT_TRUE(observer.last_extension_uninstalled.empty());
1682 UninstallExtension(good_crx, false);
1683 ASSERT_EQ(good_crx, observer.last_extension_uninstalled);
1684
1685 tracker->RemoveObserver(&observer);
1686}
1687
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001688// Tests that flags passed to OnExternalExtensionFileFound() make it to the
1689// extension object.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001690TEST_F(ExtensionServiceTest, InstallingExternalExtensionWithFlags) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001691 const char kPrefFromBookmark[] = "from_bookmark";
1692
1693 InitializeEmptyExtensionService();
1694
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001695 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001696 set_extensions_enabled(true);
1697
1698 // Register and install an external extension.
1699 Version version("1.0.0.0");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001700 if (service_->OnExternalExtensionFileFound(
1701 good_crx,
1702 &version,
1703 path,
1704 Manifest::EXTERNAL_PREF,
1705 Extension::FROM_BOOKMARK,
1706 false /* mark_acknowledged */)) {
1707 content::WindowedNotificationObserver(
1708 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1709 content::NotificationService::AllSources()).Wait();
1710 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001711
1712 const Extension* extension = service_->GetExtensionById(good_crx, false);
1713 ASSERT_TRUE(extension);
1714 ASSERT_TRUE(extension->from_bookmark());
1715 ValidateBooleanPref(good_crx, kPrefFromBookmark, true);
1716
1717 // Upgrade to version 2.0, the flag should be preserved.
1718 path = data_dir_.AppendASCII("good2.crx");
1719 UpdateExtension(good_crx, path, ENABLED);
1720 ValidateBooleanPref(good_crx, kPrefFromBookmark, true);
1721 extension = service_->GetExtensionById(good_crx, false);
1722 ASSERT_TRUE(extension);
1723 ASSERT_TRUE(extension->from_bookmark());
1724}
1725
1726// Test the handling of Extension::EXTERNAL_EXTENSION_UNINSTALLED
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001727TEST_F(ExtensionServiceTest, UninstallingExternalExtensions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001728 InitializeEmptyExtensionService();
1729
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001730 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001731 set_extensions_enabled(true);
1732
1733 Version version("1.0.0.0");
1734 // Install an external extension.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001735 if (service_->OnExternalExtensionFileFound(good_crx, &version,
1736 path, Manifest::EXTERNAL_PREF,
1737 Extension::NO_FLAGS, false)) {
1738 content::WindowedNotificationObserver(
1739 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1740 content::NotificationService::AllSources()).Wait();
1741 }
1742
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001743 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1744
1745 // Uninstall it and check that its killbit gets set.
1746 UninstallExtension(good_crx, false);
1747 ValidateIntegerPref(good_crx, "location",
1748 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1749
1750 // Try to re-install it externally. This should fail because of the killbit.
1751 service_->OnExternalExtensionFileFound(good_crx, &version,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001752 path, Manifest::EXTERNAL_PREF,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001753 Extension::NO_FLAGS, false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001754 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001755 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
1756 ValidateIntegerPref(good_crx, "location",
1757 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1758
1759 version = Version("1.0.0.1");
1760 // Repeat the same thing with a newer version of the extension.
1761 path = data_dir_.AppendASCII("good2.crx");
1762 service_->OnExternalExtensionFileFound(good_crx, &version,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001763 path, Manifest::EXTERNAL_PREF,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001764 Extension::NO_FLAGS, false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001765 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001766 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
1767 ValidateIntegerPref(good_crx, "location",
1768 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1769
1770 // Try adding the same extension from an external update URL.
1771 ASSERT_FALSE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
1772 good_crx,
1773 GURL("http:://fake.update/url"),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001774 Manifest::EXTERNAL_PREF_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001775
1776 ASSERT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
1777}
1778
1779// Test that uninstalling an external extension does not crash when
1780// the extension could not be loaded.
1781// This extension shown in preferences file requires an experimental permission.
1782// It could not be loaded without such permission.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001783TEST_F(ExtensionServiceTest, UninstallingNotLoadedExtension) {
1784 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001785 .AppendASCII("good")
1786 .AppendASCII("Extensions");
1787 // The preference contains an external extension
1788 // that requires 'experimental' permission.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001789 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001790 .DirName()
1791 .AppendASCII("PreferencesExperimental");
1792
1793 // Aforementioned extension will not be loaded if
1794 // there is no '--enable-experimental-extension-apis' command line flag.
1795 InitializeInstalledExtensionService(pref_path, source_install_dir);
1796
1797 service_->Init();
1798
1799 // Check and try to uninstall it.
1800 // If we don't check whether the extension is loaded before we uninstall it
1801 // in CheckExternalUninstall, a crash will happen here because we will get or
1802 // dereference a NULL pointer (extension) inside UninstallExtension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001803 MockExtensionProvider provider(NULL, Manifest::EXTERNAL_REGISTRY);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001804 service_->OnExternalProviderReady(&provider);
1805}
1806
1807// Test that external extensions with incorrect IDs are not installed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001808TEST_F(ExtensionServiceTest, FailOnWrongId) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001809 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001810 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001811 set_extensions_enabled(true);
1812
1813 Version version("1.0.0.0");
1814
1815 const std::string wrong_id = all_zero;
1816 const std::string correct_id = good_crx;
1817 ASSERT_NE(correct_id, wrong_id);
1818
1819 // Install an external extension with an ID from the external
1820 // source that is not equal to the ID in the extension manifest.
1821 service_->OnExternalExtensionFileFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001822 wrong_id, &version, path, Manifest::EXTERNAL_PREF,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001823 Extension::NO_FLAGS, false);
1824
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001825 content::WindowedNotificationObserver(
1826 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1827 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001828 ASSERT_FALSE(service_->GetExtensionById(good_crx, false));
1829
1830 // Try again with the right ID. Expect success.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001831 if (service_->OnExternalExtensionFileFound(
1832 correct_id, &version, path, Manifest::EXTERNAL_PREF,
1833 Extension::NO_FLAGS, false)) {
1834 content::WindowedNotificationObserver(
1835 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1836 content::NotificationService::AllSources()).Wait();
1837 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001838 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1839}
1840
1841// Test that external extensions with incorrect versions are not installed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001842TEST_F(ExtensionServiceTest, FailOnWrongVersion) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001843 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001844 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001845 set_extensions_enabled(true);
1846
1847 // Install an external extension with a version from the external
1848 // source that is not equal to the version in the extension manifest.
1849 Version wrong_version("1.2.3.4");
1850 service_->OnExternalExtensionFileFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001851 good_crx, &wrong_version, path, Manifest::EXTERNAL_PREF,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001852 Extension::NO_FLAGS, false);
1853
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001854 content::WindowedNotificationObserver(
1855 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1856 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001857 ASSERT_FALSE(service_->GetExtensionById(good_crx, false));
1858
1859 // Try again with the right version. Expect success.
1860 service_->pending_extension_manager()->Remove(good_crx);
1861 Version correct_version("1.0.0.0");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001862 if (service_->OnExternalExtensionFileFound(
1863 good_crx, &correct_version, path, Manifest::EXTERNAL_PREF,
1864 Extension::NO_FLAGS, false)) {
1865 content::WindowedNotificationObserver(
1866 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
1867 content::NotificationService::AllSources()).Wait();
1868 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001869 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1870}
1871
1872// Install a user script (they get converted automatically to an extension)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001873TEST_F(ExtensionServiceTest, InstallUserScript) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001874 // The details of script conversion are tested elsewhere, this just tests
1875 // integration with ExtensionService.
1876 InitializeEmptyExtensionService();
1877
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001878 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001879 .AppendASCII("user_script_basic.user.js");
1880
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001881 ASSERT_TRUE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001882 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
1883 installer->set_allow_silent_install(true);
1884 installer->InstallUserScript(
1885 path,
1886 GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js"));
1887
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001888 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001889 std::vector<string16> errors = GetErrors();
1890 EXPECT_TRUE(installed_) << "Nothing was installed.";
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001891 EXPECT_FALSE(was_update_) << path.value();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001892 ASSERT_EQ(1u, loaded_.size()) << "Nothing was loaded.";
1893 EXPECT_EQ(0u, errors.size()) << "There were errors: "
1894 << JoinString(errors, ',');
1895 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) <<
1896 path.value();
1897
1898 installed_ = NULL;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001899 was_update_ = false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001900 loaded_.clear();
1901 ExtensionErrorReporter::GetInstance()->ClearErrors();
1902}
1903
1904// Extensions don't install during shutdown.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001905TEST_F(ExtensionServiceTest, InstallExtensionDuringShutdown) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001906 InitializeEmptyExtensionService();
1907
1908 // Simulate shutdown.
1909 service_->set_browser_terminating_for_test(true);
1910
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001911 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001912 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
1913 installer->set_allow_silent_install(true);
1914 installer->InstallCrx(path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001915 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001916
1917 EXPECT_FALSE(installed_) << "Extension installed during shutdown.";
1918 ASSERT_EQ(0u, loaded_.size()) << "Extension loaded during shutdown.";
1919}
1920
1921// This tests that the granted permissions preferences are correctly set when
1922// installing an extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001923TEST_F(ExtensionServiceTest, GrantedPermissions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001924 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001925 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001926 .AppendASCII("permissions");
1927
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001928 base::FilePath pem_path = path.AppendASCII("unknown.pem");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001929 path = path.AppendASCII("unknown");
1930
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001931 ASSERT_TRUE(base::PathExists(pem_path));
1932 ASSERT_TRUE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001933
1934 ExtensionPrefs* prefs = service_->extension_prefs();
1935
1936 APIPermissionSet expected_api_perms;
1937 URLPatternSet expected_host_perms;
1938
1939 // Make sure there aren't any granted permissions before the
1940 // extension is installed.
1941 scoped_refptr<PermissionSet> known_perms(
1942 prefs->GetGrantedPermissions(permissions_crx));
1943 EXPECT_FALSE(known_perms.get());
1944
1945 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1946
1947 EXPECT_EQ(0u, GetErrors().size());
1948 ASSERT_EQ(1u, service_->extensions()->size());
1949 EXPECT_EQ(permissions_crx, extension->id());
1950
1951 // Verify that the valid API permissions have been recognized.
1952 expected_api_perms.insert(APIPermission::kTab);
1953
1954 AddPattern(&expected_host_perms, "http://*.google.com/*");
1955 AddPattern(&expected_host_perms, "https://*.google.com/*");
1956 AddPattern(&expected_host_perms, "http://*.google.com.hk/*");
1957 AddPattern(&expected_host_perms, "http://www.example.com/*");
1958
1959 known_perms = prefs->GetGrantedPermissions(extension->id());
1960 EXPECT_TRUE(known_perms.get());
1961 EXPECT_FALSE(known_perms->IsEmpty());
1962 EXPECT_EQ(expected_api_perms, known_perms->apis());
1963 EXPECT_FALSE(known_perms->HasEffectiveFullAccess());
1964 EXPECT_EQ(expected_host_perms, known_perms->effective_hosts());
1965}
1966
1967
1968#if !defined(OS_CHROMEOS)
1969// This tests that the granted permissions preferences are correctly set for
1970// default apps.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001971TEST_F(ExtensionServiceTest, DefaultAppsGrantedPermissions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001972 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001973 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001974 .AppendASCII("permissions");
1975
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001976 base::FilePath pem_path = path.AppendASCII("unknown.pem");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001977 path = path.AppendASCII("unknown");
1978
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001979 ASSERT_TRUE(base::PathExists(pem_path));
1980 ASSERT_TRUE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001981
1982 ExtensionPrefs* prefs = service_->extension_prefs();
1983
1984 APIPermissionSet expected_api_perms;
1985 URLPatternSet expected_host_perms;
1986
1987 // Make sure there aren't any granted permissions before the
1988 // extension is installed.
1989 scoped_refptr<PermissionSet> known_perms(
1990 prefs->GetGrantedPermissions(permissions_crx));
1991 EXPECT_FALSE(known_perms.get());
1992
1993 const Extension* extension = PackAndInstallCRX(
1994 path, pem_path, INSTALL_NEW, Extension::WAS_INSTALLED_BY_DEFAULT);
1995
1996 EXPECT_EQ(0u, GetErrors().size());
1997 ASSERT_EQ(1u, service_->extensions()->size());
1998 EXPECT_EQ(permissions_crx, extension->id());
1999
2000 // Verify that the valid API permissions have been recognized.
2001 expected_api_perms.insert(APIPermission::kTab);
2002
2003 known_perms = prefs->GetGrantedPermissions(extension->id());
2004 EXPECT_TRUE(known_perms.get());
2005 EXPECT_FALSE(known_perms->IsEmpty());
2006 EXPECT_EQ(expected_api_perms, known_perms->apis());
2007 EXPECT_FALSE(known_perms->HasEffectiveFullAccess());
2008}
2009#endif
2010
2011#if !defined(OS_CHROMEOS)
2012// Tests that the granted permissions full_access bit gets set correctly when
2013// an extension contains an NPAPI plugin. Don't run this test on Chrome OS
2014// since they don't support plugins.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002015TEST_F(ExtensionServiceTest, GrantedFullAccessPermissions) {
2016 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002017
2018 InitializeEmptyExtensionService();
2019
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002020 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002021 .AppendASCII("good")
2022 .AppendASCII("Extensions")
2023 .AppendASCII(good1)
2024 .AppendASCII("2");
2025
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002026 ASSERT_TRUE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002027 const Extension* extension = PackAndInstallCRX(path, INSTALL_NEW);
2028 EXPECT_EQ(0u, GetErrors().size());
2029 EXPECT_EQ(1u, service_->extensions()->size());
2030 ExtensionPrefs* prefs = service_->extension_prefs();
2031
2032 scoped_refptr<PermissionSet> permissions(
2033 prefs->GetGrantedPermissions(extension->id()));
2034 EXPECT_FALSE(permissions->IsEmpty());
2035 EXPECT_TRUE(permissions->HasEffectiveFullAccess());
2036 EXPECT_FALSE(permissions->apis().empty());
2037 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kPlugin));
2038
2039 // Full access implies full host access too...
2040 EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
2041}
2042#endif
2043
2044// Tests that the extension is disabled when permissions are missing from
2045// the extension's granted permissions preferences. (This simulates updating
2046// the browser to a version which recognizes more permissions).
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002047TEST_F(ExtensionServiceTest, GrantedAPIAndHostPermissions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002048 InitializeEmptyExtensionService();
2049
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002050 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002051 .AppendASCII("permissions")
2052 .AppendASCII("unknown");
2053
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002054 ASSERT_TRUE(base::PathExists(path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002055
2056 const Extension* extension = PackAndInstallCRX(path, INSTALL_NEW);
2057
2058 EXPECT_EQ(0u, GetErrors().size());
2059 EXPECT_EQ(1u, service_->extensions()->size());
2060 std::string extension_id = extension->id();
2061
2062 ExtensionPrefs* prefs = service_->extension_prefs();
2063
2064 APIPermissionSet expected_api_permissions;
2065 URLPatternSet expected_host_permissions;
2066
2067 expected_api_permissions.insert(APIPermission::kTab);
2068 AddPattern(&expected_host_permissions, "http://*.google.com/*");
2069 AddPattern(&expected_host_permissions, "https://*.google.com/*");
2070 AddPattern(&expected_host_permissions, "http://*.google.com.hk/*");
2071 AddPattern(&expected_host_permissions, "http://www.example.com/*");
2072
2073 std::set<std::string> host_permissions;
2074
2075 // Test that the extension is disabled when an API permission is missing from
2076 // the extension's granted api permissions preference. (This simulates
2077 // updating the browser to a version which recognizes a new API permission).
2078 SetPref(extension_id, "granted_permissions.api",
2079 new ListValue(), "granted_permissions.api");
2080 service_->ReloadExtensions();
2081
2082 EXPECT_EQ(1u, service_->disabled_extensions()->size());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002083 extension = service_->disabled_extensions()->begin()->get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002084
2085 ASSERT_TRUE(prefs->IsExtensionDisabled(extension_id));
2086 ASSERT_FALSE(service_->IsExtensionEnabled(extension_id));
2087 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
2088
2089 // Now grant and re-enable the extension, making sure the prefs are updated.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002090 service_->GrantPermissionsAndEnableExtension(extension);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002091
2092 ASSERT_FALSE(prefs->IsExtensionDisabled(extension_id));
2093 ASSERT_TRUE(service_->IsExtensionEnabled(extension_id));
2094 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
2095
2096 scoped_refptr<PermissionSet> current_perms(
2097 prefs->GetGrantedPermissions(extension_id));
2098 ASSERT_TRUE(current_perms.get());
2099 ASSERT_FALSE(current_perms->IsEmpty());
2100 ASSERT_FALSE(current_perms->HasEffectiveFullAccess());
2101 ASSERT_EQ(expected_api_permissions, current_perms->apis());
2102 ASSERT_EQ(expected_host_permissions, current_perms->effective_hosts());
2103
2104 // Tests that the extension is disabled when a host permission is missing from
2105 // the extension's granted host permissions preference. (This simulates
2106 // updating the browser to a version which recognizes additional host
2107 // permissions).
2108 host_permissions.clear();
2109 current_perms = NULL;
2110
2111 host_permissions.insert("http://*.google.com/*");
2112 host_permissions.insert("https://*.google.com/*");
2113 host_permissions.insert("http://*.google.com.hk/*");
2114
2115 ListValue* api_permissions = new ListValue();
2116 api_permissions->Append(
2117 Value::CreateStringValue("tabs"));
2118 SetPref(extension_id, "granted_permissions.api",
2119 api_permissions, "granted_permissions.api");
2120 SetPrefStringSet(
2121 extension_id, "granted_permissions.scriptable_host", host_permissions);
2122
2123 service_->ReloadExtensions();
2124
2125 EXPECT_EQ(1u, service_->disabled_extensions()->size());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002126 extension = service_->disabled_extensions()->begin()->get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002127
2128 ASSERT_TRUE(prefs->IsExtensionDisabled(extension_id));
2129 ASSERT_FALSE(service_->IsExtensionEnabled(extension_id));
2130 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
2131
2132 // Now grant and re-enable the extension, making sure the prefs are updated.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002133 service_->GrantPermissionsAndEnableExtension(extension);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002134
2135 ASSERT_TRUE(service_->IsExtensionEnabled(extension_id));
2136 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
2137
2138 current_perms = prefs->GetGrantedPermissions(extension_id);
2139 ASSERT_TRUE(current_perms.get());
2140 ASSERT_FALSE(current_perms->IsEmpty());
2141 ASSERT_FALSE(current_perms->HasEffectiveFullAccess());
2142 ASSERT_EQ(expected_api_permissions, current_perms->apis());
2143 ASSERT_EQ(expected_host_permissions, current_perms->effective_hosts());
2144}
2145
2146// Test Packaging and installing an extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002147TEST_F(ExtensionServiceTest, PackExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002148 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002149 base::FilePath input_directory = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002150 .AppendASCII("good")
2151 .AppendASCII("Extensions")
2152 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
2153 .AppendASCII("1.0.0.0");
2154
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002155 base::ScopedTempDir temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002156 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002157 base::FilePath output_directory = temp_dir.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002158
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002159 base::FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
2160 base::FilePath privkey_path(output_directory.AppendASCII("privkey.pem"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002161
2162 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002163 ASSERT_TRUE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002164 privkey_path, ExtensionCreator::kNoRunFlags));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002165 ASSERT_TRUE(base::PathExists(crx_path));
2166 ASSERT_TRUE(base::PathExists(privkey_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002167
2168 // Repeat the run with the pem file gone, and no special flags
2169 // Should refuse to overwrite the existing crx.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002170 base::DeleteFile(privkey_path, false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002171 ASSERT_FALSE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002172 privkey_path, ExtensionCreator::kNoRunFlags));
2173
2174 // OK, now try it with a flag to overwrite existing crx. Should work.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002175 ASSERT_TRUE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002176 privkey_path, ExtensionCreator::kOverwriteCRX));
2177
2178 // Repeat the run allowing existing crx, but the existing pem is still
2179 // an error. Should fail.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002180 ASSERT_FALSE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002181 privkey_path, ExtensionCreator::kOverwriteCRX));
2182
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002183 ASSERT_TRUE(base::PathExists(privkey_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002184 InstallCRX(crx_path, INSTALL_NEW);
2185
2186 // Try packing with invalid paths.
2187 creator.reset(new ExtensionCreator());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002188 ASSERT_FALSE(
2189 creator->Run(base::FilePath(), base::FilePath(), base::FilePath(),
2190 base::FilePath(), ExtensionCreator::kOverwriteCRX));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002191
2192 // Try packing an empty directory. Should fail because an empty directory is
2193 // not a valid extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002194 base::ScopedTempDir temp_dir2;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002195 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
2196 creator.reset(new ExtensionCreator());
2197 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002198 base::FilePath(), ExtensionCreator::kOverwriteCRX));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002199
2200 // Try packing with an invalid manifest.
2201 std::string invalid_manifest_content = "I am not a manifest.";
2202 ASSERT_TRUE(file_util::WriteFile(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002203 temp_dir2.path().Append(extensions::kManifestFilename),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002204 invalid_manifest_content.c_str(), invalid_manifest_content.size()));
2205 creator.reset(new ExtensionCreator());
2206 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002207 base::FilePath(), ExtensionCreator::kOverwriteCRX));
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01002208
2209 // Try packing with a private key that is a valid key, but invalid for the
2210 // extension.
2211 base::FilePath bad_private_key_dir = data_dir_.AppendASCII("bad_private_key");
2212 crx_path = output_directory.AppendASCII("bad_private_key.crx");
2213 privkey_path = data_dir_.AppendASCII("bad_private_key.pem");
2214 ASSERT_FALSE(creator->Run(bad_private_key_dir, crx_path, base::FilePath(),
2215 privkey_path, ExtensionCreator::kOverwriteCRX));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002216}
2217
2218// Test Packaging and installing an extension whose name contains punctuation.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002219TEST_F(ExtensionServiceTest, PackPunctuatedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002220 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002221 base::FilePath input_directory = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002222 .AppendASCII("good")
2223 .AppendASCII("Extensions")
2224 .AppendASCII(good0)
2225 .AppendASCII("1.0.0.0");
2226
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002227 base::ScopedTempDir temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002228 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
2229
2230 // Extension names containing punctuation, and the expected names for the
2231 // packed extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002232 const base::FilePath punctuated_names[] = {
2233 base::FilePath(FILE_PATH_LITERAL("this.extensions.name.has.periods")),
2234 base::FilePath(FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod")),
2235 base::FilePath(FILE_PATH_LITERAL("thisextensionhasaslashinitsname/")).
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002236 NormalizePathSeparators(),
2237 };
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002238 const base::FilePath expected_crx_names[] = {
2239 base::FilePath(FILE_PATH_LITERAL("this.extensions.name.has.periods.crx")),
2240 base::FilePath(
2241 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.crx")),
2242 base::FilePath(FILE_PATH_LITERAL("thisextensionhasaslashinitsname.crx")),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002243 };
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002244 const base::FilePath expected_private_key_names[] = {
2245 base::FilePath(FILE_PATH_LITERAL("this.extensions.name.has.periods.pem")),
2246 base::FilePath(
2247 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.pem")),
2248 base::FilePath(FILE_PATH_LITERAL("thisextensionhasaslashinitsname.pem")),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002249 };
2250
2251 for (size_t i = 0; i < arraysize(punctuated_names); ++i) {
2252 SCOPED_TRACE(punctuated_names[i].value().c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002253 base::FilePath output_dir = temp_dir.path().Append(punctuated_names[i]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002254
2255 // Copy the extension into the output directory, as PackExtensionJob doesn't
2256 // let us choose where to output the packed extension.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002257 ASSERT_TRUE(base::CopyDirectory(input_directory, output_dir, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002258
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002259 base::FilePath expected_crx_path =
2260 temp_dir.path().Append(expected_crx_names[i]);
2261 base::FilePath expected_private_key_path =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002262 temp_dir.path().Append(expected_private_key_names[i]);
2263 PackExtensionTestClient pack_client(expected_crx_path,
2264 expected_private_key_path);
2265 scoped_refptr<extensions::PackExtensionJob> packer(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002266 new extensions::PackExtensionJob(&pack_client, output_dir,
2267 base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002268 ExtensionCreator::kOverwriteCRX));
2269 packer->Start();
2270
2271 // The packer will post a notification task to the current thread's message
2272 // loop when it is finished. We manually run the loop here so that we
2273 // block and catch the notification; otherwise, the process would exit.
2274 // This call to |Run()| is matched by a call to |Quit()| in the
2275 // |PackExtensionTestClient|'s notification handling code.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002276 base::MessageLoop::current()->Run();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002277
2278 if (HasFatalFailure())
2279 return;
2280
2281 InstallCRX(expected_crx_path, INSTALL_NEW);
2282 }
2283}
2284
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002285TEST_F(ExtensionServiceTest, PackExtensionContainingKeyFails) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002286 InitializeEmptyExtensionService();
2287
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002288 base::ScopedTempDir extension_temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002289 ASSERT_TRUE(extension_temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002290 base::FilePath input_directory = extension_temp_dir.path().AppendASCII("ext");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002291 ASSERT_TRUE(base::CopyDirectory(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002292 data_dir_
2293 .AppendASCII("good")
2294 .AppendASCII("Extensions")
2295 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
2296 .AppendASCII("1.0.0.0"),
2297 input_directory,
2298 /*recursive=*/true));
2299
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002300 base::ScopedTempDir output_temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002301 ASSERT_TRUE(output_temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002302 base::FilePath output_directory = output_temp_dir.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002303
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002304 base::FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
2305 base::FilePath privkey_path(output_directory.AppendASCII("privkey.pem"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002306
2307 // Pack the extension once to get a private key.
2308 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002309 ASSERT_TRUE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002310 privkey_path, ExtensionCreator::kNoRunFlags))
2311 << creator->error_message();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002312 ASSERT_TRUE(base::PathExists(crx_path));
2313 ASSERT_TRUE(base::PathExists(privkey_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002314
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002315 base::DeleteFile(crx_path, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002316 // Move the pem file into the extension.
Ben Murdocheb525c52013-07-10 11:40:50 +01002317 base::Move(privkey_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002318 input_directory.AppendASCII("privkey.pem"));
2319
2320 // This pack should fail because of the contained private key.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002321 EXPECT_FALSE(creator->Run(input_directory, crx_path, base::FilePath(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002322 privkey_path, ExtensionCreator::kNoRunFlags));
2323 EXPECT_THAT(creator->error_message(),
2324 testing::ContainsRegex(
2325 "extension includes the key file.*privkey.pem"));
2326}
2327
2328// Test Packaging and installing an extension using an openssl generated key.
2329// The openssl is generated with the following:
2330// > openssl genrsa -out privkey.pem 1024
2331// > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem
2332// The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a
2333// PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002334TEST_F(ExtensionServiceTest, PackExtensionOpenSSLKey) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002335 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002336 base::FilePath input_directory = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002337 .AppendASCII("good")
2338 .AppendASCII("Extensions")
2339 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
2340 .AppendASCII("1.0.0.0");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002341 base::FilePath privkey_path(data_dir_.AppendASCII(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002342 "openssl_privkey_asn1.pem"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002343 ASSERT_TRUE(base::PathExists(privkey_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002344
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002345 base::ScopedTempDir temp_dir;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002346 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002347 base::FilePath output_directory = temp_dir.path();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002348
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002349 base::FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002350
2351 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
2352 ASSERT_TRUE(creator->Run(input_directory, crx_path, privkey_path,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002353 base::FilePath(), ExtensionCreator::kOverwriteCRX));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002354
2355 InstallCRX(crx_path, INSTALL_NEW);
2356}
2357
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002358TEST_F(ExtensionServiceTest, InstallTheme) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002359 InitializeEmptyExtensionService();
2360
2361 // A theme.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002362 base::FilePath path = data_dir_.AppendASCII("theme.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002363 InstallCRX(path, INSTALL_NEW);
2364 int pref_count = 0;
2365 ValidatePrefKeyCount(++pref_count);
2366 ValidateIntegerPref(theme_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002367 ValidateIntegerPref(theme_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002368
2369 // A theme when extensions are disabled. Themes can be installed, even when
2370 // extensions are disabled.
2371 set_extensions_enabled(false);
2372 path = data_dir_.AppendASCII("theme2.crx");
2373 InstallCRX(path, INSTALL_NEW);
2374 ValidatePrefKeyCount(++pref_count);
2375 ValidateIntegerPref(theme2_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002376 ValidateIntegerPref(theme2_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002377
2378 // A theme with extension elements. Themes cannot have extension elements,
2379 // so any such elements (like content scripts) should be ignored.
2380 set_extensions_enabled(true);
2381 {
2382 path = data_dir_.AppendASCII("theme_with_extension.crx");
2383 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2384 ValidatePrefKeyCount(++pref_count);
2385 ASSERT_TRUE(extension);
2386 EXPECT_TRUE(extension->is_theme());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002387 EXPECT_EQ(
2388 0u,
2389 extensions::ContentScriptsInfo::GetContentScripts(extension).size());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002390 }
2391
2392 // A theme with image resources missing (misspelt path).
2393 path = data_dir_.AppendASCII("theme_missing_image.crx");
2394 InstallCRX(path, INSTALL_FAILED);
2395 ValidatePrefKeyCount(pref_count);
2396}
2397
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002398TEST_F(ExtensionServiceTest, LoadLocalizedTheme) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002399 // Load.
2400 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002401 base::FilePath extension_path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002402 .AppendASCII("theme_i18n");
2403
2404 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002405 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002406 EXPECT_EQ(0u, GetErrors().size());
2407 ASSERT_EQ(1u, loaded_.size());
2408 EXPECT_EQ(1u, service_->extensions()->size());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002409 const Extension* theme = service_->extensions()->begin()->get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002410 EXPECT_EQ("name", theme->name());
2411 EXPECT_EQ("description", theme->description());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002412
2413 // Cleanup the "Cached Theme.pak" file. Ideally, this would be installed in a
2414 // temporary directory, but it automatically installs to the extension's
2415 // directory, and we don't want to copy the whole extension for a unittest.
2416 base::FilePath theme_file = extension_path.Append(chrome::kThemePackFilename);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002417 ASSERT_TRUE(base::PathExists(theme_file));
2418 ASSERT_TRUE(base::DeleteFile(theme_file, false)); // Not recursive.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002419}
2420
2421// Tests that we can change the ID of an unpacked extension by adding a key
2422// to its manifest.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002423TEST_F(ExtensionServiceTest, UnpackedExtensionCanChangeID) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002424 InitializeEmptyExtensionService();
2425
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002426 base::ScopedTempDir temp;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002427 ASSERT_TRUE(temp.CreateUniqueTempDir());
2428
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002429 base::FilePath extension_path = temp.path();
2430 base::FilePath manifest_path =
2431 extension_path.Append(extensions::kManifestFilename);
2432 base::FilePath manifest_no_key = data_dir_.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002433 AppendASCII("unpacked").
2434 AppendASCII("manifest_no_key.json");
2435
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002436 base::FilePath manifest_with_key = data_dir_.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002437 AppendASCII("unpacked").
2438 AppendASCII("manifest_with_key.json");
2439
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002440 ASSERT_TRUE(base::PathExists(manifest_no_key));
2441 ASSERT_TRUE(base::PathExists(manifest_with_key));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002442
2443 // Load the unpacked extension with no key.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002444 base::CopyFile(manifest_no_key, manifest_path);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002445 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
2446
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002447 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002448 EXPECT_EQ(0u, GetErrors().size());
2449 ASSERT_EQ(1u, loaded_.size());
2450 EXPECT_EQ(1u, service_->extensions()->size());
2451
2452 // Add the key to the manifest.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002453 base::CopyFile(manifest_with_key, manifest_path);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002454 loaded_.clear();
2455
2456 // Reload the extensions.
2457 service_->ReloadExtensions();
2458 const Extension* extension = service_->GetExtensionById(unpacked, false);
2459 EXPECT_EQ(unpacked, extension->id());
2460 ASSERT_EQ(1u, loaded_.size());
2461
2462 // TODO(jstritar): Right now this just makes sure we don't crash and burn, but
2463 // we should also test that preferences are preserved.
2464}
2465
2466#if defined(OS_POSIX)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002467TEST_F(ExtensionServiceTest, UnpackedExtensionMayContainSymlinkedFiles) {
2468 base::FilePath source_data_dir = data_dir_.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002469 AppendASCII("unpacked").
2470 AppendASCII("symlinks_allowed");
2471
2472 // Paths to test data files.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002473 base::FilePath source_manifest = source_data_dir.AppendASCII("manifest.json");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002474 ASSERT_TRUE(base::PathExists(source_manifest));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002475 base::FilePath source_icon = source_data_dir.AppendASCII("icon.png");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002476 ASSERT_TRUE(base::PathExists(source_icon));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002477
2478 // Set up the temporary extension directory.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002479 base::ScopedTempDir temp;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002480 ASSERT_TRUE(temp.CreateUniqueTempDir());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002481 base::FilePath extension_path = temp.path();
2482 base::FilePath manifest = extension_path.Append(
2483 extensions::kManifestFilename);
2484 base::FilePath icon_symlink = extension_path.AppendASCII("icon.png");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002485 base::CopyFile(source_manifest, manifest);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002486 file_util::CreateSymbolicLink(source_icon, icon_symlink);
2487
2488 // Load extension.
2489 InitializeEmptyExtensionService();
2490 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002491 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002492
2493 EXPECT_TRUE(GetErrors().empty());
2494 ASSERT_EQ(1u, loaded_.size());
2495 EXPECT_EQ(1u, service_->extensions()->size());
2496}
2497#endif
2498
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002499TEST_F(ExtensionServiceTest, InstallLocalizedTheme) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002500 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002501 base::FilePath theme_path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002502 .AppendASCII("theme_i18n");
2503
2504 const Extension* theme = PackAndInstallCRX(theme_path, INSTALL_NEW);
2505
2506 EXPECT_EQ(0u, GetErrors().size());
2507 EXPECT_EQ(1u, service_->extensions()->size());
2508 EXPECT_EQ("name", theme->name());
2509 EXPECT_EQ("description", theme->description());
2510}
2511
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002512TEST_F(ExtensionServiceTest, InstallApps) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002513 InitializeEmptyExtensionService();
2514
2515 // An empty app.
2516 const Extension* app = PackAndInstallCRX(data_dir_.AppendASCII("app1"),
2517 INSTALL_NEW);
2518 int pref_count = 0;
2519 ValidatePrefKeyCount(++pref_count);
2520 ASSERT_EQ(1u, service_->extensions()->size());
2521 ValidateIntegerPref(app->id(), "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002522 ValidateIntegerPref(app->id(), "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002523
2524 // Another app with non-overlapping extent. Should succeed.
2525 PackAndInstallCRX(data_dir_.AppendASCII("app2"), INSTALL_NEW);
2526 ValidatePrefKeyCount(++pref_count);
2527
2528 // A third app whose extent overlaps the first. Should fail.
2529 PackAndInstallCRX(data_dir_.AppendASCII("app3"), INSTALL_FAILED);
2530 ValidatePrefKeyCount(pref_count);
2531}
2532
2533// Tests that file access is OFF by default.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002534TEST_F(ExtensionServiceTest, DefaultFileAccess) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002535 InitializeEmptyExtensionService();
2536 const Extension* extension =
2537 PackAndInstallCRX(data_dir_
2538 .AppendASCII("permissions")
2539 .AppendASCII("files"),
2540 INSTALL_NEW);
2541 EXPECT_EQ(0u, GetErrors().size());
2542 EXPECT_EQ(1u, service_->extensions()->size());
2543 EXPECT_FALSE(service_->extension_prefs()->AllowFileAccess(extension->id()));
2544}
2545
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002546TEST_F(ExtensionServiceTest, UpdateApps) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002547 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002548 base::FilePath extensions_path = data_dir_.AppendASCII("app_update");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002549
2550 // First install v1 of a hosted app.
2551 const Extension* extension =
2552 InstallCRX(extensions_path.AppendASCII("v1.crx"), INSTALL_NEW);
2553 ASSERT_EQ(1u, service_->extensions()->size());
2554 std::string id = extension->id();
2555 ASSERT_EQ(std::string("1"), extension->version()->GetString());
2556
2557 // Now try updating to v2.
2558 UpdateExtension(id,
2559 extensions_path.AppendASCII("v2.crx"),
2560 ENABLED);
2561 ASSERT_EQ(std::string("2"),
2562 service_->GetExtensionById(id, false)->version()->GetString());
2563}
2564
2565// Verifies that the NTP page and launch ordinals are kept when updating apps.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002566TEST_F(ExtensionServiceTest, UpdateAppsRetainOrdinals) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002567 InitializeEmptyExtensionService();
2568 ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002569 base::FilePath extensions_path = data_dir_.AppendASCII("app_update");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002570
2571 // First install v1 of a hosted app.
2572 const Extension* extension =
2573 InstallCRX(extensions_path.AppendASCII("v1.crx"), INSTALL_NEW);
2574 ASSERT_EQ(1u, service_->extensions()->size());
2575 std::string id = extension->id();
2576 ASSERT_EQ(std::string("1"), extension->version()->GetString());
2577
2578 // Modify the ordinals so we can distinguish them from the defaults.
2579 syncer::StringOrdinal new_page_ordinal =
2580 sorting->GetPageOrdinal(id).CreateAfter();
2581 syncer::StringOrdinal new_launch_ordinal =
2582 sorting->GetAppLaunchOrdinal(id).CreateBefore();
2583
2584 sorting->SetPageOrdinal(id, new_page_ordinal);
2585 sorting->SetAppLaunchOrdinal(id, new_launch_ordinal);
2586
2587 // Now try updating to v2.
2588 UpdateExtension(id, extensions_path.AppendASCII("v2.crx"), ENABLED);
2589 ASSERT_EQ(std::string("2"),
2590 service_->GetExtensionById(id, false)->version()->GetString());
2591
2592 // Verify that the ordinals match.
2593 ASSERT_TRUE(new_page_ordinal.Equals(sorting->GetPageOrdinal(id)));
2594 ASSERT_TRUE(new_launch_ordinal.Equals(sorting->GetAppLaunchOrdinal(id)));
2595}
2596
2597// Ensures that the CWS has properly initialized ordinals.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002598TEST_F(ExtensionServiceTest, EnsureCWSOrdinalsInitialized) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002599 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002600 service_->component_loader()->Add(
2601 IDR_WEBSTORE_MANIFEST, base::FilePath(FILE_PATH_LITERAL("web_store")));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002602 service_->Init();
2603
2604 ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting();
2605 EXPECT_TRUE(
2606 sorting->GetPageOrdinal(extension_misc::kWebStoreAppId).IsValid());
2607 EXPECT_TRUE(
2608 sorting->GetAppLaunchOrdinal(extension_misc::kWebStoreAppId).IsValid());
2609}
2610
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002611TEST_F(ExtensionServiceTest, InstallAppsWithUnlimitedStorage) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002612 InitializeEmptyExtensionService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002613 EXPECT_TRUE(service_->extensions()->is_empty());
2614
2615 int pref_count = 0;
2616
2617 // Install app1 with unlimited storage.
2618 const Extension* extension =
2619 PackAndInstallCRX(data_dir_.AppendASCII("app1"), INSTALL_NEW);
2620 ValidatePrefKeyCount(++pref_count);
2621 ASSERT_EQ(1u, service_->extensions()->size());
2622 const std::string id1 = extension->id();
2623 EXPECT_TRUE(extension->HasAPIPermission(
2624 APIPermission::kUnlimitedStorage));
2625 EXPECT_TRUE(extension->web_extent().MatchesURL(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002626 extensions::AppLaunchInfo::GetFullLaunchURL(extension)));
2627 const GURL origin1(
2628 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002629 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
2630 IsStorageUnlimited(origin1));
2631
2632 // Install app2 from the same origin with unlimited storage.
2633 extension = PackAndInstallCRX(data_dir_.AppendASCII("app2"), INSTALL_NEW);
2634 ValidatePrefKeyCount(++pref_count);
2635 ASSERT_EQ(2u, service_->extensions()->size());
2636 const std::string id2 = extension->id();
2637 EXPECT_TRUE(extension->HasAPIPermission(
2638 APIPermission::kUnlimitedStorage));
2639 EXPECT_TRUE(extension->web_extent().MatchesURL(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002640 extensions::AppLaunchInfo::GetFullLaunchURL(extension)));
2641 const GURL origin2(
2642 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002643 EXPECT_EQ(origin1, origin2);
2644 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
2645 IsStorageUnlimited(origin2));
2646
2647
2648 // Uninstall one of them, unlimited storage should still be granted
2649 // to the origin.
2650 UninstallExtension(id1, false);
2651 EXPECT_EQ(1u, service_->extensions()->size());
2652 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
2653 IsStorageUnlimited(origin1));
2654
2655 // Uninstall the other, unlimited storage should be revoked.
2656 UninstallExtension(id2, false);
2657 EXPECT_EQ(0u, service_->extensions()->size());
2658 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
2659 IsStorageUnlimited(origin2));
2660}
2661
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002662TEST_F(ExtensionServiceTest, InstallAppsAndCheckStorageProtection) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002663 InitializeEmptyExtensionService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002664 EXPECT_TRUE(service_->extensions()->is_empty());
2665
2666 int pref_count = 0;
2667
2668 const Extension* extension =
2669 PackAndInstallCRX(data_dir_.AppendASCII("app1"), INSTALL_NEW);
2670 ValidatePrefKeyCount(++pref_count);
2671 ASSERT_EQ(1u, service_->extensions()->size());
2672 EXPECT_TRUE(extension->is_app());
2673 const std::string id1 = extension->id();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002674 const GURL origin1(
2675 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002676 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
2677 IsStorageProtected(origin1));
2678
2679 // App 4 has a different origin (maps.google.com).
2680 extension = PackAndInstallCRX(data_dir_.AppendASCII("app4"), INSTALL_NEW);
2681 ValidatePrefKeyCount(++pref_count);
2682 ASSERT_EQ(2u, service_->extensions()->size());
2683 const std::string id2 = extension->id();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002684 const GURL origin2(
2685 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002686 ASSERT_NE(origin1, origin2);
2687 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
2688 IsStorageProtected(origin2));
2689
2690 UninstallExtension(id1, false);
2691 EXPECT_EQ(1u, service_->extensions()->size());
2692
2693 UninstallExtension(id2, false);
2694
2695 EXPECT_TRUE(service_->extensions()->is_empty());
2696 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
2697 IsStorageProtected(origin1));
2698 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
2699 IsStorageProtected(origin2));
2700}
2701
2702// Test that when an extension version is reinstalled, nothing happens.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002703TEST_F(ExtensionServiceTest, Reinstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002704 InitializeEmptyExtensionService();
2705
2706 // A simple extension that should install without error.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002707 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002708 InstallCRX(path, INSTALL_NEW);
2709
2710 ValidatePrefKeyCount(1);
2711 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002712 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002713
2714 // Reinstall the same version, it should overwrite the previous one.
2715 InstallCRX(path, INSTALL_UPDATED);
2716
2717 ValidatePrefKeyCount(1);
2718 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002719 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002720}
2721
2722// Test that we can determine if extensions came from the
2723// Chrome web store.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002724TEST_F(ExtensionServiceTest, FromWebStore) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002725 InitializeEmptyExtensionService();
2726
2727 // A simple extension that should install without error.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002728 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002729 // Not from web store.
2730 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2731 std::string id = extension->id();
2732
2733 ValidatePrefKeyCount(1);
2734 ValidateBooleanPref(good_crx, "from_webstore", false);
2735 ASSERT_FALSE(extension->from_webstore());
2736
2737 // Test install from web store.
2738 InstallCRXFromWebStore(path, INSTALL_UPDATED); // From web store.
2739
2740 ValidatePrefKeyCount(1);
2741 ValidateBooleanPref(good_crx, "from_webstore", true);
2742
2743 // Reload so extension gets reinitialized with new value.
2744 service_->ReloadExtensions();
2745 extension = service_->GetExtensionById(id, false);
2746 ASSERT_TRUE(extension->from_webstore());
2747
2748 // Upgrade to version 2.0
2749 path = data_dir_.AppendASCII("good2.crx");
2750 UpdateExtension(good_crx, path, ENABLED);
2751 ValidatePrefKeyCount(1);
2752 ValidateBooleanPref(good_crx, "from_webstore", true);
2753}
2754
2755// Test upgrading a signed extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002756TEST_F(ExtensionServiceTest, UpgradeSignedGood) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002757 InitializeEmptyExtensionService();
2758
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002759 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002760 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2761 std::string id = extension->id();
2762
2763 ASSERT_EQ("1.0.0.0", extension->version()->GetString());
2764 ASSERT_EQ(0u, GetErrors().size());
2765
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002766 // Upgrade to version 1.0.0.1.
2767 // Also test that the extension's old and new title are correctly retrieved.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002768 path = data_dir_.AppendASCII("good2.crx");
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002769 InstallCRX(path, INSTALL_UPDATED, Extension::NO_FLAGS, "My extension 1");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002770 extension = service_->GetExtensionById(id, false);
2771
2772 ASSERT_EQ("1.0.0.1", extension->version()->GetString());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002773 ASSERT_EQ("My updated extension 1", extension->name());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002774 ASSERT_EQ(0u, GetErrors().size());
2775}
2776
2777// Test upgrading a signed extension with a bad signature.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002778TEST_F(ExtensionServiceTest, UpgradeSignedBad) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002779 InitializeEmptyExtensionService();
2780
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002781 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002782 InstallCRX(path, INSTALL_NEW);
2783
2784 // Try upgrading with a bad signature. This should fail during the unpack,
2785 // because the key will not match the signature.
2786 path = data_dir_.AppendASCII("bad_signature.crx");
2787 InstallCRX(path, INSTALL_FAILED);
2788}
2789
2790// Test a normal update via the UpdateExtension API
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002791TEST_F(ExtensionServiceTest, UpdateExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002792 InitializeEmptyExtensionService();
2793
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002794 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002795
2796 const Extension* good = InstallCRX(path, INSTALL_NEW);
2797 ASSERT_EQ("1.0.0.0", good->VersionString());
2798 ASSERT_EQ(good_crx, good->id());
2799
2800 path = data_dir_.AppendASCII("good2.crx");
2801 UpdateExtension(good_crx, path, ENABLED);
2802 ASSERT_EQ("1.0.0.1",
2803 service_->GetExtensionById(good_crx, false)->
2804 version()->GetString());
2805}
2806
2807// Extensions should not be updated during browser shutdown.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002808TEST_F(ExtensionServiceTest, UpdateExtensionDuringShutdown) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002809 InitializeEmptyExtensionService();
2810
2811 // Install an extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002812 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002813 const Extension* good = InstallCRX(path, INSTALL_NEW);
2814 ASSERT_EQ(good_crx, good->id());
2815
2816 // Simulate shutdown.
2817 service_->set_browser_terminating_for_test(true);
2818
2819 // Update should fail and extension should not be updated.
2820 path = data_dir_.AppendASCII("good2.crx");
2821 bool updated = service_->UpdateExtension(good_crx, path, GURL(), NULL);
2822 ASSERT_FALSE(updated);
2823 ASSERT_EQ("1.0.0.0",
2824 service_->GetExtensionById(good_crx, false)->
2825 version()->GetString());
2826}
2827
2828// Test updating a not-already-installed extension - this should fail
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002829TEST_F(ExtensionServiceTest, UpdateNotInstalledExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002830 InitializeEmptyExtensionService();
2831
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002832 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002833 UpdateExtension(good_crx, path, UPDATED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002834 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002835
2836 ASSERT_EQ(0u, service_->extensions()->size());
2837 ASSERT_FALSE(installed_);
2838 ASSERT_EQ(0u, loaded_.size());
2839}
2840
2841// Makes sure you can't downgrade an extension via UpdateExtension
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002842TEST_F(ExtensionServiceTest, UpdateWillNotDowngrade) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002843 InitializeEmptyExtensionService();
2844
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002845 base::FilePath path = data_dir_.AppendASCII("good2.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002846
2847 const Extension* good = InstallCRX(path, INSTALL_NEW);
2848 ASSERT_EQ("1.0.0.1", good->VersionString());
2849 ASSERT_EQ(good_crx, good->id());
2850
2851 // Change path from good2.crx -> good.crx
2852 path = data_dir_.AppendASCII("good.crx");
2853 UpdateExtension(good_crx, path, FAILED);
2854 ASSERT_EQ("1.0.0.1",
2855 service_->GetExtensionById(good_crx, false)->
2856 version()->GetString());
2857}
2858
2859// Make sure calling update with an identical version does nothing
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002860TEST_F(ExtensionServiceTest, UpdateToSameVersionIsNoop) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002861 InitializeEmptyExtensionService();
2862
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002863 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002864
2865 const Extension* good = InstallCRX(path, INSTALL_NEW);
2866 ASSERT_EQ(good_crx, good->id());
2867 UpdateExtension(good_crx, path, FAILED_SILENTLY);
2868}
2869
2870// Tests that updating an extension does not clobber old state.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002871TEST_F(ExtensionServiceTest, UpdateExtensionPreservesState) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002872 InitializeEmptyExtensionService();
2873
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002874 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002875
2876 const Extension* good = InstallCRX(path, INSTALL_NEW);
2877 ASSERT_EQ("1.0.0.0", good->VersionString());
2878 ASSERT_EQ(good_crx, good->id());
2879
2880 // Disable it and allow it to run in incognito. These settings should carry
2881 // over to the updated version.
2882 service_->DisableExtension(good->id(), Extension::DISABLE_USER_ACTION);
2883 service_->SetIsIncognitoEnabled(good->id(), true);
2884 service_->extension_prefs()->SetDidExtensionEscalatePermissions(good, true);
2885
2886 path = data_dir_.AppendASCII("good2.crx");
2887 UpdateExtension(good_crx, path, INSTALLED);
2888 ASSERT_EQ(1u, service_->disabled_extensions()->size());\
2889 const Extension* good2 = service_->GetExtensionById(good_crx, true);
2890 ASSERT_EQ("1.0.0.1", good2->version()->GetString());
2891 EXPECT_TRUE(service_->IsIncognitoEnabled(good2->id()));
2892 EXPECT_TRUE(service_->extension_prefs()->DidExtensionEscalatePermissions(
2893 good2->id()));
2894}
2895
2896// Tests that updating preserves extension location.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002897TEST_F(ExtensionServiceTest, UpdateExtensionPreservesLocation) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002898 InitializeEmptyExtensionService();
2899
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002900 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002901
2902 const Extension* good =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002903 InstallCRXWithLocation(path, Manifest::EXTERNAL_PREF, INSTALL_NEW);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002904
2905 ASSERT_EQ("1.0.0.0", good->VersionString());
2906 ASSERT_EQ(good_crx, good->id());
2907
2908 path = data_dir_.AppendASCII("good2.crx");
2909 UpdateExtension(good_crx, path, ENABLED);
2910 const Extension* good2 = service_->GetExtensionById(good_crx, false);
2911 ASSERT_EQ("1.0.0.1", good2->version()->GetString());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002912 EXPECT_EQ(good2->location(), Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002913}
2914
2915// Makes sure that LOAD extension types can downgrade.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002916TEST_F(ExtensionServiceTest, LoadExtensionsCanDowngrade) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002917 InitializeEmptyExtensionService();
2918
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002919 base::ScopedTempDir temp;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002920 ASSERT_TRUE(temp.CreateUniqueTempDir());
2921
2922 // We'll write the extension manifest dynamically to a temporary path
2923 // to make it easier to change the version number.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002924 base::FilePath extension_path = temp.path();
2925 base::FilePath manifest_path =
2926 extension_path.Append(extensions::kManifestFilename);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002927 ASSERT_FALSE(base::PathExists(manifest_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002928
2929 // Start with version 2.0.
2930 DictionaryValue manifest;
2931 manifest.SetString("version", "2.0");
2932 manifest.SetString("name", "LOAD Downgrade Test");
2933 manifest.SetInteger("manifest_version", 2);
2934
2935 JSONFileValueSerializer serializer(manifest_path);
2936 ASSERT_TRUE(serializer.Serialize(manifest));
2937
2938 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002939 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002940
2941 EXPECT_EQ(0u, GetErrors().size());
2942 ASSERT_EQ(1u, loaded_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002943 EXPECT_EQ(Manifest::UNPACKED, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002944 EXPECT_EQ(1u, service_->extensions()->size());
2945 EXPECT_EQ("2.0", loaded_[0]->VersionString());
2946
2947 // Now set the version number to 1.0, reload the extensions and verify that
2948 // the downgrade was accepted.
2949 manifest.SetString("version", "1.0");
2950 ASSERT_TRUE(serializer.Serialize(manifest));
2951
2952 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002953 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002954
2955 EXPECT_EQ(0u, GetErrors().size());
2956 ASSERT_EQ(1u, loaded_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002957 EXPECT_EQ(Manifest::UNPACKED, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002958 EXPECT_EQ(1u, service_->extensions()->size());
2959 EXPECT_EQ("1.0", loaded_[0]->VersionString());
2960}
2961
2962#if !defined(OS_CHROMEOS)
2963// LOAD extensions with plugins require approval.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002964TEST_F(ExtensionServiceTest, LoadExtensionsWithPlugins) {
2965 base::FilePath extension_with_plugin_path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002966 .AppendASCII("good")
2967 .AppendASCII("Extensions")
2968 .AppendASCII(good1)
2969 .AppendASCII("2");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002970 base::FilePath extension_no_plugin_path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002971 .AppendASCII("good")
2972 .AppendASCII("Extensions")
2973 .AppendASCII(good2)
2974 .AppendASCII("1.0");
2975
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002976 InitPluginService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002977 InitializeEmptyExtensionService();
2978 InitializeExtensionProcessManager();
2979 service_->set_show_extensions_prompts(true);
2980
2981 // Start by canceling any install prompts.
2982 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
2983 switches::kAppsGalleryInstallAutoConfirmForTests,
2984 "cancel");
2985
2986 // The extension that has a plugin should not install.
2987 extensions::UnpackedInstaller::Create(service_)->Load(
2988 extension_with_plugin_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002989 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002990 EXPECT_EQ(0u, GetErrors().size());
2991 EXPECT_EQ(0u, loaded_.size());
2992 EXPECT_EQ(0u, service_->extensions()->size());
2993 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2994
2995 // But the extension with no plugin should since there's no prompt.
Ben Murdochca12bfa2013-07-23 11:17:05 +01002996 ExtensionErrorReporter::GetInstance()->ClearErrors();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002997 extensions::UnpackedInstaller::Create(service_)->Load(
2998 extension_no_plugin_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002999 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003000 EXPECT_EQ(0u, GetErrors().size());
3001 EXPECT_EQ(1u, loaded_.size());
3002 EXPECT_EQ(1u, service_->extensions()->size());
3003 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3004 EXPECT_TRUE(service_->extensions()->Contains(good2));
3005
3006 // The plugin extension should install if we accept the dialog.
3007 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
3008 switches::kAppsGalleryInstallAutoConfirmForTests,
3009 "accept");
3010
Ben Murdochca12bfa2013-07-23 11:17:05 +01003011 ExtensionErrorReporter::GetInstance()->ClearErrors();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003012 extensions::UnpackedInstaller::Create(service_)->Load(
3013 extension_with_plugin_path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003014 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003015 EXPECT_EQ(0u, GetErrors().size());
3016 EXPECT_EQ(2u, loaded_.size());
3017 EXPECT_EQ(2u, service_->extensions()->size());
3018 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3019 EXPECT_TRUE(service_->extensions()->Contains(good1));
3020 EXPECT_TRUE(service_->extensions()->Contains(good2));
3021
3022 // Make sure the granted permissions have been setup.
3023 scoped_refptr<PermissionSet> permissions(
3024 service_->extension_prefs()->GetGrantedPermissions(good1));
3025 EXPECT_FALSE(permissions->IsEmpty());
3026 EXPECT_TRUE(permissions->HasEffectiveFullAccess());
3027 EXPECT_FALSE(permissions->apis().empty());
3028 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kPlugin));
3029
3030 // We should be able to reload the extension without getting another prompt.
3031 loaded_.clear();
3032 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
3033 switches::kAppsGalleryInstallAutoConfirmForTests,
3034 "cancel");
3035
3036 service_->ReloadExtension(good1);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003037 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003038 EXPECT_EQ(1u, loaded_.size());
3039 EXPECT_EQ(2u, service_->extensions()->size());
3040 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3041}
3042#endif
3043
3044namespace {
3045
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003046bool IsExtension(const Extension* extension) {
3047 return extension->GetType() == Manifest::TYPE_EXTENSION;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003048}
3049
3050} // namespace
3051
3052// Test adding a pending extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003053TEST_F(ExtensionServiceTest, AddPendingExtensionFromSync) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003054 InitializeEmptyExtensionService();
3055
3056 const std::string kFakeId(all_zero);
3057 const GURL kFakeUpdateURL("http:://fake.update/url");
3058 const bool kFakeInstallSilently(true);
3059
3060 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3061 kFakeId, kFakeUpdateURL, &IsExtension,
3062 kFakeInstallSilently));
3063
3064 const extensions::PendingExtensionInfo* pending_extension_info;
3065 ASSERT_TRUE((pending_extension_info = service_->pending_extension_manager()->
3066 GetById(kFakeId)));
3067 EXPECT_EQ(kFakeUpdateURL, pending_extension_info->update_url());
3068 EXPECT_EQ(&IsExtension, pending_extension_info->should_allow_install_);
3069 EXPECT_EQ(kFakeInstallSilently, pending_extension_info->install_silently());
3070}
3071
3072namespace {
3073const char kGoodId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
3074const char kGoodUpdateURL[] = "http://good.update/url";
3075const bool kGoodIsFromSync = true;
3076const bool kGoodInstallSilently = true;
3077} // namespace
3078
3079// Test updating a pending extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003080TEST_F(ExtensionServiceTest, UpdatePendingExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003081 InitializeEmptyExtensionService();
3082 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3083 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
3084 kGoodInstallSilently));
3085 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3086
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003087 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003088 UpdateExtension(kGoodId, path, ENABLED);
3089
3090 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3091
3092 const Extension* extension = service_->GetExtensionById(kGoodId, true);
3093 ASSERT_TRUE(extension);
3094}
3095
3096namespace {
3097
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003098bool IsTheme(const Extension* extension) {
3099 return extension->is_theme();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003100}
3101
3102} // namespace
3103
3104// Test updating a pending theme.
3105// Disabled due to ASAN failure. http://crbug.com/108320
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003106TEST_F(ExtensionServiceTest, DISABLED_UpdatePendingTheme) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003107 InitializeEmptyExtensionService();
3108 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3109 theme_crx, GURL(), &IsTheme, false));
3110 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3111
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003112 base::FilePath path = data_dir_.AppendASCII("theme.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003113 UpdateExtension(theme_crx, path, ENABLED);
3114
3115 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3116
3117 const Extension* extension = service_->GetExtensionById(theme_crx, true);
3118 ASSERT_TRUE(extension);
3119
3120 EXPECT_FALSE(
3121 service_->extension_prefs()->IsExtensionDisabled(extension->id()));
3122 EXPECT_TRUE(service_->IsExtensionEnabled(theme_crx));
3123}
3124
3125#if defined(OS_CHROMEOS)
3126// Always fails on ChromeOS: http://crbug.com/79737
3127#define MAYBE_UpdatePendingExternalCrx DISABLED_UpdatePendingExternalCrx
3128#else
3129#define MAYBE_UpdatePendingExternalCrx UpdatePendingExternalCrx
3130#endif
3131// Test updating a pending CRX as if the source is an external extension
3132// with an update URL. In this case we don't know if the CRX is a theme
3133// or not.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003134TEST_F(ExtensionServiceTest, MAYBE_UpdatePendingExternalCrx) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003135 InitializeEmptyExtensionService();
3136 EXPECT_TRUE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003137 theme_crx, GURL(), Manifest::EXTERNAL_PREF_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003138
3139 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3140
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003141 base::FilePath path = data_dir_.AppendASCII("theme.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003142 UpdateExtension(theme_crx, path, ENABLED);
3143
3144 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3145
3146 const Extension* extension = service_->GetExtensionById(theme_crx, true);
3147 ASSERT_TRUE(extension);
3148
3149 EXPECT_FALSE(
3150 service_->extension_prefs()->IsExtensionDisabled(extension->id()));
3151 EXPECT_TRUE(service_->IsExtensionEnabled(extension->id()));
3152 EXPECT_FALSE(service_->IsIncognitoEnabled(extension->id()));
3153}
3154
3155// Test updating a pending CRX as if the source is an external extension
3156// with an update URL. The external update should overwrite a sync update,
3157// but a sync update should not overwrite a non-sync update.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003158TEST_F(ExtensionServiceTest, UpdatePendingExternalCrxWinsOverSync) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003159 InitializeEmptyExtensionService();
3160
3161 // Add a crx to be installed from the update mechanism.
3162 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3163 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
3164 kGoodInstallSilently));
3165
3166 // Check that there is a pending crx, with is_from_sync set to true.
3167 const extensions::PendingExtensionInfo* pending_extension_info;
3168 ASSERT_TRUE((pending_extension_info = service_->pending_extension_manager()->
3169 GetById(kGoodId)));
3170 EXPECT_TRUE(pending_extension_info->is_from_sync());
3171
3172 // Add a crx to be updated, with the same ID, from a non-sync source.
3173 EXPECT_TRUE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003174 kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_PREF_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003175
3176 // Check that there is a pending crx, with is_from_sync set to false.
3177 ASSERT_TRUE((pending_extension_info = service_->pending_extension_manager()->
3178 GetById(kGoodId)));
3179 EXPECT_FALSE(pending_extension_info->is_from_sync());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003180 EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003181 pending_extension_info->install_source());
3182
3183 // Add a crx to be installed from the update mechanism.
3184 EXPECT_FALSE(service_->pending_extension_manager()->AddFromSync(
3185 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
3186 kGoodInstallSilently));
3187
3188 // Check that the external, non-sync update was not overridden.
3189 ASSERT_TRUE((pending_extension_info = service_->pending_extension_manager()->
3190 GetById(kGoodId)));
3191 EXPECT_FALSE(pending_extension_info->is_from_sync());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003192 EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003193 pending_extension_info->install_source());
3194}
3195
3196// Updating a theme should fail if the updater is explicitly told that
3197// the CRX is not a theme.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003198TEST_F(ExtensionServiceTest, UpdatePendingCrxThemeMismatch) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003199 InitializeEmptyExtensionService();
3200 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3201 theme_crx, GURL(), &IsExtension, true));
3202
3203 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3204
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003205 base::FilePath path = data_dir_.AppendASCII("theme.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003206 UpdateExtension(theme_crx, path, FAILED_SILENTLY);
3207
3208 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
3209
3210 const Extension* extension = service_->GetExtensionById(theme_crx, true);
3211 ASSERT_FALSE(extension);
3212}
3213
3214// TODO(akalin): Test updating a pending extension non-silently once
3215// we can mock out ExtensionInstallUI and inject our version into
3216// UpdateExtension().
3217
3218// Test updating a pending extension which fails the should-install test.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003219TEST_F(ExtensionServiceTest, UpdatePendingExtensionFailedShouldInstallTest) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003220 InitializeEmptyExtensionService();
3221 // Add pending extension with a flipped is_theme.
3222 EXPECT_TRUE(service_->pending_extension_manager()->AddFromSync(
3223 kGoodId, GURL(kGoodUpdateURL), &IsTheme, kGoodInstallSilently));
3224 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3225
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003226 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003227 UpdateExtension(kGoodId, path, UPDATED);
3228
3229 // TODO(akalin): Figure out how to check that the extensions
3230 // directory is cleaned up properly in OnExtensionInstalled().
3231
3232 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3233}
3234
3235// TODO(akalin): Figure out how to test that installs of pending
3236// unsyncable extensions are blocked.
3237
3238// Test updating a pending extension for one that is not pending.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003239TEST_F(ExtensionServiceTest, UpdatePendingExtensionNotPending) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003240 InitializeEmptyExtensionService();
3241
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003242 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003243 UpdateExtension(kGoodId, path, UPDATED);
3244
3245 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3246}
3247
3248// Test updating a pending extension for one that is already
3249// installed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003250TEST_F(ExtensionServiceTest, UpdatePendingExtensionAlreadyInstalled) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003251 InitializeEmptyExtensionService();
3252
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003253 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003254 const Extension* good = InstallCRX(path, INSTALL_NEW);
3255 ASSERT_EQ(1u, service_->extensions()->size());
3256
3257 EXPECT_FALSE(good->is_theme());
3258
3259 // Use AddExtensionImpl() as AddFrom*() would balk.
3260 service_->pending_extension_manager()->AddExtensionImpl(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003261 good->id(), extensions::ManifestURL::GetUpdateURL(good),
3262 Version(), &IsExtension, kGoodIsFromSync,
3263 kGoodInstallSilently, Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003264 UpdateExtension(good->id(), path, ENABLED);
3265
3266 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
3267}
3268
3269// Test pref settings for blacklist and unblacklist extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003270TEST_F(ExtensionServiceTest, SetUnsetBlacklistInPrefs) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003271 InitializeEmptyExtensionService();
3272 std::vector<std::string> blacklist;
3273 blacklist.push_back(good0);
3274 blacklist.push_back("invalid_id"); // an invalid id
3275 blacklist.push_back(good1);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003276 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3277 "v1");
3278
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003279 // Make sure pref is updated
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003280 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003281
3282 // blacklist is set for good0,1,2
3283 ValidateBooleanPref(good0, "blacklist", true);
3284 ValidateBooleanPref(good1, "blacklist", true);
3285 // invalid_id should not be inserted to pref.
3286 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
3287
3288 // remove good1, add good2
3289 blacklist.pop_back();
3290 blacklist.push_back(good2);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003291 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3292 "v2");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003293
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003294 // only good0 and good1 should be set
3295 ValidateBooleanPref(good0, "blacklist", true);
3296 EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
3297 ValidateBooleanPref(good2, "blacklist", true);
3298 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
3299}
3300
3301// Unload installed extension from blacklist.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003302TEST_F(ExtensionServiceTest, UnloadBlacklistedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003303 InitializeEmptyExtensionService();
3304
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003305 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003306
3307 const Extension* good = InstallCRX(path, INSTALL_NEW);
3308 EXPECT_EQ(good_crx, good->id());
3309 UpdateExtension(good_crx, path, FAILED_SILENTLY);
3310
3311 std::vector<std::string> blacklist;
3312 blacklist.push_back(good_crx);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003313 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3314 "v1");
3315
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003316 // Make sure pref is updated
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003317 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003318
3319 // Now, the good_crx is blacklisted.
3320 ValidateBooleanPref(good_crx, "blacklist", true);
3321 EXPECT_EQ(0u, service_->extensions()->size());
3322
3323 // Remove good_crx from blacklist
3324 blacklist.pop_back();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003325 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3326 "v2");
3327
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003328 // Make sure pref is updated
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003329 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003330 // blacklist value should not be set for good_crx
3331 EXPECT_FALSE(IsPrefExist(good_crx, "blacklist"));
3332}
3333
3334// Unload installed extension from blacklist.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003335TEST_F(ExtensionServiceTest, BlacklistedExtensionWillNotInstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003336 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003337
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01003338 // Fake the blacklisting of good_crx by pretending that we get an update
3339 // which includes it.
3340 extensions::Blacklist* blacklist =
3341 ExtensionSystem::Get(profile_.get())->blacklist();
3342 blacklist->SetFromUpdater(std::vector<std::string>(1, good_crx), "v1");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003343
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01003344 // Now good_crx is blacklisted.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003345 ValidateBooleanPref(good_crx, "blacklist", true);
3346
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01003347 // We cannot install good_crx.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003348 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01003349 // HACK: specify WAS_INSTALLED_BY_DEFAULT so that test machinery doesn't
3350 // decide to install this silently. Somebody should fix these tests, all
3351 // 6,000 lines of them. Hah!
3352 InstallCRX(path, INSTALL_FAILED, Extension::WAS_INSTALLED_BY_DEFAULT);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003353 EXPECT_EQ(0u, service_->extensions()->size());
3354 ValidateBooleanPref(good_crx, "blacklist", true);
3355}
3356
3357// Unload blacklisted extension on policy change.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003358TEST_F(ExtensionServiceTest, UnloadBlacklistedExtensionPolicy) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003359 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003360 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003361
3362 const Extension* good = InstallCRX(path, INSTALL_NEW);
3363 EXPECT_EQ(good_crx, good->id());
3364 UpdateExtension(good_crx, path, FAILED_SILENTLY);
3365 EXPECT_EQ(1u, service_->extensions()->size());
3366
3367 base::ListValue whitelist;
3368 PrefService* prefs = service_->extension_prefs()->pref_service();
3369 whitelist.Append(base::Value::CreateStringValue(good_crx));
3370 prefs->Set(prefs::kExtensionInstallAllowList, whitelist);
3371
3372 std::vector<std::string> blacklist;
3373 blacklist.push_back(good_crx);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003374 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3375 "v1");
3376
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003377 // Make sure pref is updated
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003378 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003379
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003380 // The good_crx is blacklisted and the whitelist doesn't negate it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003381 ValidateBooleanPref(good_crx, "blacklist", true);
3382 EXPECT_EQ(0u, service_->extensions()->size());
3383}
3384
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003385// Test loading extensions from the profile directory, except
3386// blacklisted ones.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003387TEST_F(ExtensionServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003388 // Initialize the test dir with a good Preferences/extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003389 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003390 .AppendASCII("good")
3391 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003392 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003393 .DirName()
3394 .AppendASCII("Preferences");
3395 InitializeInstalledExtensionService(pref_path, source_install_dir);
3396
3397 // Blacklist good1.
3398 std::vector<std::string> blacklist;
3399 blacklist.push_back(good1);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003400 ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
3401 "v1");
3402
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003403 // Make sure pref is updated
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003404 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003405
3406 ValidateBooleanPref(good1, "blacklist", true);
3407
3408 // Load extensions.
3409 service_->Init();
3410
3411 std::vector<string16> errors = GetErrors();
3412 for (std::vector<string16>::iterator err = errors.begin();
3413 err != errors.end(); ++err) {
3414 LOG(ERROR) << *err;
3415 }
3416 ASSERT_EQ(2u, loaded_.size());
3417
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003418 EXPECT_TRUE(service_->GetInstalledExtension(good1));
3419 int include_mask = ExtensionService::INCLUDE_EVERYTHING &
3420 ~ExtensionService::INCLUDE_BLACKLISTED;
3421 EXPECT_FALSE(service_->GetExtensionById(good1, include_mask));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003422}
3423
3424// Will not install extension blacklisted by policy.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003425TEST_F(ExtensionServiceTest, BlacklistedByPolicyWillNotInstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003426 InitializeEmptyExtensionService();
3427
3428 // Blacklist everything.
3429 {
3430 ListPrefUpdate update(profile_->GetPrefs(),
3431 prefs::kExtensionInstallDenyList);
3432 ListValue* blacklist = update.Get();
3433 blacklist->Append(Value::CreateStringValue("*"));
3434 }
3435
3436 // Blacklist prevents us from installing good_crx.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003437 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003438 InstallCRX(path, INSTALL_FAILED);
3439 EXPECT_EQ(0u, service_->extensions()->size());
3440
3441 // Now whitelist this particular extension.
3442 {
3443 ListPrefUpdate update(profile_->GetPrefs(),
3444 prefs::kExtensionInstallAllowList);
3445 ListValue* whitelist = update.Get();
3446 whitelist->Append(Value::CreateStringValue(good_crx));
3447 }
3448
3449 // Ensure we can now install good_crx.
3450 InstallCRX(path, INSTALL_NEW);
3451 EXPECT_EQ(1u, service_->extensions()->size());
3452}
3453
3454// Extension blacklisted by policy get unloaded after installing.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003455TEST_F(ExtensionServiceTest, BlacklistedByPolicyRemovedIfRunning) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003456 InitializeEmptyExtensionService();
3457
3458 // Install good_crx.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003459 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003460 InstallCRX(path, INSTALL_NEW);
3461 EXPECT_EQ(1u, service_->extensions()->size());
3462
3463 { // Scope for pref update notification.
3464 PrefService* prefs = profile_->GetPrefs();
3465 ListPrefUpdate update(prefs, prefs::kExtensionInstallDenyList);
3466 ListValue* blacklist = update.Get();
3467 ASSERT_TRUE(blacklist != NULL);
3468
3469 // Blacklist this extension.
3470 blacklist->Append(Value::CreateStringValue(good_crx));
3471 }
3472
3473 // Extension should not be running now.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003474 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003475 EXPECT_EQ(0u, service_->extensions()->size());
3476}
3477
3478// Tests that component extensions are not blacklisted by policy.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003479TEST_F(ExtensionServiceTest, ComponentExtensionWhitelisted) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003480 InitializeEmptyExtensionService();
3481
3482 // Blacklist everything.
3483 {
3484 ListPrefUpdate update(profile_->GetPrefs(),
3485 prefs::kExtensionInstallDenyList);
3486 ListValue* blacklist = update.Get();
3487 blacklist->Append(Value::CreateStringValue("*"));
3488 }
3489
3490 // Install a component extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003491 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003492 .AppendASCII("good")
3493 .AppendASCII("Extensions")
3494 .AppendASCII(good0)
3495 .AppendASCII("1.0.0.0");
3496 std::string manifest;
3497 ASSERT_TRUE(file_util::ReadFileToString(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003498 path.Append(extensions::kManifestFilename), &manifest));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003499 service_->component_loader()->Add(manifest, path);
3500 service_->Init();
3501
3502 // Extension should be installed despite blacklist.
3503 ASSERT_EQ(1u, service_->extensions()->size());
3504 EXPECT_TRUE(service_->GetExtensionById(good0, false));
3505
3506 // Poke external providers and make sure the extension is still present.
3507 service_->CheckForExternalUpdates();
3508 ASSERT_EQ(1u, service_->extensions()->size());
3509 EXPECT_TRUE(service_->GetExtensionById(good0, false));
3510
3511 // Extension should not be uninstalled on blacklist changes.
3512 {
3513 ListPrefUpdate update(profile_->GetPrefs(),
3514 prefs::kExtensionInstallDenyList);
3515 ListValue* blacklist = update.Get();
3516 blacklist->Append(Value::CreateStringValue(good0));
3517 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003518 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003519 ASSERT_EQ(1u, service_->extensions()->size());
3520 EXPECT_TRUE(service_->GetExtensionById(good0, false));
3521}
3522
3523// Tests that policy-installed extensions are not blacklisted by policy.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003524TEST_F(ExtensionServiceTest, PolicyInstalledExtensionsWhitelisted) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003525 InitializeEmptyExtensionService();
3526
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003527 {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003528 // Blacklist everything.
3529 ListPrefUpdate blacklist_update(profile_->GetPrefs(),
3530 prefs::kExtensionInstallDenyList);
3531 ListValue* blacklist = blacklist_update.Get();
3532 blacklist->AppendString("*");
3533
3534 // Mark good.crx for force-installation.
3535 DictionaryPrefUpdate forcelist_update(profile_->GetPrefs(),
3536 prefs::kExtensionInstallForceList);
3537 extensions::ExternalPolicyLoader::AddExtension(
3538 forcelist_update.Get(), good_crx, "http://example.com/update_url");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003539 }
3540
3541 // Have policy force-install an extension.
3542 MockExtensionProvider* provider =
3543 new MockExtensionProvider(service_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003544 Manifest::EXTERNAL_POLICY_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003545 AddMockExternalProvider(provider);
3546 provider->UpdateOrAddExtension(good_crx, "1.0.0.0",
3547 data_dir_.AppendASCII("good.crx"));
3548
3549 // Reloading extensions should find our externally registered extension
3550 // and install it.
3551 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003552 content::WindowedNotificationObserver(
3553 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
3554 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003555
3556 // Extension should be installed despite blacklist.
3557 ASSERT_EQ(1u, service_->extensions()->size());
3558 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3559
3560 // Blacklist update should not uninstall the extension.
3561 {
3562 ListPrefUpdate update(profile_->GetPrefs(),
3563 prefs::kExtensionInstallDenyList);
3564 ListValue* blacklist = update.Get();
3565 blacklist->Append(Value::CreateStringValue(good0));
3566 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003567 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003568 ASSERT_EQ(1u, service_->extensions()->size());
3569 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3570}
3571
3572// Tests that extensions cannot be installed if the policy provider prohibits
3573// it. This functionality is implemented in CrxInstaller::ConfirmInstall().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003574TEST_F(ExtensionServiceTest, ManagementPolicyProhibitsInstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003575 InitializeEmptyExtensionService();
3576
3577 management_policy_->UnregisterAllProviders();
3578 extensions::TestManagementPolicyProvider provider_(
3579 extensions::TestManagementPolicyProvider::PROHIBIT_LOAD);
3580 management_policy_->RegisterProvider(&provider_);
3581
3582 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_FAILED);
3583 EXPECT_EQ(0u, service_->extensions()->size());
3584}
3585
3586// Tests that extensions cannot be loaded from prefs if the policy provider
3587// prohibits it. This functionality is implemented in InstalledLoader::Load().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003588TEST_F(ExtensionServiceTest, ManagementPolicyProhibitsLoadFromPrefs) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003589 InitializeEmptyExtensionService();
3590
3591 // Create a fake extension to be loaded as though it were read from prefs.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003592 base::FilePath path = data_dir_.AppendASCII("management")
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003593 .AppendASCII("simple_extension");
3594 DictionaryValue manifest;
3595 manifest.SetString(keys::kName, "simple_extension");
3596 manifest.SetString(keys::kVersion, "1");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003597 // UNPACKED is for extensions loaded from a directory. We use it here, even
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003598 // though we're testing loading from prefs, so that we don't need to provide
3599 // an extension key.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003600 extensions::ExtensionInfo extension_info(
3601 &manifest, std::string(), path, Manifest::UNPACKED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003602
3603 // Ensure we can load it with no management policy in place.
3604 management_policy_->UnregisterAllProviders();
3605 EXPECT_EQ(0u, service_->extensions()->size());
3606 extensions::InstalledLoader(service_).Load(extension_info, false);
3607 EXPECT_EQ(1u, service_->extensions()->size());
3608
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003609 const Extension* extension = (service_->extensions()->begin())->get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003610 EXPECT_TRUE(service_->UninstallExtension(extension->id(), false, NULL));
3611 EXPECT_EQ(0u, service_->extensions()->size());
3612
3613 // Ensure we cannot load it if management policy prohibits installation.
3614 extensions::TestManagementPolicyProvider provider_(
3615 extensions::TestManagementPolicyProvider::PROHIBIT_LOAD);
3616 management_policy_->RegisterProvider(&provider_);
3617
3618 extensions::InstalledLoader(service_).Load(extension_info, false);
3619 EXPECT_EQ(0u, service_->extensions()->size());
3620}
3621
3622// Tests disabling an extension when prohibited by the ManagementPolicy.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003623TEST_F(ExtensionServiceTest, ManagementPolicyProhibitsDisable) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003624 InitializeEmptyExtensionService();
3625
3626 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3627 EXPECT_EQ(1u, service_->extensions()->size());
3628 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3629
3630 management_policy_->UnregisterAllProviders();
3631 extensions::TestManagementPolicyProvider provider(
3632 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
3633 management_policy_->RegisterProvider(&provider);
3634
3635 // Attempt to disable it.
3636 service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
3637
3638 EXPECT_EQ(1u, service_->extensions()->size());
3639 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3640 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3641}
3642
3643// Tests uninstalling an extension when prohibited by the ManagementPolicy.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003644TEST_F(ExtensionServiceTest, ManagementPolicyProhibitsUninstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003645 InitializeEmptyExtensionService();
3646
3647 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3648 EXPECT_EQ(1u, service_->extensions()->size());
3649 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3650
3651 management_policy_->UnregisterAllProviders();
3652 extensions::TestManagementPolicyProvider provider(
3653 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
3654 management_policy_->RegisterProvider(&provider);
3655
3656 // Attempt to uninstall it.
3657 EXPECT_FALSE(service_->UninstallExtension(good_crx, false, NULL));
3658
3659 EXPECT_EQ(1u, service_->extensions()->size());
3660 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3661}
3662
3663// Tests that previously installed extensions that are now prohibited from
3664// being installed are removed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003665TEST_F(ExtensionServiceTest, ManagementPolicyUnloadsAllProhibited) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003666 InitializeEmptyExtensionService();
3667
3668 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3669 InstallCRX(data_dir_.AppendASCII("page_action.crx"), INSTALL_NEW);
3670 EXPECT_EQ(2u, service_->extensions()->size());
3671 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3672
3673 management_policy_->UnregisterAllProviders();
3674 extensions::TestManagementPolicyProvider provider(
3675 extensions::TestManagementPolicyProvider::PROHIBIT_LOAD);
3676 management_policy_->RegisterProvider(&provider);
3677
3678 // Run the policy check.
3679 service_->CheckManagementPolicy();
3680 EXPECT_EQ(0u, service_->extensions()->size());
3681 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3682}
3683
3684// Tests that previously disabled extensions that are now required to be
3685// enabled are re-enabled on reinstall.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003686TEST_F(ExtensionServiceTest, ManagementPolicyRequiresEnable) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003687 InitializeEmptyExtensionService();
3688
3689 // Install, then disable, an extension.
3690 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3691 EXPECT_EQ(1u, service_->extensions()->size());
3692 service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
3693 EXPECT_EQ(1u, service_->disabled_extensions()->size());
3694
3695 // Register an ExtensionMnagementPolicy that requires the extension to remain
3696 // enabled.
3697 management_policy_->UnregisterAllProviders();
3698 extensions::TestManagementPolicyProvider provider(
3699 extensions::TestManagementPolicyProvider::MUST_REMAIN_ENABLED);
3700 management_policy_->RegisterProvider(&provider);
3701
3702 // Reinstall the extension.
3703 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_UPDATED);
3704 EXPECT_EQ(1u, service_->extensions()->size());
3705 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3706}
3707
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003708TEST_F(ExtensionServiceTest, ExternalExtensionAutoAcknowledgement) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003709 InitializeEmptyExtensionService();
3710 set_extensions_enabled(true);
3711
3712 {
3713 // Register and install an external extension.
3714 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003715 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003716 AddMockExternalProvider(provider);
3717 provider->UpdateOrAddExtension(good_crx, "1.0.0.0",
3718 data_dir_.AppendASCII("good.crx"));
3719 }
3720 {
3721 // Have policy force-install an extension.
3722 MockExtensionProvider* provider =
3723 new MockExtensionProvider(service_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003724 Manifest::EXTERNAL_POLICY_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003725 AddMockExternalProvider(provider);
3726 provider->UpdateOrAddExtension(page_action, "1.0.0.0",
3727 data_dir_.AppendASCII("page_action.crx"));
3728 }
3729
3730 // Providers are set up. Let them run.
3731 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003732
3733 int count = 2;
3734 content::WindowedNotificationObserver(
3735 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
3736 base::Bind(&WaitForCountNotificationsCallback, &count)).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003737
3738 ASSERT_EQ(2u, service_->extensions()->size());
3739 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3740 EXPECT_TRUE(service_->GetExtensionById(page_action, false));
3741 ExtensionPrefs* prefs = service_->extension_prefs();
3742 ASSERT_TRUE(!prefs->IsExternalExtensionAcknowledged(good_crx));
3743 ASSERT_TRUE(prefs->IsExternalExtensionAcknowledged(page_action));
3744}
3745
3746#if !defined(OS_CHROMEOS)
3747// This tests if default apps are installed correctly.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003748TEST_F(ExtensionServiceTest, DefaultAppsInstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003749 InitializeEmptyExtensionService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003750 set_extensions_enabled(true);
3751
3752 {
3753 std::string json_data =
3754 "{"
3755 " \"ldnnhddmnhbkjipkidpdiheffobcpfmf\" : {"
3756 " \"external_crx\": \"good.crx\","
3757 " \"external_version\": \"1.0.0.0\","
3758 " \"is_bookmark_app\": false"
3759 " }"
3760 "}";
3761 default_apps::Provider* provider =
3762 new default_apps::Provider(
3763 profile_.get(),
3764 service_,
3765 new extensions::ExternalTestingLoader(json_data, data_dir_),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003766 Manifest::INTERNAL,
3767 Manifest::INVALID_LOCATION,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003768 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT);
3769
3770 AddMockExternalProvider(provider);
3771 }
3772
3773 ASSERT_EQ(0u, service_->extensions()->size());
3774 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003775 content::WindowedNotificationObserver(
3776 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
3777 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003778
3779 ASSERT_EQ(1u, service_->extensions()->size());
3780 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3781 const Extension* extension = service_->GetExtensionById(good_crx, false);
3782 EXPECT_TRUE(extension->from_webstore());
3783 EXPECT_TRUE(extension->was_installed_by_default());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003784}
3785#endif
3786
3787// Tests disabling extensions
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003788TEST_F(ExtensionServiceTest, DisableExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003789 InitializeEmptyExtensionService();
3790
3791 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3792 EXPECT_FALSE(service_->extensions()->is_empty());
3793 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
3794 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
3795 EXPECT_TRUE(service_->disabled_extensions()->is_empty());
3796
3797 // Disable it.
3798 service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
3799
3800 EXPECT_TRUE(service_->extensions()->is_empty());
3801 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
3802 EXPECT_FALSE(service_->GetExtensionById(good_crx, false));
3803 EXPECT_FALSE(service_->disabled_extensions()->is_empty());
3804}
3805
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003806TEST_F(ExtensionServiceTest, DisableTerminatedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003807 InitializeEmptyExtensionService();
3808
3809 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3810 TerminateExtension(good_crx);
3811 EXPECT_TRUE(service_->GetTerminatedExtension(good_crx));
3812
3813 // Disable it.
3814 service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
3815
3816 EXPECT_FALSE(service_->GetTerminatedExtension(good_crx));
3817 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
3818 EXPECT_FALSE(service_->disabled_extensions()->is_empty());
3819}
3820
3821// Tests disabling all extensions (simulating --disable-extensions flag).
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003822TEST_F(ExtensionServiceTest, DisableAllExtensions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003823 InitializeEmptyExtensionService();
3824
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003825 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003826 InstallCRX(path, INSTALL_NEW);
3827
3828 EXPECT_EQ(1u, service_->extensions()->size());
3829 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3830
3831 // Disable extensions.
3832 service_->set_extensions_enabled(false);
3833 service_->ReloadExtensions();
3834
3835 // There shouldn't be extensions in either list.
3836 EXPECT_EQ(0u, service_->extensions()->size());
3837 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3838
3839 // This shouldn't do anything when all extensions are disabled.
3840 service_->EnableExtension(good_crx);
3841 service_->ReloadExtensions();
3842
3843 // There still shouldn't be extensions in either list.
3844 EXPECT_EQ(0u, service_->extensions()->size());
3845 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3846
3847 // And then re-enable the extensions.
3848 service_->set_extensions_enabled(true);
3849 service_->ReloadExtensions();
3850
3851 EXPECT_EQ(1u, service_->extensions()->size());
3852 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3853}
3854
3855// Tests reloading extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003856TEST_F(ExtensionServiceTest, ReloadExtensions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003857 InitializeEmptyExtensionService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003858
3859 // Simple extension that should install without error.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003860 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003861 InstallCRX(path, INSTALL_NEW,
3862 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT);
3863 const char* extension_id = good_crx;
3864 service_->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
3865
3866 EXPECT_EQ(0u, service_->extensions()->size());
3867 EXPECT_EQ(1u, service_->disabled_extensions()->size());
3868
3869 service_->ReloadExtensions();
3870
3871 // The creation flags should not change when reloading the extension.
3872 const Extension* extension = service_->GetExtensionById(good_crx, true);
3873 EXPECT_TRUE(extension->from_webstore());
3874 EXPECT_TRUE(extension->was_installed_by_default());
3875 EXPECT_FALSE(extension->from_bookmark());
3876
3877 // Extension counts shouldn't change.
3878 EXPECT_EQ(0u, service_->extensions()->size());
3879 EXPECT_EQ(1u, service_->disabled_extensions()->size());
3880
3881 service_->EnableExtension(extension_id);
3882
3883 EXPECT_EQ(1u, service_->extensions()->size());
3884 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3885
3886 // Need to clear |loaded_| manually before reloading as the
3887 // EnableExtension() call above inserted into it and
3888 // UnloadAllExtensions() doesn't send out notifications.
3889 loaded_.clear();
3890 service_->ReloadExtensions();
3891
3892 // Extension counts shouldn't change.
3893 EXPECT_EQ(1u, service_->extensions()->size());
3894 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3895}
3896
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003897// Tests reloading an extension.
3898TEST_F(ExtensionServiceTest, ReloadExtension) {
3899 InitializeEmptyExtensionService();
3900 InitializeExtensionProcessManager();
3901
3902 // Simple extension that should install without error.
3903 const char* extension_id = "behllobkkfkfnphdnhnkndlbkcpglgmj";
3904 base::FilePath ext = data_dir_
3905 .AppendASCII("good")
3906 .AppendASCII("Extensions")
3907 .AppendASCII(extension_id)
3908 .AppendASCII("1.0.0.0");
3909 extensions::UnpackedInstaller::Create(service_)->Load(ext);
3910 loop_.RunUntilIdle();
3911
3912 EXPECT_EQ(1u, service_->extensions()->size());
3913 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3914
3915 service_->ReloadExtension(extension_id);
3916
3917 // Extension should be disabled now, waiting to be reloaded.
3918 EXPECT_EQ(0u, service_->extensions()->size());
3919 EXPECT_EQ(1u, service_->disabled_extensions()->size());
3920 EXPECT_EQ(Extension::DISABLE_RELOAD,
3921 service_->extension_prefs()->GetDisableReasons(extension_id));
3922
3923 // Reloading again should not crash.
3924 service_->ReloadExtension(extension_id);
3925
3926 // Finish reloading
3927 loop_.RunUntilIdle();
3928
3929 // Extension should be enabled again.
3930 EXPECT_EQ(1u, service_->extensions()->size());
3931 EXPECT_EQ(0u, service_->disabled_extensions()->size());
3932}
3933
3934TEST_F(ExtensionServiceTest, UninstallExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003935 InitializeEmptyExtensionService();
3936 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3937 EXPECT_EQ(1u, service_->extensions()->size());
3938 UninstallExtension(good_crx, false);
3939 EXPECT_EQ(0u, service_->extensions()->size());
3940}
3941
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003942TEST_F(ExtensionServiceTest, UninstallTerminatedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003943 InitializeEmptyExtensionService();
3944 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3945 TerminateExtension(good_crx);
3946 UninstallExtension(good_crx, false);
3947}
3948
3949// Tests the uninstaller helper.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003950TEST_F(ExtensionServiceTest, UninstallExtensionHelper) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003951 InitializeEmptyExtensionService();
3952 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3953 UninstallExtension(good_crx, true);
3954}
3955
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003956TEST_F(ExtensionServiceTest, UninstallExtensionHelperTerminated) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003957 InitializeEmptyExtensionService();
3958 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
3959 TerminateExtension(good_crx);
3960 UninstallExtension(good_crx, true);
3961}
3962
3963// An extension disabled because of unsupported requirements should re-enabled
3964// if updated to a version with supported requirements as long as there are no
3965// other disable reasons.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003966TEST_F(ExtensionServiceTest, UpgradingRequirementsEnabled) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003967 InitializeEmptyExtensionService();
3968 BlackListWebGL();
3969
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003970 base::FilePath path = data_dir_.AppendASCII("requirements");
3971 base::FilePath pem_path = data_dir_.AppendASCII("requirements")
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003972 .AppendASCII("v1_good.pem");
3973 const Extension* extension_v1 = PackAndInstallCRX(path.AppendASCII("v1_good"),
3974 pem_path,
3975 INSTALL_NEW);
3976 std::string id = extension_v1->id();
3977 EXPECT_TRUE(service_->IsExtensionEnabled(id));
3978
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003979 base::FilePath v2_bad_requirements_crx = GetTemporaryFile();
3980
3981 PackCRX(path.AppendASCII("v2_bad_requirements"),
3982 pem_path,
3983 v2_bad_requirements_crx);
3984 UpdateExtension(id, v2_bad_requirements_crx, INSTALLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003985 EXPECT_FALSE(service_->IsExtensionEnabled(id));
3986
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003987 base::FilePath v3_good_crx = GetTemporaryFile();
3988
3989 PackCRX(path.AppendASCII("v3_good"), pem_path, v3_good_crx);
3990 UpdateExtension(id, v3_good_crx, ENABLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003991 EXPECT_TRUE(service_->IsExtensionEnabled(id));
3992}
3993
3994// Extensions disabled through user action should stay disabled.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003995TEST_F(ExtensionServiceTest, UpgradingRequirementsDisabled) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003996 InitializeEmptyExtensionService();
3997 BlackListWebGL();
3998
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003999 base::FilePath path = data_dir_.AppendASCII("requirements");
4000 base::FilePath pem_path = data_dir_.AppendASCII("requirements")
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004001 .AppendASCII("v1_good.pem");
4002 const Extension* extension_v1 = PackAndInstallCRX(path.AppendASCII("v1_good"),
4003 pem_path,
4004 INSTALL_NEW);
4005 std::string id = extension_v1->id();
4006 service_->DisableExtension(id, Extension::DISABLE_USER_ACTION);
4007 EXPECT_FALSE(service_->IsExtensionEnabled(id));
4008
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004009 base::FilePath v2_bad_requirements_crx = GetTemporaryFile();
4010
4011 PackCRX(path.AppendASCII("v2_bad_requirements"),
4012 pem_path,
4013 v2_bad_requirements_crx);
4014 UpdateExtension(id, v2_bad_requirements_crx, INSTALLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004015 EXPECT_FALSE(service_->IsExtensionEnabled(id));
4016
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004017 base::FilePath v3_good_crx = GetTemporaryFile();
4018
4019 PackCRX(path.AppendASCII("v3_good"), pem_path, v3_good_crx);
4020 UpdateExtension(id, v3_good_crx, INSTALLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004021 EXPECT_FALSE(service_->IsExtensionEnabled(id));
4022}
4023
4024// The extension should not re-enabled because it was disabled from a
4025// permission increase.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004026TEST_F(ExtensionServiceTest, UpgradingRequirementsPermissions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004027 InitializeEmptyExtensionService();
4028 BlackListWebGL();
4029
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004030 base::FilePath path = data_dir_.AppendASCII("requirements");
4031 base::FilePath pem_path = data_dir_.AppendASCII("requirements")
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004032 .AppendASCII("v1_good.pem");
4033 const Extension* extension_v1 = PackAndInstallCRX(path.AppendASCII("v1_good"),
4034 pem_path,
4035 INSTALL_NEW);
4036 std::string id = extension_v1->id();
4037 EXPECT_TRUE(service_->IsExtensionEnabled(id));
4038
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004039 base::FilePath v2_bad_requirements_and_permissions_crx = GetTemporaryFile();
4040
4041 PackCRX(path.AppendASCII("v2_bad_requirements_and_permissions"),
4042 pem_path,
4043 v2_bad_requirements_and_permissions_crx);
4044 UpdateExtension(id, v2_bad_requirements_and_permissions_crx, INSTALLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004045 EXPECT_FALSE(service_->IsExtensionEnabled(id));
4046
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004047 base::FilePath v3_bad_permissions_crx = GetTemporaryFile();
4048
4049 PackCRX(path.AppendASCII("v3_bad_permissions"),
4050 pem_path,
4051 v3_bad_permissions_crx);
4052 UpdateExtension(id, v3_bad_permissions_crx, INSTALLED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004053 EXPECT_FALSE(service_->IsExtensionEnabled(id));
4054}
4055
4056// Unpacked extensions are not allowed to be installed if they have unsupported
4057// requirements.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004058TEST_F(ExtensionServiceTest, UnpackedRequirements) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004059 InitializeEmptyExtensionService();
4060 BlackListWebGL();
4061
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004062 base::FilePath path = data_dir_.AppendASCII("requirements")
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004063 .AppendASCII("v2_bad_requirements");
4064 extensions::UnpackedInstaller::Create(service_)->Load(path);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004065 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004066 EXPECT_EQ(1u, GetErrors().size());
4067 EXPECT_EQ(0u, service_->extensions()->size());
4068}
4069
4070class ExtensionCookieCallback {
4071 public:
4072 ExtensionCookieCallback()
4073 : result_(false),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004074 weak_factory_(base::MessageLoop::current()) {}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004075
4076 void SetCookieCallback(bool result) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004077 base::MessageLoop::current()->PostTask(FROM_HERE,
4078 base::Bind(&base::MessageLoop::Quit, weak_factory_.GetWeakPtr()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004079 result_ = result;
4080 }
4081
4082 void GetAllCookiesCallback(const net::CookieList& list) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004083 base::MessageLoop::current()->PostTask(FROM_HERE,
4084 base::Bind(&base::MessageLoop::Quit, weak_factory_.GetWeakPtr()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004085 list_ = list;
4086 }
4087 net::CookieList list_;
4088 bool result_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004089 base::WeakPtrFactory<base::MessageLoop> weak_factory_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004090};
4091
4092// Verifies extension state is removed upon uninstall.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004093TEST_F(ExtensionServiceTest, ClearExtensionData) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004094 InitializeEmptyExtensionService();
4095 ExtensionCookieCallback callback;
4096
4097 // Load a test extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004098 base::FilePath path = data_dir_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004099 path = path.AppendASCII("good.crx");
4100 const Extension* extension = InstallCRX(path, INSTALL_NEW);
4101 ASSERT_TRUE(extension);
4102 GURL ext_url(extension->url());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004103 std::string origin_id = webkit_database::GetIdentifierFromOrigin(ext_url);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004104
4105 // Set a cookie for the extension.
4106 net::CookieMonster* cookie_monster =
4107 profile_->GetRequestContextForExtensions()->GetURLRequestContext()->
4108 cookie_store()->GetCookieMonster();
4109 ASSERT_TRUE(cookie_monster);
4110 net::CookieOptions options;
4111 cookie_monster->SetCookieWithOptionsAsync(
4112 ext_url, "dummy=value", options,
4113 base::Bind(&ExtensionCookieCallback::SetCookieCallback,
4114 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004115 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004116 EXPECT_TRUE(callback.result_);
4117
4118 cookie_monster->GetAllCookiesForURLAsync(
4119 ext_url,
4120 base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
4121 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004122 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004123 EXPECT_EQ(1U, callback.list_.size());
4124
4125 // Open a database.
4126 webkit_database::DatabaseTracker* db_tracker =
4127 BrowserContext::GetDefaultStoragePartition(profile_.get())->
4128 GetDatabaseTracker();
4129 string16 db_name = UTF8ToUTF16("db");
4130 string16 description = UTF8ToUTF16("db_description");
4131 int64 size;
4132 db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size);
4133 db_tracker->DatabaseClosed(origin_id, db_name);
4134 std::vector<webkit_database::OriginInfo> origins;
4135 db_tracker->GetAllOriginsInfo(&origins);
4136 EXPECT_EQ(1U, origins.size());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004137 EXPECT_EQ(origin_id, origins[0].GetOriginIdentifier());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004138
4139 // Create local storage. We only simulate this by creating the backing files.
4140 // Note: This test depends on details of how the dom_storage library
4141 // stores data in the host file system.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004142 base::FilePath lso_dir_path =
4143 profile_->GetPath().AppendASCII("Local Storage");
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004144 base::FilePath lso_file_path = lso_dir_path.AppendASCII(origin_id)
4145 .AddExtension(FILE_PATH_LITERAL(".localstorage"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004146 EXPECT_TRUE(file_util::CreateDirectory(lso_dir_path));
4147 EXPECT_EQ(0, file_util::WriteFile(lso_file_path, NULL, 0));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004148 EXPECT_TRUE(base::PathExists(lso_file_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004149
4150 // Create indexed db. Similarly, it is enough to only simulate this by
4151 // creating the directory on the disk.
4152 IndexedDBContext* idb_context =
4153 BrowserContext::GetDefaultStoragePartition(profile_.get())->
4154 GetIndexedDBContext();
Ben Murdocheb525c52013-07-10 11:40:50 +01004155 idb_context->SetTaskRunnerForTesting(
4156 base::MessageLoop::current()->message_loop_proxy().get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004157 base::FilePath idb_path = idb_context->GetFilePathForTesting(origin_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004158 EXPECT_TRUE(file_util::CreateDirectory(idb_path));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004159 EXPECT_TRUE(base::DirectoryExists(idb_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004160
4161 // Uninstall the extension.
4162 service_->UninstallExtension(good_crx, false, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004163 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004164
4165 // Check that the cookie is gone.
4166 cookie_monster->GetAllCookiesForURLAsync(
4167 ext_url,
4168 base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
4169 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004170 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004171 EXPECT_EQ(0U, callback.list_.size());
4172
4173 // The database should have vanished as well.
4174 origins.clear();
4175 db_tracker->GetAllOriginsInfo(&origins);
4176 EXPECT_EQ(0U, origins.size());
4177
4178 // Check that the LSO file has been removed.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004179 EXPECT_FALSE(base::PathExists(lso_file_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004180
4181 // Check if the indexed db has disappeared too.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004182 EXPECT_FALSE(base::DirectoryExists(idb_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004183}
4184
4185// Verifies app state is removed upon uninstall.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004186TEST_F(ExtensionServiceTest, ClearAppData) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004187 InitializeEmptyExtensionService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004188 ExtensionCookieCallback callback;
4189
4190 int pref_count = 0;
4191
4192 // Install app1 with unlimited storage.
4193 const Extension* extension =
4194 PackAndInstallCRX(data_dir_.AppendASCII("app1"), INSTALL_NEW);
4195 ValidatePrefKeyCount(++pref_count);
4196 ASSERT_EQ(1u, service_->extensions()->size());
4197 const std::string id1 = extension->id();
4198 EXPECT_TRUE(extension->HasAPIPermission(
4199 APIPermission::kUnlimitedStorage));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004200 const GURL origin1(
4201 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004202 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
4203 IsStorageUnlimited(origin1));
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004204 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004205
4206 // Install app2 from the same origin with unlimited storage.
4207 extension = PackAndInstallCRX(data_dir_.AppendASCII("app2"), INSTALL_NEW);
4208 ValidatePrefKeyCount(++pref_count);
4209 ASSERT_EQ(2u, service_->extensions()->size());
4210 const std::string id2 = extension->id();
4211 EXPECT_TRUE(extension->HasAPIPermission(
4212 APIPermission::kUnlimitedStorage));
4213 EXPECT_TRUE(extension->web_extent().MatchesURL(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004214 extensions::AppLaunchInfo::GetFullLaunchURL(extension)));
4215 const GURL origin2(
4216 extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004217 EXPECT_EQ(origin1, origin2);
4218 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
4219 IsStorageUnlimited(origin2));
4220
4221 // Set a cookie for the extension.
4222 net::CookieMonster* cookie_monster =
4223 profile_->GetRequestContext()->GetURLRequestContext()->
4224 cookie_store()->GetCookieMonster();
4225 ASSERT_TRUE(cookie_monster);
4226 net::CookieOptions options;
4227 cookie_monster->SetCookieWithOptionsAsync(
4228 origin1, "dummy=value", options,
4229 base::Bind(&ExtensionCookieCallback::SetCookieCallback,
4230 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004231 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004232 EXPECT_TRUE(callback.result_);
4233
4234 cookie_monster->GetAllCookiesForURLAsync(
4235 origin1,
4236 base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
4237 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004238 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004239 EXPECT_EQ(1U, callback.list_.size());
4240
4241 // Open a database.
4242 webkit_database::DatabaseTracker* db_tracker =
4243 BrowserContext::GetDefaultStoragePartition(profile_.get())->
4244 GetDatabaseTracker();
4245 string16 db_name = UTF8ToUTF16("db");
4246 string16 description = UTF8ToUTF16("db_description");
4247 int64 size;
4248 db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size);
4249 db_tracker->DatabaseClosed(origin_id, db_name);
4250 std::vector<webkit_database::OriginInfo> origins;
4251 db_tracker->GetAllOriginsInfo(&origins);
4252 EXPECT_EQ(1U, origins.size());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004253 EXPECT_EQ(origin_id, origins[0].GetOriginIdentifier());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004254
4255 // Create local storage. We only simulate this by creating the backing files.
4256 // Note: This test depends on details of how the dom_storage library
4257 // stores data in the host file system.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004258 base::FilePath lso_dir_path =
4259 profile_->GetPath().AppendASCII("Local Storage");
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004260 base::FilePath lso_file_path = lso_dir_path.AppendASCII(origin_id)
4261 .AddExtension(FILE_PATH_LITERAL(".localstorage"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004262 EXPECT_TRUE(file_util::CreateDirectory(lso_dir_path));
4263 EXPECT_EQ(0, file_util::WriteFile(lso_file_path, NULL, 0));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004264 EXPECT_TRUE(base::PathExists(lso_file_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004265
4266 // Create indexed db. Similarly, it is enough to only simulate this by
4267 // creating the directory on the disk.
4268 IndexedDBContext* idb_context =
4269 BrowserContext::GetDefaultStoragePartition(profile_.get())->
4270 GetIndexedDBContext();
Ben Murdocheb525c52013-07-10 11:40:50 +01004271 idb_context->SetTaskRunnerForTesting(
4272 base::MessageLoop::current()->message_loop_proxy().get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004273 base::FilePath idb_path = idb_context->GetFilePathForTesting(origin_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004274 EXPECT_TRUE(file_util::CreateDirectory(idb_path));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004275 EXPECT_TRUE(base::DirectoryExists(idb_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004276
4277 // Uninstall one of them, unlimited storage should still be granted
4278 // to the origin.
4279 UninstallExtension(id1, false);
4280 EXPECT_EQ(1u, service_->extensions()->size());
4281 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
4282 IsStorageUnlimited(origin1));
4283
4284 // Check that the cookie is still there.
4285 cookie_monster->GetAllCookiesForURLAsync(
4286 origin1,
4287 base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
4288 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004289 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004290 EXPECT_EQ(1U, callback.list_.size());
4291
4292 // Now uninstall the other. Storage should be cleared for the apps.
4293 UninstallExtension(id2, false);
4294 EXPECT_EQ(0u, service_->extensions()->size());
4295 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
4296 IsStorageUnlimited(origin1));
4297
4298 // Check that the cookie is gone.
4299 cookie_monster->GetAllCookiesForURLAsync(
4300 origin1,
4301 base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
4302 base::Unretained(&callback)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004303 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004304 EXPECT_EQ(0U, callback.list_.size());
4305
4306 // The database should have vanished as well.
4307 origins.clear();
4308 db_tracker->GetAllOriginsInfo(&origins);
4309 EXPECT_EQ(0U, origins.size());
4310
4311 // Check that the LSO file has been removed.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004312 EXPECT_FALSE(base::PathExists(lso_file_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004313
4314 // Check if the indexed db has disappeared too.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004315 EXPECT_FALSE(base::DirectoryExists(idb_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004316}
4317
4318// Tests loading single extensions (like --load-extension)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004319// Flaky crashes. http://crbug.com/231806
4320TEST_F(ExtensionServiceTest, DISABLED_LoadExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004321 InitializeEmptyExtensionService();
4322
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004323 base::FilePath ext1 = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004324 .AppendASCII("good")
4325 .AppendASCII("Extensions")
4326 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
4327 .AppendASCII("1.0.0.0");
4328 extensions::UnpackedInstaller::Create(service_)->Load(ext1);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004329 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004330 EXPECT_EQ(0u, GetErrors().size());
4331 ASSERT_EQ(1u, loaded_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004332 EXPECT_EQ(Manifest::UNPACKED, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004333 EXPECT_EQ(1u, service_->extensions()->size());
4334
4335 ValidatePrefKeyCount(1);
4336
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004337 base::FilePath no_manifest = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004338 .AppendASCII("bad")
4339 // .AppendASCII("Extensions")
4340 .AppendASCII("cccccccccccccccccccccccccccccccc")
4341 .AppendASCII("1");
4342 extensions::UnpackedInstaller::Create(service_)->Load(no_manifest);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004343 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004344 EXPECT_EQ(1u, GetErrors().size());
4345 ASSERT_EQ(1u, loaded_.size());
4346 EXPECT_EQ(1u, service_->extensions()->size());
4347
4348 // Test uninstall.
4349 std::string id = loaded_[0]->id();
4350 EXPECT_FALSE(unloaded_id_.length());
4351 service_->UninstallExtension(id, false, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004352 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004353 EXPECT_EQ(id, unloaded_id_);
4354 ASSERT_EQ(0u, loaded_.size());
4355 EXPECT_EQ(0u, service_->extensions()->size());
4356}
4357
4358// Tests that we generate IDs when they are not specified in the manifest for
4359// --load-extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004360TEST_F(ExtensionServiceTest, GenerateID) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004361 InitializeEmptyExtensionService();
4362
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004363 base::FilePath no_id_ext = data_dir_.AppendASCII("no_id");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004364 extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004365 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004366 EXPECT_EQ(0u, GetErrors().size());
4367 ASSERT_EQ(1u, loaded_.size());
4368 ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004369 EXPECT_EQ(loaded_[0]->location(), Manifest::UNPACKED);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004370
4371 ValidatePrefKeyCount(1);
4372
4373 std::string previous_id = loaded_[0]->id();
4374
4375 // If we reload the same path, we should get the same extension ID.
4376 extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004377 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004378 ASSERT_EQ(1u, loaded_.size());
4379 ASSERT_EQ(previous_id, loaded_[0]->id());
4380}
4381
4382void ExtensionServiceTest::TestExternalProvider(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004383 MockExtensionProvider* provider, Manifest::Location location) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004384 // Verify that starting with no providers loads no extensions.
4385 service_->Init();
4386 ASSERT_EQ(0u, loaded_.size());
4387
4388 provider->set_visit_count(0);
4389
4390 // Register a test extension externally using the mock registry provider.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004391 base::FilePath source_path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004392
4393 // Add the extension.
4394 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
4395
4396 // Reloading extensions should find our externally registered extension
4397 // and install it.
4398 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004399 content::WindowedNotificationObserver(
4400 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
4401 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004402
4403 ASSERT_EQ(0u, GetErrors().size());
4404 ASSERT_EQ(1u, loaded_.size());
4405 ASSERT_EQ(location, loaded_[0]->location());
4406 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
4407 ValidatePrefKeyCount(1);
4408 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
4409 ValidateIntegerPref(good_crx, "location", location);
4410
4411 // Reload extensions without changing anything. The extension should be
4412 // loaded again.
4413 loaded_.clear();
4414 service_->ReloadExtensions();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004415 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004416 ASSERT_EQ(0u, GetErrors().size());
4417 ASSERT_EQ(1u, loaded_.size());
4418 ValidatePrefKeyCount(1);
4419 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
4420 ValidateIntegerPref(good_crx, "location", location);
4421
4422 // Now update the extension with a new version. We should get upgraded.
4423 source_path = source_path.DirName().AppendASCII("good2.crx");
4424 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path);
4425
4426 loaded_.clear();
4427 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004428 content::WindowedNotificationObserver(
4429 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
4430 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004431 ASSERT_EQ(0u, GetErrors().size());
4432 ASSERT_EQ(1u, loaded_.size());
4433 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
4434 ValidatePrefKeyCount(1);
4435 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
4436 ValidateIntegerPref(good_crx, "location", location);
4437
4438 // Uninstall the extension and reload. Nothing should happen because the
4439 // preference should prevent us from reinstalling.
4440 std::string id = loaded_[0]->id();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004441 bool no_uninstall =
4442 management_policy_->MustRemainEnabled(loaded_[0].get(), NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004443 service_->UninstallExtension(id, false, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004444 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004445
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004446 base::FilePath install_path = extensions_install_dir_.AppendASCII(id);
4447 if (no_uninstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004448 // Policy controlled extensions should not have been touched by uninstall.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004449 ASSERT_TRUE(base::PathExists(install_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004450 } else {
4451 // The extension should also be gone from the install directory.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004452 ASSERT_FALSE(base::PathExists(install_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004453 loaded_.clear();
4454 service_->CheckForExternalUpdates();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004455 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004456 ASSERT_EQ(0u, loaded_.size());
4457 ValidatePrefKeyCount(1);
4458 ValidateIntegerPref(good_crx, "state",
4459 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
4460 ValidateIntegerPref(good_crx, "location", location);
4461
4462 // Now clear the preference and reinstall.
4463 SetPrefInteg(good_crx, "state", Extension::ENABLED);
4464
4465 loaded_.clear();
4466 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004467 content::WindowedNotificationObserver(
4468 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
4469 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004470 ASSERT_EQ(1u, loaded_.size());
4471 }
4472 ValidatePrefKeyCount(1);
4473 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
4474 ValidateIntegerPref(good_crx, "location", location);
4475
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004476 if (management_policy_->MustRemainEnabled(loaded_[0].get(), NULL)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004477 EXPECT_EQ(2, provider->visit_count());
4478 } else {
4479 // Now test an externally triggered uninstall (deleting the registry key or
4480 // the pref entry).
4481 provider->RemoveExtension(good_crx);
4482
4483 loaded_.clear();
4484 service_->OnExternalProviderReady(provider);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004485 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004486 ASSERT_EQ(0u, loaded_.size());
4487 ValidatePrefKeyCount(0);
4488
4489 // The extension should also be gone from the install directory.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004490 ASSERT_FALSE(base::PathExists(install_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004491
4492 // Now test the case where user uninstalls and then the extension is removed
4493 // from the external provider.
4494 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path);
4495 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004496 content::WindowedNotificationObserver(
4497 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
4498 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004499
4500 ASSERT_EQ(1u, loaded_.size());
4501 ASSERT_EQ(0u, GetErrors().size());
4502
4503 // User uninstalls.
4504 loaded_.clear();
4505 service_->UninstallExtension(id, false, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004506 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004507 ASSERT_EQ(0u, loaded_.size());
4508
4509 // Then remove the extension from the extension provider.
4510 provider->RemoveExtension(good_crx);
4511
4512 // Should still be at 0.
4513 loaded_.clear();
4514 extensions::InstalledLoader(service_).LoadAllExtensions();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004515 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004516 ASSERT_EQ(0u, loaded_.size());
4517 ValidatePrefKeyCount(1);
4518
4519 EXPECT_EQ(5, provider->visit_count());
4520 }
4521}
4522
4523// Tests the external installation feature
4524#if defined(OS_WIN)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004525TEST_F(ExtensionServiceTest, ExternalInstallRegistry) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004526 // This should all work, even when normal extension installation is disabled.
4527 InitializeEmptyExtensionService();
4528 set_extensions_enabled(false);
4529
4530 // Now add providers. Extension system takes ownership of the objects.
4531 MockExtensionProvider* reg_provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004532 new MockExtensionProvider(service_, Manifest::EXTERNAL_REGISTRY);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004533 AddMockExternalProvider(reg_provider);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004534 TestExternalProvider(reg_provider, Manifest::EXTERNAL_REGISTRY);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004535}
4536#endif
4537
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004538TEST_F(ExtensionServiceTest, ExternalInstallPref) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004539 InitializeEmptyExtensionService();
4540
4541 // Now add providers. Extension system takes ownership of the objects.
4542 MockExtensionProvider* pref_provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004543 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004544
4545 AddMockExternalProvider(pref_provider);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004546 TestExternalProvider(pref_provider, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004547}
4548
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004549TEST_F(ExtensionServiceTest, ExternalInstallPrefUpdateUrl) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004550 // This should all work, even when normal extension installation is disabled.
4551 InitializeEmptyExtensionService();
4552 set_extensions_enabled(false);
4553
4554 // TODO(skerner): The mock provider is not a good model of a provider
4555 // that works with update URLs, because it adds file and version info.
4556 // Extend the mock to work with update URLs. This test checks the
4557 // behavior that is common to all external extension visitors. The
4558 // browser test ExtensionManagementTest.ExternalUrlUpdate tests that
4559 // what the visitor does results in an extension being downloaded and
4560 // installed.
4561 MockExtensionProvider* pref_provider =
4562 new MockExtensionProvider(service_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004563 Manifest::EXTERNAL_PREF_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004564 AddMockExternalProvider(pref_provider);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004565 TestExternalProvider(pref_provider, Manifest::EXTERNAL_PREF_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004566}
4567
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004568TEST_F(ExtensionServiceTest, ExternalInstallPolicyUpdateUrl) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004569 // This should all work, even when normal extension installation is disabled.
4570 InitializeEmptyExtensionService();
4571 set_extensions_enabled(false);
4572
4573 // TODO(skerner): The mock provider is not a good model of a provider
4574 // that works with update URLs, because it adds file and version info.
4575 // Extend the mock to work with update URLs. This test checks the
4576 // behavior that is common to all external extension visitors. The
4577 // browser test ExtensionManagementTest.ExternalUrlUpdate tests that
4578 // what the visitor does results in an extension being downloaded and
4579 // installed.
4580 MockExtensionProvider* pref_provider =
4581 new MockExtensionProvider(service_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004582 Manifest::EXTERNAL_POLICY_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004583 AddMockExternalProvider(pref_provider);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004584 TestExternalProvider(pref_provider, Manifest::EXTERNAL_POLICY_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004585}
4586
4587// Tests that external extensions get uninstalled when the external extension
4588// providers can't account for them.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004589TEST_F(ExtensionServiceTest, ExternalUninstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004590 // Start the extensions service with one external extension already installed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004591 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004592 .AppendASCII("good")
4593 .AppendASCII("Extensions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004594 base::FilePath pref_path = source_install_dir
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004595 .DirName()
4596 .AppendASCII("PreferencesExternal");
4597
4598 // This initializes the extensions service with no ExternalProviders.
4599 InitializeInstalledExtensionService(pref_path, source_install_dir);
4600 set_extensions_enabled(false);
4601
4602 service_->Init();
4603
4604 ASSERT_EQ(0u, GetErrors().size());
4605 ASSERT_EQ(0u, loaded_.size());
4606
4607 // Verify that it's not the disabled extensions flag causing it not to load.
4608 set_extensions_enabled(true);
4609 service_->ReloadExtensions();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004610 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004611
4612 ASSERT_EQ(0u, GetErrors().size());
4613 ASSERT_EQ(0u, loaded_.size());
4614}
4615
4616// Test that running multiple update checks simultaneously does not
4617// keep the update from succeeding.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004618TEST_F(ExtensionServiceTest, MultipleExternalUpdateCheck) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004619 InitializeEmptyExtensionService();
4620
4621 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004622 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004623 AddMockExternalProvider(provider);
4624
4625 // Verify that starting with no providers loads no extensions.
4626 service_->Init();
4627 ASSERT_EQ(0u, loaded_.size());
4628
4629 // Start two checks for updates.
4630 provider->set_visit_count(0);
4631 service_->CheckForExternalUpdates();
4632 service_->CheckForExternalUpdates();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004633 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004634
4635 // Two calls should cause two checks for external extensions.
4636 EXPECT_EQ(2, provider->visit_count());
4637 EXPECT_EQ(0u, GetErrors().size());
4638 EXPECT_EQ(0u, loaded_.size());
4639
4640 // Register a test extension externally using the mock registry provider.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004641 base::FilePath source_path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004642 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
4643
4644 // Two checks for external updates should find the extension, and install it
4645 // once.
4646 provider->set_visit_count(0);
4647 service_->CheckForExternalUpdates();
4648 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004649 content::WindowedNotificationObserver(
4650 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
4651 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004652 EXPECT_EQ(2, provider->visit_count());
4653 ASSERT_EQ(0u, GetErrors().size());
4654 ASSERT_EQ(1u, loaded_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004655 ASSERT_EQ(Manifest::EXTERNAL_PREF, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004656 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
4657 ValidatePrefKeyCount(1);
4658 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004659 ValidateIntegerPref(good_crx, "location", Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004660
4661 provider->RemoveExtension(good_crx);
4662 provider->set_visit_count(0);
4663 service_->CheckForExternalUpdates();
4664 service_->CheckForExternalUpdates();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004665 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004666
4667 // Two calls should cause two checks for external extensions.
4668 // Because the external source no longer includes good_crx,
4669 // good_crx will be uninstalled. So, expect that no extensions
4670 // are loaded.
4671 EXPECT_EQ(2, provider->visit_count());
4672 EXPECT_EQ(0u, GetErrors().size());
4673 EXPECT_EQ(0u, loaded_.size());
4674}
4675
4676namespace {
4677 class ScopedBrowserLocale {
4678 public:
4679 explicit ScopedBrowserLocale(const std::string& new_locale)
4680 : old_locale_(g_browser_process->GetApplicationLocale()) {
4681 g_browser_process->SetApplicationLocale(new_locale);
4682 }
4683
4684 ~ScopedBrowserLocale() {
4685 g_browser_process->SetApplicationLocale(old_locale_);
4686 }
4687
4688 private:
4689 std::string old_locale_;
4690 };
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004691} // namespace
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004692
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004693TEST_F(ExtensionServiceTest, ExternalPrefProvider) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004694 InitializeEmptyExtensionService();
4695
4696 // Test some valid extension records.
4697 // Set a base path to avoid erroring out on relative paths.
4698 // Paths starting with // are absolute on every platform we support.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004699 base::FilePath base_path(FILE_PATH_LITERAL("//base/path"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004700 ASSERT_TRUE(base_path.IsAbsolute());
4701 MockProviderVisitor visitor(base_path);
4702 std::string json_data =
4703 "{"
4704 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4705 " \"external_crx\": \"RandomExtension.crx\","
4706 " \"external_version\": \"1.0\""
4707 " },"
4708 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
4709 " \"external_crx\": \"RandomExtension2.crx\","
4710 " \"external_version\": \"2.0\""
4711 " },"
4712 " \"cccccccccccccccccccccccccccccccc\": {"
4713 " \"external_update_url\": \"http:\\\\foo.com/update\""
4714 " }"
4715 "}";
4716 EXPECT_EQ(3, visitor.Visit(json_data));
4717
4718 // Simulate an external_extensions.json file that contains seven invalid
4719 // records:
4720 // - One that is missing the 'external_crx' key.
4721 // - One that is missing the 'external_version' key.
4722 // - One that is specifying .. in the path.
4723 // - One that specifies both a file and update URL.
4724 // - One that specifies no file or update URL.
4725 // - One that has an update URL that is not well formed.
4726 // - One that contains a malformed version.
4727 // - One that has an invalid id.
4728 // - One that has a non-dictionary value.
4729 // - One that has an integer 'external_version' instead of a string.
4730 // The final extension is valid, and we check that it is read to make sure
4731 // failures don't stop valid records from being read.
4732 json_data =
4733 "{"
4734 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4735 " \"external_version\": \"1.0\""
4736 " },"
4737 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
4738 " \"external_crx\": \"RandomExtension.crx\""
4739 " },"
4740 " \"cccccccccccccccccccccccccccccccc\": {"
4741 " \"external_crx\": \"..\\\\foo\\\\RandomExtension2.crx\","
4742 " \"external_version\": \"2.0\""
4743 " },"
4744 " \"dddddddddddddddddddddddddddddddd\": {"
4745 " \"external_crx\": \"RandomExtension2.crx\","
4746 " \"external_version\": \"2.0\","
4747 " \"external_update_url\": \"http:\\\\foo.com/update\""
4748 " },"
4749 " \"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\": {"
4750 " },"
4751 " \"ffffffffffffffffffffffffffffffff\": {"
4752 " \"external_update_url\": \"This string is not a valid URL\""
4753 " },"
4754 " \"gggggggggggggggggggggggggggggggg\": {"
4755 " \"external_crx\": \"RandomExtension3.crx\","
4756 " \"external_version\": \"This is not a valid version!\""
4757 " },"
4758 " \"This is not a valid id!\": {},"
4759 " \"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\": true,"
4760 " \"iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\": {"
4761 " \"external_crx\": \"RandomExtension4.crx\","
4762 " \"external_version\": 1.0"
4763 " },"
4764 " \"pppppppppppppppppppppppppppppppp\": {"
4765 " \"external_crx\": \"RandomValidExtension.crx\","
4766 " \"external_version\": \"1.0\""
4767 " }"
4768 "}";
4769 EXPECT_EQ(1, visitor.Visit(json_data));
4770
4771 // Check that if a base path is not provided, use of a relative
4772 // path fails.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004773 base::FilePath empty;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004774 MockProviderVisitor visitor_no_relative_paths(empty);
4775
4776 // Use absolute paths. Expect success.
4777 json_data =
4778 "{"
4779 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4780 " \"external_crx\": \"//RandomExtension1.crx\","
4781 " \"external_version\": \"3.0\""
4782 " },"
4783 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
4784 " \"external_crx\": \"//path/to/RandomExtension2.crx\","
4785 " \"external_version\": \"3.0\""
4786 " }"
4787 "}";
4788 EXPECT_EQ(2, visitor_no_relative_paths.Visit(json_data));
4789
4790 // Use a relative path. Expect that it will error out.
4791 json_data =
4792 "{"
4793 " \"cccccccccccccccccccccccccccccccc\": {"
4794 " \"external_crx\": \"RandomExtension2.crx\","
4795 " \"external_version\": \"3.0\""
4796 " }"
4797 "}";
4798 EXPECT_EQ(0, visitor_no_relative_paths.Visit(json_data));
4799
4800 // Test supported_locales.
4801 json_data =
4802 "{"
4803 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4804 " \"external_crx\": \"RandomExtension.crx\","
4805 " \"external_version\": \"1.0\","
4806 " \"supported_locales\": [ \"en\" ]"
4807 " },"
4808 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
4809 " \"external_crx\": \"RandomExtension2.crx\","
4810 " \"external_version\": \"2.0\","
4811 " \"supported_locales\": [ \"en-GB\" ]"
4812 " },"
4813 " \"cccccccccccccccccccccccccccccccc\": {"
4814 " \"external_crx\": \"RandomExtension2.crx\","
4815 " \"external_version\": \"3.0\","
4816 " \"supported_locales\": [ \"en_US\", \"fr\" ]"
4817 " }"
4818 "}";
4819 {
4820 ScopedBrowserLocale guard("en-US");
4821 EXPECT_EQ(2, visitor.Visit(json_data));
4822 }
4823
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004824 // Test keep_if_present.
4825 json_data =
4826 "{"
4827 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4828 " \"external_crx\": \"RandomExtension.crx\","
4829 " \"external_version\": \"1.0\","
4830 " \"keep_if_present\": true"
4831 " }"
4832 "}";
4833 {
4834 EXPECT_EQ(0, visitor.Visit(json_data));
4835 }
4836
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004837 // Test is_bookmark_app.
4838 MockProviderVisitor from_bookmark_visitor(
4839 base_path, Extension::FROM_BOOKMARK);
4840 json_data =
4841 "{"
4842 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4843 " \"external_crx\": \"RandomExtension.crx\","
4844 " \"external_version\": \"1.0\","
4845 " \"is_bookmark_app\": true"
4846 " }"
4847 "}";
4848 EXPECT_EQ(1, from_bookmark_visitor.Visit(json_data));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004849
4850 // Test is_from_webstore.
4851 MockProviderVisitor from_webstore_visitor(
4852 base_path, Extension::FROM_WEBSTORE);
4853 json_data =
4854 "{"
4855 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
4856 " \"external_crx\": \"RandomExtension.crx\","
4857 " \"external_version\": \"1.0\","
4858 " \"is_from_webstore\": true"
4859 " }"
4860 "}";
4861 EXPECT_EQ(1, from_webstore_visitor.Visit(json_data));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004862}
4863
4864// Test loading good extensions from the profile directory.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004865TEST_F(ExtensionServiceTest, LoadAndRelocalizeExtensions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004866 // Ensure we're testing in "en" and leave global state untouched.
4867 extension_l10n_util::ScopedLocaleForTest testLocale("en");
4868
4869 // Initialize the test dir with a good Preferences/extensions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004870 base::FilePath source_install_dir = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004871 .AppendASCII("l10n");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004872 base::FilePath pref_path = source_install_dir.AppendASCII("Preferences");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004873 InitializeInstalledExtensionService(pref_path, source_install_dir);
4874
4875 service_->Init();
4876
4877 ASSERT_EQ(3u, loaded_.size());
4878
4879 // This was equal to "sr" on load.
4880 ValidateStringPref(loaded_[0]->id(), keys::kCurrentLocale, "en");
4881
4882 // These are untouched by re-localization.
4883 ValidateStringPref(loaded_[1]->id(), keys::kCurrentLocale, "en");
4884 EXPECT_FALSE(IsPrefExist(loaded_[1]->id(), keys::kCurrentLocale));
4885
4886 // This one starts with Serbian name, and gets re-localized into English.
4887 EXPECT_EQ("My name is simple.", loaded_[0]->name());
4888
4889 // These are untouched by re-localization.
4890 EXPECT_EQ("My name is simple.", loaded_[1]->name());
4891 EXPECT_EQ("no l10n", loaded_[2]->name());
4892}
4893
4894class ExtensionsReadyRecorder : public content::NotificationObserver {
4895 public:
4896 ExtensionsReadyRecorder() : ready_(false) {
4897 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
4898 content::NotificationService::AllSources());
4899 }
4900
4901 void set_ready(bool value) { ready_ = value; }
4902 bool ready() { return ready_; }
4903
4904 private:
4905 virtual void Observe(int type,
4906 const content::NotificationSource& source,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004907 const content::NotificationDetails& details) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004908 switch (type) {
4909 case chrome::NOTIFICATION_EXTENSIONS_READY:
4910 ready_ = true;
4911 break;
4912 default:
4913 NOTREACHED();
4914 }
4915 }
4916
4917 content::NotificationRegistrar registrar_;
4918 bool ready_;
4919};
4920
4921// Test that we get enabled/disabled correctly for all the pref/command-line
4922// combinations. We don't want to derive from the ExtensionServiceTest class
4923// for this test, so we use ExtensionServiceTestSimple.
4924//
4925// Also tests that we always fire EXTENSIONS_READY, no matter whether we are
4926// enabled or not.
4927TEST(ExtensionServiceTestSimple, Enabledness) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004928 // Make sure the PluginService singleton is destroyed at the end of the test.
4929 base::ShadowingAtExitManager at_exit_manager;
Ben Murdochca12bfa2013-07-23 11:17:05 +01004930#if defined(ENABLE_PLUGINS)
4931 content::PluginService::GetInstance()->Init();
4932 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
4933#endif
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004934
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004935 ExtensionErrorReporter::Init(false); // no noisy errors
4936 ExtensionsReadyRecorder recorder;
4937 scoped_ptr<TestingProfile> profile(new TestingProfile());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004938 base::MessageLoop loop;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004939 content::TestBrowserThread ui_thread(BrowserThread::UI, &loop);
4940 content::TestBrowserThread file_thread(BrowserThread::FILE, &loop);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004941#if defined OS_CHROMEOS
4942 chromeos::ScopedTestDeviceSettingsService device_settings_service;
4943 chromeos::ScopedTestCrosSettings cros_settings;
4944 scoped_ptr<chromeos::ScopedTestUserManager> user_manager(
4945 new chromeos::ScopedTestUserManager);
4946#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004947 scoped_ptr<CommandLine> command_line;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004948 base::FilePath install_dir = profile->GetPath()
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004949 .AppendASCII(extensions::kInstallDirectoryName);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004950
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004951 // By default, we are enabled.
4952 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
4953 ExtensionService* service = static_cast<extensions::TestExtensionSystem*>(
4954 ExtensionSystem::Get(profile.get()))->
4955 CreateExtensionService(
4956 command_line.get(),
4957 install_dir,
4958 false);
4959 EXPECT_TRUE(service->extensions_enabled());
4960 service->Init();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004961 loop.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004962 EXPECT_TRUE(recorder.ready());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004963#if defined OS_CHROMEOS
4964 user_manager.reset();
4965#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004966
4967 // If either the command line or pref is set, we are disabled.
4968 recorder.set_ready(false);
4969 profile.reset(new TestingProfile());
4970 command_line->AppendSwitch(switches::kDisableExtensions);
4971 service = static_cast<extensions::TestExtensionSystem*>(
4972 ExtensionSystem::Get(profile.get()))->
4973 CreateExtensionService(
4974 command_line.get(),
4975 install_dir,
4976 false);
4977 EXPECT_FALSE(service->extensions_enabled());
4978 service->Init();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004979 loop.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004980 EXPECT_TRUE(recorder.ready());
4981
4982 recorder.set_ready(false);
4983 profile.reset(new TestingProfile());
4984 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
4985 service = static_cast<extensions::TestExtensionSystem*>(
4986 ExtensionSystem::Get(profile.get()))->
4987 CreateExtensionService(
4988 command_line.get(),
4989 install_dir,
4990 false);
4991 EXPECT_FALSE(service->extensions_enabled());
4992 service->Init();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004993 loop.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004994 EXPECT_TRUE(recorder.ready());
4995
4996 recorder.set_ready(false);
4997 profile.reset(new TestingProfile());
4998 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
4999 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
5000 service = static_cast<extensions::TestExtensionSystem*>(
5001 ExtensionSystem::Get(profile.get()))->
5002 CreateExtensionService(
5003 command_line.get(),
5004 install_dir,
5005 false);
5006 EXPECT_FALSE(service->extensions_enabled());
5007 service->Init();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005008 loop.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005009 EXPECT_TRUE(recorder.ready());
5010
5011 // Explicitly delete all the resources used in this test.
5012 profile.reset();
5013 service = NULL;
5014 // Execute any pending deletion tasks.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005015 loop.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005016}
5017
5018// Test loading extensions that require limited and unlimited storage quotas.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005019TEST_F(ExtensionServiceTest, StorageQuota) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005020 InitializeEmptyExtensionService();
5021
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005022 base::FilePath extensions_path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005023 .AppendASCII("storage_quota");
5024
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005025 base::FilePath limited_quota_ext =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005026 extensions_path.AppendASCII("limited_quota")
5027 .AppendASCII("1.0");
5028
5029 // The old permission name for unlimited quota was "unlimited_storage", but
5030 // we changed it to "unlimitedStorage". This tests both versions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005031 base::FilePath unlimited_quota_ext =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005032 extensions_path.AppendASCII("unlimited_quota")
5033 .AppendASCII("1.0");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005034 base::FilePath unlimited_quota_ext2 =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005035 extensions_path.AppendASCII("unlimited_quota")
5036 .AppendASCII("2.0");
5037 extensions::UnpackedInstaller::Create(service_)->Load(limited_quota_ext);
5038 extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext);
5039 extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext2);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005040 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005041
5042 ASSERT_EQ(3u, loaded_.size());
5043 EXPECT_TRUE(profile_.get());
5044 EXPECT_FALSE(profile_->IsOffTheRecord());
5045 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->IsStorageUnlimited(
5046 loaded_[0]->url()));
5047 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->IsStorageUnlimited(
5048 loaded_[1]->url()));
5049 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->IsStorageUnlimited(
5050 loaded_[2]->url()));
5051}
5052
5053// Tests ComponentLoader::Add().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005054TEST_F(ExtensionServiceTest, ComponentExtensions) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005055 InitializeEmptyExtensionService();
5056
5057 // Component extensions should work even when extensions are disabled.
5058 set_extensions_enabled(false);
5059
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005060 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005061 .AppendASCII("good")
5062 .AppendASCII("Extensions")
5063 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
5064 .AppendASCII("1.0.0.0");
5065
5066 std::string manifest;
5067 ASSERT_TRUE(file_util::ReadFileToString(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005068 path.Append(extensions::kManifestFilename), &manifest));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005069
5070 service_->component_loader()->Add(manifest, path);
5071 service_->Init();
5072
5073 // Note that we do not pump messages -- the extension should be loaded
5074 // immediately.
5075
5076 EXPECT_EQ(0u, GetErrors().size());
5077 ASSERT_EQ(1u, loaded_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005078 EXPECT_EQ(Manifest::COMPONENT, loaded_[0]->location());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005079 EXPECT_EQ(1u, service_->extensions()->size());
5080
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005081 // Component extensions get a prefs entry on first install.
5082 ValidatePrefKeyCount(1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005083
5084 // Reload all extensions, and make sure it comes back.
5085 std::string extension_id = (*service_->extensions()->begin())->id();
5086 loaded_.clear();
5087 service_->ReloadExtensions();
5088 ASSERT_EQ(1u, service_->extensions()->size());
5089 EXPECT_EQ(extension_id, (*service_->extensions()->begin())->id());
5090}
5091
5092namespace {
5093 class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
5094 virtual syncer::SyncError ProcessSyncChanges(
5095 const tracked_objects::Location& from_here,
5096 const syncer::SyncChangeList& change_list) OVERRIDE {
5097 return syncer::SyncError();
5098 }
5099 };
5100}
5101
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01005102TEST_F(ExtensionServiceTest, DeferredSyncStartupPreInstalledComponent) {
5103 InitializeEmptyExtensionService();
5104
5105 bool flare_was_called = false;
5106 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
5107 base::WeakPtrFactory<ExtensionServiceTest> factory(this);
5108 service_->SetSyncStartFlare(
5109 base::Bind(&ExtensionServiceTest::MockSyncStartFlare,
5110 factory.GetWeakPtr(),
5111 &flare_was_called, // Safe due to WeakPtrFactory scope.
5112 &triggered_type)); // Safe due to WeakPtrFactory scope.
5113
5114 // Install a component extension.
5115 base::FilePath path = data_dir_
5116 .AppendASCII("good")
5117 .AppendASCII("Extensions")
5118 .AppendASCII(good0)
5119 .AppendASCII("1.0.0.0");
5120 std::string manifest;
5121 ASSERT_TRUE(file_util::ReadFileToString(
5122 path.Append(extensions::kManifestFilename), &manifest));
5123 service_->component_loader()->Add(manifest, path);
5124 ASSERT_FALSE(service_->is_ready());
5125 service_->Init();
5126 ASSERT_TRUE(service_->is_ready());
5127
5128 // Extensions added before service is_ready() don't trigger sync startup.
5129 EXPECT_FALSE(flare_was_called);
5130 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
5131}
5132
5133TEST_F(ExtensionServiceTest, DeferredSyncStartupPreInstalledNormal) {
5134 // Initialize the test dir with a good Preferences/extensions.
5135 base::FilePath source_install_dir = data_dir_
5136 .AppendASCII("good")
5137 .AppendASCII("Extensions");
5138 base::FilePath pref_path = source_install_dir
5139 .DirName()
5140 .AppendASCII("Preferences");
5141 InitializeInstalledExtensionService(pref_path, source_install_dir);
5142
5143 bool flare_was_called = false;
5144 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
5145 base::WeakPtrFactory<ExtensionServiceTest> factory(this);
5146 service_->SetSyncStartFlare(
5147 base::Bind(&ExtensionServiceTest::MockSyncStartFlare,
5148 factory.GetWeakPtr(),
5149 &flare_was_called, // Safe due to WeakPtrFactory scope.
5150 &triggered_type)); // Safe due to WeakPtrFactory scope.
5151
5152 ASSERT_FALSE(service_->is_ready());
5153 service_->Init();
5154 ASSERT_TRUE(service_->is_ready());
5155
5156 // Extensions added before service is_ready() don't trigger sync startup.
5157 EXPECT_FALSE(flare_was_called);
5158 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
5159}
5160
5161TEST_F(ExtensionServiceTest, DeferredSyncStartupOnInstall) {
5162 InitializeEmptyExtensionService();
5163 service_->Init();
5164 ASSERT_TRUE(service_->is_ready());
5165
5166 bool flare_was_called = false;
5167 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
5168 base::WeakPtrFactory<ExtensionServiceTest> factory(this);
5169 service_->SetSyncStartFlare(
5170 base::Bind(&ExtensionServiceTest::MockSyncStartFlare,
5171 factory.GetWeakPtr(),
5172 &flare_was_called, // Safe due to WeakPtrFactory scope.
5173 &triggered_type)); // Safe due to WeakPtrFactory scope.
5174
5175 base::FilePath path = data_dir_.AppendASCII("good.crx");
5176 InstallCRX(path, INSTALL_NEW);
5177
5178 EXPECT_TRUE(flare_was_called);
5179 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
5180
5181 // Reset.
5182 flare_was_called = false;
5183 triggered_type = syncer::UNSPECIFIED;
5184
5185 // Once sync starts, flare should no longer be invoked.
5186 service_->MergeDataAndStartSyncing(
5187 syncer::EXTENSIONS, syncer::SyncDataList(),
5188 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5189 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5190 path = data_dir_.AppendASCII("page_action.crx");
5191 InstallCRX(path, INSTALL_NEW);
5192 EXPECT_FALSE(flare_was_called);
5193 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
5194}
5195
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005196TEST_F(ExtensionServiceTest, GetSyncData) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005197 InitializeEmptyExtensionService();
5198 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5199 const Extension* extension = service_->GetInstalledExtension(good_crx);
5200 ASSERT_TRUE(extension);
5201
5202 service_->MergeDataAndStartSyncing(
5203 syncer::EXTENSIONS, syncer::SyncDataList(),
5204 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5205 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5206
5207 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5208 ASSERT_EQ(list.size(), 1U);
5209 extensions::ExtensionSyncData data(list[0]);
5210 EXPECT_EQ(extension->id(), data.id());
5211 EXPECT_FALSE(data.uninstalled());
5212 EXPECT_EQ(service_->IsExtensionEnabled(good_crx), data.enabled());
5213 EXPECT_EQ(service_->IsIncognitoEnabled(good_crx), data.incognito_enabled());
5214 EXPECT_TRUE(data.version().Equals(*extension->version()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005215 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
5216 data.update_url());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005217 EXPECT_EQ(extension->name(), data.name());
5218}
5219
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005220TEST_F(ExtensionServiceTest, GetSyncDataTerminated) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005221 InitializeEmptyExtensionService();
5222 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5223 TerminateExtension(good_crx);
5224 const Extension* extension = service_->GetInstalledExtension(good_crx);
5225 ASSERT_TRUE(extension);
5226
5227 TestSyncProcessorStub processor;
5228 service_->MergeDataAndStartSyncing(
5229 syncer::EXTENSIONS, syncer::SyncDataList(),
5230 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5231 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5232
5233 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5234 ASSERT_EQ(list.size(), 1U);
5235 extensions::ExtensionSyncData data(list[0]);
5236 EXPECT_EQ(extension->id(), data.id());
5237 EXPECT_FALSE(data.uninstalled());
5238 EXPECT_EQ(service_->IsExtensionEnabled(good_crx), data.enabled());
5239 EXPECT_EQ(service_->IsIncognitoEnabled(good_crx), data.incognito_enabled());
5240 EXPECT_TRUE(data.version().Equals(*extension->version()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005241 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
5242 data.update_url());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005243 EXPECT_EQ(extension->name(), data.name());
5244}
5245
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005246TEST_F(ExtensionServiceTest, GetSyncDataFilter) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005247 InitializeEmptyExtensionService();
5248 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5249 const Extension* extension = service_->GetInstalledExtension(good_crx);
5250 ASSERT_TRUE(extension);
5251
5252 TestSyncProcessorStub processor;
5253 service_->MergeDataAndStartSyncing(syncer::APPS, syncer::SyncDataList(),
5254 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5255 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5256
5257 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5258 ASSERT_EQ(list.size(), 0U);
5259}
5260
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005261TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005262 InitializeEmptyExtensionService();
5263 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5264 const Extension* extension = service_->GetInstalledExtension(good_crx);
5265 ASSERT_TRUE(extension);
5266
5267 TestSyncProcessorStub processor;
5268 service_->MergeDataAndStartSyncing(
5269 syncer::EXTENSIONS, syncer::SyncDataList(),
5270 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5271 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5272
5273 {
5274 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5275 ASSERT_EQ(list.size(), 1U);
5276 extensions::ExtensionSyncData data(list[0]);
5277 EXPECT_TRUE(data.enabled());
5278 EXPECT_FALSE(data.incognito_enabled());
5279 }
5280
5281 service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
5282 {
5283 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5284 ASSERT_EQ(list.size(), 1U);
5285 extensions::ExtensionSyncData data(list[0]);
5286 EXPECT_FALSE(data.enabled());
5287 EXPECT_FALSE(data.incognito_enabled());
5288 }
5289
5290 service_->SetIsIncognitoEnabled(good_crx, true);
5291 {
5292 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5293 ASSERT_EQ(list.size(), 1U);
5294 extensions::ExtensionSyncData data(list[0]);
5295 EXPECT_FALSE(data.enabled());
5296 EXPECT_TRUE(data.incognito_enabled());
5297 }
5298
5299 service_->EnableExtension(good_crx);
5300 {
5301 syncer::SyncDataList list = service_->GetAllSyncData(syncer::EXTENSIONS);
5302 ASSERT_EQ(list.size(), 1U);
5303 extensions::ExtensionSyncData data(list[0]);
5304 EXPECT_TRUE(data.enabled());
5305 EXPECT_TRUE(data.incognito_enabled());
5306 }
5307}
5308
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005309TEST_F(ExtensionServiceTest, SyncForUninstalledExternalExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005310 InitializeEmptyExtensionService();
5311 InstallCRXWithLocation(data_dir_.AppendASCII("good.crx"),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005312 Manifest::EXTERNAL_PREF, INSTALL_NEW);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005313 const Extension* extension = service_->GetInstalledExtension(good_crx);
5314 ASSERT_TRUE(extension);
5315
5316 TestSyncProcessorStub processor;
5317 service_->MergeDataAndStartSyncing(
5318 syncer::EXTENSIONS, syncer::SyncDataList(),
5319 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5320 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5321
5322 UninstallExtension(good_crx, false);
5323 EXPECT_TRUE(service_->IsExternalExtensionUninstalled(good_crx));
5324
5325 sync_pb::EntitySpecifics specifics;
5326 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
5327 sync_pb::ExtensionSpecifics* extension_specifics =
5328 app_specifics->mutable_extension();
5329 extension_specifics->set_id(good_crx);
5330 extension_specifics->set_version("1.0");
5331 extension_specifics->set_enabled(true);
5332
5333 syncer::SyncData sync_data =
5334 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5335 syncer::SyncChange sync_change(FROM_HERE,
5336 syncer::SyncChange::ACTION_UPDATE,
5337 sync_data);
5338 syncer::SyncChangeList list(1);
5339 list[0] = sync_change;
5340
5341 service_->ProcessSyncChanges(FROM_HERE, list);
5342 EXPECT_TRUE(service_->IsExternalExtensionUninstalled(good_crx));
5343}
5344
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005345TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettings) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005346 InitializeEmptyExtensionService();
5347 const Extension* app =
5348 PackAndInstallCRX(data_dir_.AppendASCII("app"), INSTALL_NEW);
5349 ASSERT_TRUE(app);
5350 ASSERT_TRUE(app->is_app());
5351
5352 TestSyncProcessorStub processor;
5353 service_->MergeDataAndStartSyncing(syncer::APPS, syncer::SyncDataList(),
5354 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5355 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5356
5357 syncer::StringOrdinal initial_ordinal =
5358 syncer::StringOrdinal::CreateInitialOrdinal();
5359 {
5360 syncer::SyncDataList list = service_->GetAllSyncData(syncer::APPS);
5361 ASSERT_EQ(list.size(), 1U);
5362
5363 extensions::AppSyncData app_sync_data(list[0]);
5364 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data.app_launch_ordinal()));
5365 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data.page_ordinal()));
5366 }
5367
5368 ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting();
5369 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
5370 {
5371 syncer::SyncDataList list = service_->GetAllSyncData(syncer::APPS);
5372 ASSERT_EQ(list.size(), 1U);
5373
5374 extensions::AppSyncData app_sync_data(list[0]);
5375 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.app_launch_ordinal()));
5376 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data.page_ordinal()));
5377 }
5378
5379 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
5380 {
5381 syncer::SyncDataList list = service_->GetAllSyncData(syncer::APPS);
5382 ASSERT_EQ(list.size(), 1U);
5383
5384 extensions::AppSyncData app_sync_data(list[0]);
5385 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.app_launch_ordinal()));
5386 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.page_ordinal()));
5387 }
5388}
5389
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005390TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005391 InitializeEmptyExtensionService();
5392 const size_t kAppCount = 3;
5393 const Extension* apps[kAppCount];
5394 apps[0] = PackAndInstallCRX(data_dir_.AppendASCII("app1"), INSTALL_NEW);
5395 apps[1] = PackAndInstallCRX(data_dir_.AppendASCII("app2"), INSTALL_NEW);
5396 apps[2] = PackAndInstallCRX(data_dir_.AppendASCII("app4"), INSTALL_NEW);
5397 for (size_t i = 0; i < kAppCount; ++i) {
5398 ASSERT_TRUE(apps[i]);
5399 ASSERT_TRUE(apps[i]->is_app());
5400 }
5401
5402 TestSyncProcessorStub processor;
5403 service_->MergeDataAndStartSyncing(syncer::APPS, syncer::SyncDataList(),
5404 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5405 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5406
5407 service_->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
5408 {
5409 syncer::SyncDataList list = service_->GetAllSyncData(syncer::APPS);
5410 ASSERT_EQ(list.size(), 3U);
5411
5412 extensions::AppSyncData data[kAppCount];
5413 for (size_t i = 0; i < kAppCount; ++i) {
5414 data[i] = extensions::AppSyncData(list[i]);
5415 }
5416
5417 // The sync data is not always in the same order our apps were installed in,
5418 // so we do that sorting here so we can make sure the values are changed as
5419 // expected.
5420 syncer::StringOrdinal app_launch_ordinals[kAppCount];
5421 for (size_t i = 0; i < kAppCount; ++i) {
5422 for (size_t j = 0; j < kAppCount; ++j) {
5423 if (apps[i]->id() == data[j].id())
5424 app_launch_ordinals[i] = data[j].app_launch_ordinal();
5425 }
5426 }
5427
5428 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
5429 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
5430 }
5431}
5432
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005433TEST_F(ExtensionServiceTest, GetSyncDataList) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005434 InitializeEmptyExtensionService();
5435 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5436 InstallCRX(data_dir_.AppendASCII("page_action.crx"), INSTALL_NEW);
5437 InstallCRX(data_dir_.AppendASCII("theme.crx"), INSTALL_NEW);
5438 InstallCRX(data_dir_.AppendASCII("theme2.crx"), INSTALL_NEW);
5439
5440 TestSyncProcessorStub processor;
5441 service_->MergeDataAndStartSyncing(syncer::APPS, syncer::SyncDataList(),
5442 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5443 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5444 service_->MergeDataAndStartSyncing(
5445 syncer::EXTENSIONS, syncer::SyncDataList(),
5446 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5447 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5448
5449 service_->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
5450 TerminateExtension(theme2_crx);
5451
5452 EXPECT_EQ(0u, service_->GetAllSyncData(syncer::APPS).size());
5453 EXPECT_EQ(2u, service_->GetAllSyncData(syncer::EXTENSIONS).size());
5454}
5455
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005456TEST_F(ExtensionServiceTest, ProcessSyncDataUninstall) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005457 InitializeEmptyExtensionService();
5458 TestSyncProcessorStub processor;
5459 service_->MergeDataAndStartSyncing(
5460 syncer::EXTENSIONS, syncer::SyncDataList(),
5461 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5462 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5463
5464 sync_pb::EntitySpecifics specifics;
5465 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
5466 ext_specifics->set_id(good_crx);
5467 ext_specifics->set_version("1.0");
5468 syncer::SyncData sync_data =
5469 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5470 syncer::SyncChange sync_change(FROM_HERE,
5471 syncer::SyncChange::ACTION_DELETE,
5472 sync_data);
5473 syncer::SyncChangeList list(1);
5474 list[0] = sync_change;
5475
5476 // Should do nothing.
5477 service_->ProcessSyncChanges(FROM_HERE, list);
5478 EXPECT_FALSE(service_->GetExtensionById(good_crx, true));
5479
5480 // Install the extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005481 base::FilePath extension_path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005482 InstallCRX(extension_path, INSTALL_NEW);
5483 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
5484
5485 // Should uninstall the extension.
5486 service_->ProcessSyncChanges(FROM_HERE, list);
5487 EXPECT_FALSE(service_->GetExtensionById(good_crx, true));
5488
5489 // Should again do nothing.
5490 service_->ProcessSyncChanges(FROM_HERE, list);
5491 EXPECT_FALSE(service_->GetExtensionById(good_crx, true));
5492}
5493
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005494TEST_F(ExtensionServiceTest, ProcessSyncDataWrongType) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005495 InitializeEmptyExtensionService();
5496
5497 // Install the extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005498 base::FilePath extension_path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005499 InstallCRX(extension_path, INSTALL_NEW);
5500 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
5501
5502 sync_pb::EntitySpecifics specifics;
5503 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
5504 sync_pb::ExtensionSpecifics* extension_specifics =
5505 app_specifics->mutable_extension();
5506 extension_specifics->set_id(good_crx);
5507 extension_specifics->set_version(
5508 service_->GetInstalledExtension(good_crx)->version()->GetString());
5509
5510 {
5511 extension_specifics->set_enabled(true);
5512 syncer::SyncData sync_data =
5513 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5514 syncer::SyncChange sync_change(FROM_HERE,
5515 syncer::SyncChange::ACTION_DELETE,
5516 sync_data);
5517 syncer::SyncChangeList list(1);
5518 list[0] = sync_change;
5519
5520 // Should do nothing
5521 service_->ProcessSyncChanges(FROM_HERE, list);
5522 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
5523 }
5524
5525 {
5526 extension_specifics->set_enabled(false);
5527 syncer::SyncData sync_data =
5528 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5529 syncer::SyncChange sync_change(FROM_HERE,
5530 syncer::SyncChange::ACTION_UPDATE,
5531 sync_data);
5532 syncer::SyncChangeList list(1);
5533 list[0] = sync_change;
5534
5535 // Should again do nothing.
5536 service_->ProcessSyncChanges(FROM_HERE, list);
5537 EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
5538 }
5539}
5540
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005541TEST_F(ExtensionServiceTest, ProcessSyncDataSettings) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005542 InitializeEmptyExtensionService();
5543 InitializeExtensionProcessManager();
5544 TestSyncProcessorStub processor;
5545 service_->MergeDataAndStartSyncing(
5546 syncer::EXTENSIONS, syncer::SyncDataList(),
5547 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5548 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5549
5550 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5551 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
5552 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
5553
5554 sync_pb::EntitySpecifics specifics;
5555 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
5556 ext_specifics->set_id(good_crx);
5557 ext_specifics->set_version(
5558 service_->GetInstalledExtension(good_crx)->version()->GetString());
5559 ext_specifics->set_enabled(false);
5560
5561 {
5562 syncer::SyncData sync_data =
5563 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5564 syncer::SyncChange sync_change(FROM_HERE,
5565 syncer::SyncChange::ACTION_UPDATE,
5566 sync_data);
5567 syncer::SyncChangeList list(1);
5568 list[0] = sync_change;
5569 service_->ProcessSyncChanges(FROM_HERE, list);
5570 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
5571 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
5572 }
5573
5574 {
5575 ext_specifics->set_enabled(true);
5576 ext_specifics->set_incognito_enabled(true);
5577 syncer::SyncData sync_data =
5578 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5579 syncer::SyncChange sync_change(FROM_HERE,
5580 syncer::SyncChange::ACTION_UPDATE,
5581 sync_data);
5582 syncer::SyncChangeList list(1);
5583 list[0] = sync_change;
5584 service_->ProcessSyncChanges(FROM_HERE, list);
5585 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
5586 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
5587 }
5588
5589 {
5590 ext_specifics->set_enabled(false);
5591 ext_specifics->set_incognito_enabled(true);
5592 syncer::SyncData sync_data =
5593 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5594 syncer::SyncChange sync_change(FROM_HERE,
5595 syncer::SyncChange::ACTION_UPDATE,
5596 sync_data);
5597 syncer::SyncChangeList list(1);
5598 list[0] = sync_change;
5599 service_->ProcessSyncChanges(FROM_HERE, list);
5600 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
5601 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
5602 }
5603
5604 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
5605}
5606
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005607TEST_F(ExtensionServiceTest, ProcessSyncDataTerminatedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005608 InitializeExtensionServiceWithUpdater();
5609 TestSyncProcessorStub processor;
5610 service_->MergeDataAndStartSyncing(
5611 syncer::EXTENSIONS, syncer::SyncDataList(),
5612 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5613 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5614
5615 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5616 TerminateExtension(good_crx);
5617 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
5618 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
5619
5620 sync_pb::EntitySpecifics specifics;
5621 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
5622 ext_specifics->set_id(good_crx);
5623 ext_specifics->set_version(
5624 service_->GetInstalledExtension(good_crx)->version()->GetString());
5625 ext_specifics->set_enabled(false);
5626 ext_specifics->set_incognito_enabled(true);
5627 syncer::SyncData sync_data =
5628 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5629 syncer::SyncChange sync_change(FROM_HERE,
5630 syncer::SyncChange::ACTION_UPDATE,
5631 sync_data);
5632 syncer::SyncChangeList list(1);
5633 list[0] = sync_change;
5634
5635 service_->ProcessSyncChanges(FROM_HERE, list);
5636 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
5637 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
5638
5639 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
5640}
5641
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005642TEST_F(ExtensionServiceTest, ProcessSyncDataVersionCheck) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005643 InitializeExtensionServiceWithUpdater();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005644 TestSyncProcessorStub processor;
5645 service_->MergeDataAndStartSyncing(
5646 syncer::EXTENSIONS, syncer::SyncDataList(),
5647 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5648 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5649
5650 InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
5651 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
5652 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
5653
5654 sync_pb::EntitySpecifics specifics;
5655 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
5656 ext_specifics->set_id(good_crx);
5657 ext_specifics->set_enabled(true);
5658
5659 {
5660 ext_specifics->set_version(
5661 service_->GetInstalledExtension(good_crx)->version()->GetString());
5662 syncer::SyncData sync_data =
5663 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5664 syncer::SyncChange sync_change(FROM_HERE,
5665 syncer::SyncChange::ACTION_UPDATE,
5666 sync_data);
5667 syncer::SyncChangeList list(1);
5668 list[0] = sync_change;
5669
5670 // Should do nothing if extension version == sync version.
5671 service_->ProcessSyncChanges(FROM_HERE, list);
5672 EXPECT_FALSE(service_->updater()->WillCheckSoon());
5673 }
5674
5675 // Should do nothing if extension version > sync version (but see
5676 // the TODO in ProcessExtensionSyncData).
5677 {
5678 ext_specifics->set_version("0.0.0.0");
5679 syncer::SyncData sync_data =
5680 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5681 syncer::SyncChange sync_change(FROM_HERE,
5682 syncer::SyncChange::ACTION_UPDATE,
5683 sync_data);
5684 syncer::SyncChangeList list(1);
5685 list[0] = sync_change;
5686
5687 service_->ProcessSyncChanges(FROM_HERE, list);
5688 EXPECT_FALSE(service_->updater()->WillCheckSoon());
5689 }
5690
5691 // Should kick off an update if extension version < sync version.
5692 {
5693 ext_specifics->set_version("9.9.9.9");
5694 syncer::SyncData sync_data =
5695 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5696 syncer::SyncChange sync_change(FROM_HERE,
5697 syncer::SyncChange::ACTION_UPDATE,
5698 sync_data);
5699 syncer::SyncChangeList list(1);
5700 list[0] = sync_change;
5701
5702 service_->ProcessSyncChanges(FROM_HERE, list);
5703 EXPECT_TRUE(service_->updater()->WillCheckSoon());
5704 }
5705
5706 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
5707}
5708
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005709TEST_F(ExtensionServiceTest, ProcessSyncDataNotInstalled) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005710 InitializeExtensionServiceWithUpdater();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005711 TestSyncProcessorStub processor;
5712 service_->MergeDataAndStartSyncing(
5713 syncer::EXTENSIONS, syncer::SyncDataList(),
5714 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
5715 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
5716
5717 sync_pb::EntitySpecifics specifics;
5718 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
5719 ext_specifics->set_id(good_crx);
5720 ext_specifics->set_enabled(false);
5721 ext_specifics->set_incognito_enabled(true);
5722 ext_specifics->set_update_url("http://www.google.com/");
5723 ext_specifics->set_version("1.2.3.4");
5724 syncer::SyncData sync_data =
5725 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
5726 syncer::SyncChange sync_change(FROM_HERE,
5727 syncer::SyncChange::ACTION_UPDATE,
5728 sync_data);
5729 syncer::SyncChangeList list(1);
5730 list[0] = sync_change;
5731
5732
5733 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
5734 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
5735 service_->ProcessSyncChanges(FROM_HERE, list);
5736 EXPECT_TRUE(service_->updater()->WillCheckSoon());
5737 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
5738 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
5739
5740 const extensions::PendingExtensionInfo* info;
5741 EXPECT_TRUE((info = service_->pending_extension_manager()->
5742 GetById(good_crx)));
5743 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
5744 EXPECT_TRUE(info->is_from_sync());
5745 EXPECT_TRUE(info->install_silently());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005746 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005747 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
5748}
5749
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005750TEST_F(ExtensionServiceTest, InstallPriorityExternalUpdateUrl) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005751 InitializeEmptyExtensionService();
5752
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005753 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005754 InstallCRX(path, INSTALL_NEW);
5755 ValidatePrefKeyCount(1u);
5756 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005757 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005758
5759 extensions::PendingExtensionManager* pending =
5760 service_->pending_extension_manager();
5761 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5762
5763 // Skip install when the location is the same.
5764 EXPECT_FALSE(
5765 service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005766 kGoodId, GURL(kGoodUpdateURL), Manifest::INTERNAL));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005767 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5768
5769 // Install when the location has higher priority.
5770 EXPECT_TRUE(
5771 service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005772 kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_POLICY_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005773 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5774
5775 // Try the low priority again. Should be rejected.
5776 EXPECT_FALSE(
5777 service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005778 kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_PREF_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005779 // The existing record should still be present in the pending extension
5780 // manager.
5781 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5782
5783 pending->Remove(kGoodId);
5784
5785 // Skip install when the location has the same priority as the installed
5786 // location.
5787 EXPECT_FALSE(service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005788 kGoodId, GURL(kGoodUpdateURL), Manifest::INTERNAL));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005789
5790 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5791}
5792
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005793TEST_F(ExtensionServiceTest, InstallPriorityExternalLocalFile) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005794 Version older_version("0.1.0.0");
5795 Version newer_version("2.0.0.0");
5796
5797 // We don't want the extension to be installed. A path that doesn't
5798 // point to a valid CRX ensures this.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005799 const base::FilePath kInvalidPathToCrx = base::FilePath();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005800
5801 const int kCreationFlags = 0;
5802 const bool kDontMarkAcknowledged = false;
5803
5804 InitializeEmptyExtensionService();
5805
5806 // The test below uses install source constants to test that
5807 // priority is enforced. It assumes a specific ranking of install
5808 // sources: Registry (EXTERNAL_REGISTRY) overrides external pref
5809 // (EXTERNAL_PREF), and external pref overrides user install (INTERNAL).
5810 // The following assertions verify these assumptions:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005811 ASSERT_EQ(Manifest::EXTERNAL_REGISTRY,
5812 Manifest::GetHigherPriorityLocation(Manifest::EXTERNAL_REGISTRY,
5813 Manifest::EXTERNAL_PREF));
5814 ASSERT_EQ(Manifest::EXTERNAL_REGISTRY,
5815 Manifest::GetHigherPriorityLocation(Manifest::EXTERNAL_REGISTRY,
5816 Manifest::INTERNAL));
5817 ASSERT_EQ(Manifest::EXTERNAL_PREF,
5818 Manifest::GetHigherPriorityLocation(Manifest::EXTERNAL_PREF,
5819 Manifest::INTERNAL));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005820
5821 extensions::PendingExtensionManager* pending =
5822 service_->pending_extension_manager();
5823 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5824
5825 // Simulate an external source adding the extension as INTERNAL.
5826 EXPECT_TRUE(
5827 service_->OnExternalExtensionFileFound(
5828 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005829 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005830 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5831 WaitForCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
5832
5833 // Simulate an external source adding the extension as EXTERNAL_PREF.
5834 EXPECT_TRUE(
5835 service_->OnExternalExtensionFileFound(
5836 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005837 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005838 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5839 WaitForCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
5840
5841 // Simulate an external source adding as EXTERNAL_PREF again.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005842 // This is rejected because the version and the location are the same as
5843 // the previous installation, which is still pending.
5844 EXPECT_FALSE(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005845 service_->OnExternalExtensionFileFound(
5846 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005847 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005848 EXPECT_TRUE(pending->IsIdPending(kGoodId));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005849
5850 // Try INTERNAL again. Should fail.
5851 EXPECT_FALSE(
5852 service_->OnExternalExtensionFileFound(
5853 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005854 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005855 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5856
5857 // Now the registry adds the extension.
5858 EXPECT_TRUE(
5859 service_->OnExternalExtensionFileFound(
5860 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005861 Manifest::EXTERNAL_REGISTRY, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005862 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5863 WaitForCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
5864
5865 // Registry outranks both external pref and internal, so both fail.
5866 EXPECT_FALSE(
5867 service_->OnExternalExtensionFileFound(
5868 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005869 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005870 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5871
5872 EXPECT_FALSE(
5873 service_->OnExternalExtensionFileFound(
5874 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005875 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005876 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5877
5878 pending->Remove(kGoodId);
5879
5880 // Install the extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005881 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005882 const Extension* ext = InstallCRX(path, INSTALL_NEW);
5883 ValidatePrefKeyCount(1u);
5884 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005885 ValidateIntegerPref(good_crx, "location", Manifest::INTERNAL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005886
5887 // Now test the logic of OnExternalExtensionFileFound() when the extension
5888 // being added is already installed.
5889
5890 // Tests assume |older_version| is less than the installed version, and
5891 // |newer_version| is greater. Verify this:
5892 ASSERT_TRUE(older_version.IsOlderThan(ext->VersionString()));
5893 ASSERT_TRUE(ext->version()->IsOlderThan(newer_version.GetString()));
5894
5895 // An external install for the same location should fail if the version is
5896 // older, or the same, and succeed if the version is newer.
5897
5898 // Older than the installed version...
5899 EXPECT_FALSE(
5900 service_->OnExternalExtensionFileFound(
5901 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005902 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005903 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5904
5905 // Same version as the installed version...
5906 EXPECT_FALSE(
5907 service_->OnExternalExtensionFileFound(
5908 kGoodId, ext->version(), kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005909 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005910 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5911
5912 // Newer than the installed version...
5913 EXPECT_TRUE(
5914 service_->OnExternalExtensionFileFound(
5915 kGoodId, &newer_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005916 Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005917 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5918
5919 // An external install for a higher priority install source should succeed
5920 // if the version is greater. |older_version| is not...
5921 EXPECT_FALSE(
5922 service_->OnExternalExtensionFileFound(
5923 kGoodId, &older_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005924 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005925 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5926
5927 // |newer_version| is newer.
5928 EXPECT_TRUE(
5929 service_->OnExternalExtensionFileFound(
5930 kGoodId, &newer_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005931 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005932 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5933
5934 // An external install for an even higher priority install source should
5935 // succeed if the version is greater.
5936 EXPECT_TRUE(
5937 service_->OnExternalExtensionFileFound(
5938 kGoodId, &newer_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005939 Manifest::EXTERNAL_REGISTRY, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005940 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5941
5942 // Because EXTERNAL_PREF is a lower priority source than EXTERNAL_REGISTRY,
5943 // adding from external pref will now fail.
5944 EXPECT_FALSE(
5945 service_->OnExternalExtensionFileFound(
5946 kGoodId, &newer_version, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005947 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005948 EXPECT_TRUE(pending->IsIdPending(kGoodId));
5949}
5950
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005951TEST_F(ExtensionServiceTest, ConcurrentExternalLocalFile) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005952 Version kVersion123("1.2.3");
5953 Version kVersion124("1.2.4");
5954 Version kVersion125("1.2.5");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005955 const base::FilePath kInvalidPathToCrx = base::FilePath();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005956 const int kCreationFlags = 0;
5957 const bool kDontMarkAcknowledged = false;
5958
5959 InitializeEmptyExtensionService();
5960
5961 extensions::PendingExtensionManager* pending =
5962 service_->pending_extension_manager();
5963 EXPECT_FALSE(pending->IsIdPending(kGoodId));
5964
5965 // An external provider starts installing from a local crx.
5966 EXPECT_TRUE(
5967 service_->OnExternalExtensionFileFound(
5968 kGoodId, &kVersion123, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005969 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005970 const extensions::PendingExtensionInfo* info;
5971 EXPECT_TRUE((info = pending->GetById(kGoodId)));
5972 EXPECT_TRUE(info->version().IsValid());
5973 EXPECT_TRUE(info->version().Equals(kVersion123));
5974
5975 // Adding a newer version overrides the currently pending version.
5976 EXPECT_TRUE(
5977 service_->OnExternalExtensionFileFound(
5978 kGoodId, &kVersion124, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005979 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005980 EXPECT_TRUE((info = pending->GetById(kGoodId)));
5981 EXPECT_TRUE(info->version().IsValid());
5982 EXPECT_TRUE(info->version().Equals(kVersion124));
5983
5984 // Adding an older version fails.
5985 EXPECT_FALSE(
5986 service_->OnExternalExtensionFileFound(
5987 kGoodId, &kVersion123, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005988 Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005989 EXPECT_TRUE((info = pending->GetById(kGoodId)));
5990 EXPECT_TRUE(info->version().IsValid());
5991 EXPECT_TRUE(info->version().Equals(kVersion124));
5992
5993 // Adding an older version fails even when coming from a higher-priority
5994 // location.
5995 EXPECT_FALSE(
5996 service_->OnExternalExtensionFileFound(
5997 kGoodId, &kVersion123, kInvalidPathToCrx,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005998 Manifest::EXTERNAL_REGISTRY, kCreationFlags, kDontMarkAcknowledged));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005999 EXPECT_TRUE((info = pending->GetById(kGoodId)));
6000 EXPECT_TRUE(info->version().IsValid());
6001 EXPECT_TRUE(info->version().Equals(kVersion124));
6002
6003 // Adding the latest version from the webstore overrides a specific version.
6004 GURL kUpdateUrl("http://example.com/update");
6005 EXPECT_TRUE(
6006 service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006007 kGoodId, kUpdateUrl, Manifest::EXTERNAL_POLICY_DOWNLOAD));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006008 EXPECT_TRUE((info = pending->GetById(kGoodId)));
6009 EXPECT_FALSE(info->version().IsValid());
6010}
6011
6012// This makes sure we can package and install CRX files that use whitelisted
6013// permissions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006014TEST_F(ExtensionServiceTest, InstallWhitelistedExtension) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006015 std::string test_id = "hdkklepkcpckhnpgjnmbdfhehckloojk";
6016 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
6017 switches::kWhitelistedExtensionID, test_id);
6018
6019 InitializeEmptyExtensionService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006020 base::FilePath path = data_dir_
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006021 .AppendASCII("permissions");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006022 base::FilePath pem_path = path
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006023 .AppendASCII("whitelist.pem");
6024 path = path
6025 .AppendASCII("whitelist");
6026
6027 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
6028 EXPECT_EQ(0u, GetErrors().size());
6029 ASSERT_EQ(1u, service_->extensions()->size());
6030 EXPECT_EQ(test_id, extension->id());
6031}
6032
6033// Test that when multiple sources try to install an extension,
6034// we consistently choose the right one. To make tests easy to read,
6035// methods that fake requests to install crx files in several ways
6036// are provided.
6037class ExtensionSourcePriorityTest : public ExtensionServiceTest {
6038 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006039 virtual void SetUp() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006040 ExtensionServiceTest::SetUp();
6041
6042 // All tests use a single extension. Put the id and path in member vars
6043 // that all methods can read.
6044 crx_id_ = kGoodId;
6045 crx_path_ = data_dir_.AppendASCII("good.crx");
6046 }
6047
6048 // Fake an external source adding a URL to fetch an extension from.
6049 bool AddPendingExternalPrefUrl() {
6050 return service_->pending_extension_manager()->AddFromExternalUpdateUrl(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006051 crx_id_, GURL(), Manifest::EXTERNAL_PREF_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006052 }
6053
6054 // Fake an external file from external_extensions.json.
6055 bool AddPendingExternalPrefFileInstall() {
6056 Version version("1.0.0.0");
6057
6058 return service_->OnExternalExtensionFileFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006059 crx_id_, &version, crx_path_, Manifest::EXTERNAL_PREF,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006060 Extension::NO_FLAGS, false);
6061 }
6062
6063 // Fake a request from sync to install an extension.
6064 bool AddPendingSyncInstall() {
6065 return service_->pending_extension_manager()->AddFromSync(
6066 crx_id_, GURL(kGoodUpdateURL), &IsExtension, kGoodInstallSilently);
6067 }
6068
6069 // Fake a policy install.
6070 bool AddPendingPolicyInstall() {
6071 // Get path to the CRX with id |kGoodId|.
6072 return service_->OnExternalExtensionUpdateUrlFound(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006073 crx_id_, GURL(), Manifest::EXTERNAL_POLICY_DOWNLOAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006074 }
6075
6076 // Get the install source of a pending extension.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006077 Manifest::Location GetPendingLocation() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006078 const extensions::PendingExtensionInfo* info;
6079 EXPECT_TRUE((info = service_->pending_extension_manager()->
6080 GetById(crx_id_)));
6081 return info->install_source();
6082 }
6083
6084 // Is an extension pending from a sync request?
6085 bool GetPendingIsFromSync() {
6086 const extensions::PendingExtensionInfo* info;
6087 EXPECT_TRUE((info = service_->pending_extension_manager()->
6088 GetById(crx_id_)));
6089 return info->is_from_sync();
6090 }
6091
6092 // Is the CRX id these tests use pending?
6093 bool IsCrxPending() {
6094 return service_->pending_extension_manager()->IsIdPending(crx_id_);
6095 }
6096
6097 // Is an extension installed?
6098 bool IsCrxInstalled() {
6099 return (service_->GetExtensionById(crx_id_, true) != NULL);
6100 }
6101
6102 protected:
6103 // All tests use a single extension. Making the id and path member
6104 // vars avoids pasing the same argument to every method.
6105 std::string crx_id_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006106 base::FilePath crx_path_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006107};
6108
6109// Test that a pending request for installation of an external CRX from
6110// an update URL overrides a pending request to install the same extension
6111// from sync.
6112TEST_F(ExtensionSourcePriorityTest, PendingExternalFileOverSync) {
6113 InitializeEmptyExtensionService();
6114
6115 ASSERT_FALSE(IsCrxInstalled());
6116
6117 // Install pending extension from sync.
6118 EXPECT_TRUE(AddPendingSyncInstall());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006119 ASSERT_EQ(Manifest::INTERNAL, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006120 EXPECT_TRUE(GetPendingIsFromSync());
6121 ASSERT_FALSE(IsCrxInstalled());
6122
6123 // Install pending as external prefs json would.
6124 AddPendingExternalPrefFileInstall();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006125 ASSERT_EQ(Manifest::EXTERNAL_PREF, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006126 ASSERT_FALSE(IsCrxInstalled());
6127
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006128 // Another request from sync should be ignored.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006129 EXPECT_FALSE(AddPendingSyncInstall());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006130 ASSERT_EQ(Manifest::EXTERNAL_PREF, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006131 ASSERT_FALSE(IsCrxInstalled());
6132
6133 WaitForCrxInstall(crx_path_, INSTALL_NEW);
6134 ASSERT_TRUE(IsCrxInstalled());
6135}
6136
6137// Test that an install of an external CRX from an update overrides
6138// an install of the same extension from sync.
6139TEST_F(ExtensionSourcePriorityTest, PendingExternalUrlOverSync) {
6140 InitializeEmptyExtensionService();
6141 ASSERT_FALSE(IsCrxInstalled());
6142
6143 EXPECT_TRUE(AddPendingSyncInstall());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006144 ASSERT_EQ(Manifest::INTERNAL, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006145 EXPECT_TRUE(GetPendingIsFromSync());
6146 ASSERT_FALSE(IsCrxInstalled());
6147
6148 ASSERT_TRUE(AddPendingExternalPrefUrl());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006149 ASSERT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006150 EXPECT_FALSE(GetPendingIsFromSync());
6151 ASSERT_FALSE(IsCrxInstalled());
6152
6153 EXPECT_FALSE(AddPendingSyncInstall());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006154 ASSERT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, GetPendingLocation());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006155 EXPECT_FALSE(GetPendingIsFromSync());
6156 ASSERT_FALSE(IsCrxInstalled());
6157}
6158
6159// Test that an external install request stops sync from installing
6160// the same extension.
6161TEST_F(ExtensionSourcePriorityTest, InstallExternalBlocksSyncRequest) {
6162 InitializeEmptyExtensionService();
6163 ASSERT_FALSE(IsCrxInstalled());
6164
6165 // External prefs starts an install.
6166 AddPendingExternalPrefFileInstall();
6167
6168 // Crx installer was made, but has not yet run.
6169 ASSERT_FALSE(IsCrxInstalled());
6170
6171 // Before the CRX installer runs, Sync requests that the same extension
6172 // be installed. Should fail, because an external source is pending.
6173 ASSERT_FALSE(AddPendingSyncInstall());
6174
6175 // Wait for the external source to install.
6176 WaitForCrxInstall(crx_path_, INSTALL_NEW);
6177 ASSERT_TRUE(IsCrxInstalled());
6178
6179 // Now that the extension is installed, sync request should fail
6180 // because the extension is already installed.
6181 ASSERT_FALSE(AddPendingSyncInstall());
6182}
6183
6184// Test that installing an external extension displays a GlobalError.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006185TEST_F(ExtensionServiceTest, ExternalInstallGlobalError) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006186 FeatureSwitch::ScopedOverride prompt(
6187 FeatureSwitch::prompt_for_external_extensions(), true);
6188
6189 InitializeEmptyExtensionService();
6190 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006191 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006192 AddMockExternalProvider(provider);
6193
6194 service_->UpdateExternalExtensionAlert();
6195 // Should return false, meaning there aren't any extensions that the user
6196 // needs to know about.
6197 EXPECT_FALSE(extensions::HasExternalInstallError(service_));
6198
6199 // This is a normal extension, installed normally.
6200 // This should NOT trigger an alert.
6201 set_extensions_enabled(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006202 base::FilePath path = data_dir_.AppendASCII("good.crx");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006203 InstallCRX(path, INSTALL_NEW);
6204
6205 service_->CheckForExternalUpdates();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006206 loop_.RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006207 EXPECT_FALSE(extensions::HasExternalInstallError(service_));
6208
6209 // A hosted app, installed externally.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006210 // This should NOT trigger an alert.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006211 provider->UpdateOrAddExtension(hosted_app, "1.0.0.0",
6212 data_dir_.AppendASCII("hosted_app.crx"));
6213
6214 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006215 content::WindowedNotificationObserver(
6216 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6217 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006218 EXPECT_FALSE(extensions::HasExternalInstallError(service_));
6219
6220 // Another normal extension, but installed externally.
6221 // This SHOULD trigger an alert.
6222 provider->UpdateOrAddExtension(page_action, "1.0.0.0",
6223 data_dir_.AppendASCII("page_action.crx"));
6224
6225 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006226 content::WindowedNotificationObserver(
6227 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6228 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006229 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
6230}
6231
6232// Test that external extensions are initially disabled, and that enabling
6233// them clears the prompt.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006234TEST_F(ExtensionServiceTest, ExternalInstallInitiallyDisabled) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006235 FeatureSwitch::ScopedOverride prompt(
6236 FeatureSwitch::prompt_for_external_extensions(), true);
6237
6238 InitializeEmptyExtensionService();
6239 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006240 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006241 AddMockExternalProvider(provider);
6242
6243 provider->UpdateOrAddExtension(page_action, "1.0.0.0",
6244 data_dir_.AppendASCII("page_action.crx"));
6245
6246 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006247 content::WindowedNotificationObserver(
6248 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6249 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006250 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
6251 EXPECT_FALSE(service_->IsExtensionEnabled(page_action));
6252
6253 const Extension* extension =
6254 service_->disabled_extensions()->GetByID(page_action);
6255 EXPECT_TRUE(extension);
6256 EXPECT_EQ(page_action, extension->id());
6257
6258 service_->EnableExtension(page_action);
6259 EXPECT_FALSE(extensions::HasExternalInstallError(service_));
6260 EXPECT_TRUE(service_->IsExtensionEnabled(page_action));
6261}
6262
6263// Test that installing multiple external extensions works.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006264TEST_F(ExtensionServiceTest, ExternalInstallMultiple) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006265 FeatureSwitch::ScopedOverride prompt(
6266 FeatureSwitch::prompt_for_external_extensions(), true);
6267
6268 InitializeEmptyExtensionService();
6269 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006270 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006271 AddMockExternalProvider(provider);
6272
6273 provider->UpdateOrAddExtension(page_action, "1.0.0.0",
6274 data_dir_.AppendASCII("page_action.crx"));
6275 provider->UpdateOrAddExtension(good_crx, "1.0.0.0",
6276 data_dir_.AppendASCII("good.crx"));
6277 provider->UpdateOrAddExtension(theme_crx, "2.0",
6278 data_dir_.AppendASCII("theme.crx"));
6279
6280 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006281 int count = 3;
6282 content::WindowedNotificationObserver(
6283 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6284 base::Bind(&WaitForCountNotificationsCallback, &count)).Wait();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006285 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
6286 EXPECT_FALSE(service_->IsExtensionEnabled(page_action));
6287 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
6288 EXPECT_FALSE(service_->IsExtensionEnabled(theme_crx));
6289
6290 service_->EnableExtension(page_action);
6291 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006292 EXPECT_FALSE(extensions::HasExternalInstallBubble(service_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006293 service_->EnableExtension(theme_crx);
6294 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006295 EXPECT_FALSE(extensions::HasExternalInstallBubble(service_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006296 service_->EnableExtension(good_crx);
6297 EXPECT_FALSE(extensions::HasExternalInstallError(service_));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006298 EXPECT_FALSE(extensions::HasExternalInstallBubble(service_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006299}
6300
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006301// Test that there is a bubble for external extensions that update
6302// from the webstore if the profile is not new.
6303TEST_F(ExtensionServiceTest, ExternalInstallUpdatesFromWebstoreOldProfile) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006304 FeatureSwitch::ScopedOverride prompt(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006305 FeatureSwitch::prompt_for_external_extensions(), true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006306
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006307 // This sets up the ExtensionPrefs used by our ExtensionService to be
6308 // post-first run.
6309 InitializeExtensionServiceHelper(false, false);
6310
6311 base::FilePath crx_path = temp_dir_.path().AppendASCII("webstore.crx");
6312 PackCRX(data_dir_.AppendASCII("update_from_webstore"),
6313 data_dir_.AppendASCII("update_from_webstore.pem"),
6314 crx_path);
6315
6316 MockExtensionProvider* provider =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006317 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006318 AddMockExternalProvider(provider);
6319 provider->UpdateOrAddExtension(updates_from_webstore, "1", crx_path);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006320
6321 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006322 content::WindowedNotificationObserver(
6323 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6324 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006325 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
6326 EXPECT_TRUE(extensions::HasExternalInstallBubble(service_));
6327 EXPECT_FALSE(service_->IsExtensionEnabled(updates_from_webstore));
6328}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006329
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006330// Test that there is no bubble for external extensions if the profile is new.
6331TEST_F(ExtensionServiceTest, ExternalInstallUpdatesFromWebstoreNewProfile) {
6332 FeatureSwitch::ScopedOverride prompt(
6333 FeatureSwitch::prompt_for_external_extensions(), true);
6334
6335 InitializeEmptyExtensionService();
6336
6337 base::FilePath crx_path = temp_dir_.path().AppendASCII("webstore.crx");
6338 PackCRX(data_dir_.AppendASCII("update_from_webstore"),
6339 data_dir_.AppendASCII("update_from_webstore.pem"),
6340 crx_path);
6341
6342 MockExtensionProvider* provider =
6343 new MockExtensionProvider(service_, Manifest::EXTERNAL_PREF);
6344 AddMockExternalProvider(provider);
6345 provider->UpdateOrAddExtension(updates_from_webstore, "1", crx_path);
6346
6347 service_->CheckForExternalUpdates();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006348 content::WindowedNotificationObserver(
6349 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
6350 content::NotificationService::AllSources()).Wait();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006351 EXPECT_TRUE(extensions::HasExternalInstallError(service_));
6352 EXPECT_FALSE(extensions::HasExternalInstallBubble(service_));
6353 EXPECT_FALSE(service_->IsExtensionEnabled(updates_from_webstore));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006354}
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01006355
6356TEST_F(ExtensionServiceTest, InstallBlacklistedExtension) {
6357 InitializeEmptyExtensionService();
6358
6359 scoped_refptr<Extension> extension = extensions::ExtensionBuilder()
6360 .SetManifest(extensions::DictionaryBuilder()
6361 .Set("name", "extension")
6362 .Set("version", "1.0")
6363 .Set("manifest_version", 2).Build())
6364 .Build();
6365 ASSERT_TRUE(extension.get());
6366 const std::string& id = extension->id();
6367
6368 std::set<std::string> id_set;
6369 id_set.insert(id);
6370 extensions::ExtensionNotificationObserver notifications(
6371 content::NotificationService::AllSources(), id_set);
6372
6373 // Installation should be allowed but the extension should never have been
6374 // loaded and it should be blacklisted in prefs.
6375 service_->OnExtensionInstalled(
6376 extension.get(),
6377 syncer::StringOrdinal(),
6378 false /* has requirement errors */,
6379 extensions::Blacklist::BLACKLISTED,
6380 false /* wait for idle */);
6381 loop_.RunUntilIdle();
6382
6383 // Extension was installed but not loaded.
6384 EXPECT_TRUE(notifications.CheckNotifications(
6385 chrome::NOTIFICATION_EXTENSION_INSTALLED));
6386
6387 EXPECT_TRUE(service_->GetInstalledExtension(id));
6388 EXPECT_FALSE(service_->extensions()->Contains(id));
6389 EXPECT_TRUE(service_->blacklisted_extensions()->Contains(id));
6390 EXPECT_TRUE(service_->extension_prefs()->IsExtensionBlacklisted(id));
6391 EXPECT_TRUE(
6392 service_->extension_prefs()->IsBlacklistedExtensionAcknowledged(id));
6393}